Squashed commit upgrading to mbedtls-3.4.0

Squash merging branch import/mbedtls-3.4.0

8225713449d3 ("libmbedtls: fix unrecognized compiler option")
f03730842d7b ("core: ltc: configure internal MD5")
2b0d0c50127c ("core: ltc: configure internal SHA-1 and SHA-224")
0e48a6e17630 ("libmedtls: core: update to mbedTLS 3.4.0 API")
049882b143af ("libutee: update to mbedTLS 3.4.0 API")
982307bf6169 ("core: LTC mpi_desc.c: update to mbedTLS 3.4.0 API")
33218e9eff7b ("ta: pkcs11: update to mbedTLS 3.4.0 API")
6956420cc064 ("libmbedtls: fix cipher_wrap.c for NIST AES Key Wrap mode")
ad67ef0b43fd ("libmbedtls: fix cipher_wrap.c for chacha20 and chachapoly")
7300f4d97bbf ("libmbedtls: add fault mitigation in mbedtls_rsa_rsassa_pkcs1_v15_verify()")
cec89b62a86d ("libmbedtls: add fault mitigation in mbedtls_rsa_rsassa_pss_verify_ext()")
e7e048796c44 ("libmbedtls: add SM2 curve")
096beff2cd31 ("libmbedtls: mbedtls_mpi_exp_mod(): optimize mempool usage")
7108668efd3f ("libmbedtls: mbedtls_mpi_exp_mod(): reduce stack usage")
0ba4eb8d0572 ("libmbedtls: mbedtls_mpi_exp_mod() initialize W")
3fd6ecf00382 ("libmbedtls: fix no CRT issue")
d5ea7e9e9aa7 ("libmbedtls: add interfaces in mbedtls for context memory operation")
2b0fb3f1fa3d ("libmedtls: mpi_miller_rabin: increase count limit")
2c3301ab99bb ("libmbedtls: add mbedtls_mpi_init_mempool()")
9a111f0da04b ("libmbedtls: make mbedtls_mpi_mont*() available")
804fe3a374f5 ("mbedtls: configure mbedtls to reach for config")
b28a41531427 ("mbedtls: remove default include/mbedtls/config.h")
dfafe507bbef ("Import mbedtls-3.4.0")

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Acked-by: Jerome Forissier <jerome.forissier@linaro.org>
Tested-by: Jerome Forissier <jerome.forissier@linaro.org> (vexpress-qemu_armv8a)
diff --git a/lib/libmbedtls/mbedtls/library/aes.c b/lib/libmbedtls/mbedtls/library/aes.c
index 03d8b7e..69da582 100644
--- a/lib/libmbedtls/mbedtls/library/aes.c
+++ b/lib/libmbedtls/mbedtls/library/aes.c
@@ -34,31 +34,20 @@
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 #if defined(MBEDTLS_PADLOCK_C)
-#include "mbedtls/padlock.h"
+#include "padlock.h"
 #endif
 #if defined(MBEDTLS_AESNI_C)
-#include "mbedtls/aesni.h"
+#include "aesni.h"
+#endif
+#if defined(MBEDTLS_AESCE_C)
+#include "aesce.h"
 #endif
 
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
 
 #if !defined(MBEDTLS_AES_ALT)
 
-/* Parameter validation macros based on platform_util.h */
-#define AES_VALIDATE_RET( cond )    \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_AES_BAD_INPUT_DATA )
-#define AES_VALIDATE( cond )        \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
-
-#if defined(MBEDTLS_PADLOCK_C) &&                      \
-    ( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) )
+#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
 static int aes_padlock_ace = -1;
 #endif
 
@@ -107,86 +96,86 @@
  */
 #define FT \
 \
-    V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \
-    V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \
-    V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \
-    V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \
-    V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \
-    V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \
-    V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \
-    V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \
-    V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \
-    V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \
-    V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \
-    V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \
-    V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \
-    V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \
-    V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \
-    V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \
-    V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \
-    V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \
-    V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \
-    V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \
-    V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \
-    V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \
-    V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \
-    V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \
-    V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \
-    V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \
-    V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \
-    V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \
-    V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \
-    V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \
-    V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \
-    V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \
-    V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \
-    V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \
-    V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \
-    V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \
-    V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \
-    V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \
-    V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \
-    V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \
-    V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \
-    V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \
-    V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \
-    V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \
-    V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \
-    V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \
-    V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \
-    V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \
-    V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \
-    V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \
-    V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \
-    V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \
-    V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \
-    V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \
-    V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \
-    V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \
-    V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \
-    V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \
-    V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \
-    V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \
-    V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \
-    V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \
-    V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \
-    V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C)
+    V(A5, 63, 63, C6), V(84, 7C, 7C, F8), V(99, 77, 77, EE), V(8D, 7B, 7B, F6), \
+    V(0D, F2, F2, FF), V(BD, 6B, 6B, D6), V(B1, 6F, 6F, DE), V(54, C5, C5, 91), \
+    V(50, 30, 30, 60), V(03, 01, 01, 02), V(A9, 67, 67, CE), V(7D, 2B, 2B, 56), \
+    V(19, FE, FE, E7), V(62, D7, D7, B5), V(E6, AB, AB, 4D), V(9A, 76, 76, EC), \
+    V(45, CA, CA, 8F), V(9D, 82, 82, 1F), V(40, C9, C9, 89), V(87, 7D, 7D, FA), \
+    V(15, FA, FA, EF), V(EB, 59, 59, B2), V(C9, 47, 47, 8E), V(0B, F0, F0, FB), \
+    V(EC, AD, AD, 41), V(67, D4, D4, B3), V(FD, A2, A2, 5F), V(EA, AF, AF, 45), \
+    V(BF, 9C, 9C, 23), V(F7, A4, A4, 53), V(96, 72, 72, E4), V(5B, C0, C0, 9B), \
+    V(C2, B7, B7, 75), V(1C, FD, FD, E1), V(AE, 93, 93, 3D), V(6A, 26, 26, 4C), \
+    V(5A, 36, 36, 6C), V(41, 3F, 3F, 7E), V(02, F7, F7, F5), V(4F, CC, CC, 83), \
+    V(5C, 34, 34, 68), V(F4, A5, A5, 51), V(34, E5, E5, D1), V(08, F1, F1, F9), \
+    V(93, 71, 71, E2), V(73, D8, D8, AB), V(53, 31, 31, 62), V(3F, 15, 15, 2A), \
+    V(0C, 04, 04, 08), V(52, C7, C7, 95), V(65, 23, 23, 46), V(5E, C3, C3, 9D), \
+    V(28, 18, 18, 30), V(A1, 96, 96, 37), V(0F, 05, 05, 0A), V(B5, 9A, 9A, 2F), \
+    V(09, 07, 07, 0E), V(36, 12, 12, 24), V(9B, 80, 80, 1B), V(3D, E2, E2, DF), \
+    V(26, EB, EB, CD), V(69, 27, 27, 4E), V(CD, B2, B2, 7F), V(9F, 75, 75, EA), \
+    V(1B, 09, 09, 12), V(9E, 83, 83, 1D), V(74, 2C, 2C, 58), V(2E, 1A, 1A, 34), \
+    V(2D, 1B, 1B, 36), V(B2, 6E, 6E, DC), V(EE, 5A, 5A, B4), V(FB, A0, A0, 5B), \
+    V(F6, 52, 52, A4), V(4D, 3B, 3B, 76), V(61, D6, D6, B7), V(CE, B3, B3, 7D), \
+    V(7B, 29, 29, 52), V(3E, E3, E3, DD), V(71, 2F, 2F, 5E), V(97, 84, 84, 13), \
+    V(F5, 53, 53, A6), V(68, D1, D1, B9), V(00, 00, 00, 00), V(2C, ED, ED, C1), \
+    V(60, 20, 20, 40), V(1F, FC, FC, E3), V(C8, B1, B1, 79), V(ED, 5B, 5B, B6), \
+    V(BE, 6A, 6A, D4), V(46, CB, CB, 8D), V(D9, BE, BE, 67), V(4B, 39, 39, 72), \
+    V(DE, 4A, 4A, 94), V(D4, 4C, 4C, 98), V(E8, 58, 58, B0), V(4A, CF, CF, 85), \
+    V(6B, D0, D0, BB), V(2A, EF, EF, C5), V(E5, AA, AA, 4F), V(16, FB, FB, ED), \
+    V(C5, 43, 43, 86), V(D7, 4D, 4D, 9A), V(55, 33, 33, 66), V(94, 85, 85, 11), \
+    V(CF, 45, 45, 8A), V(10, F9, F9, E9), V(06, 02, 02, 04), V(81, 7F, 7F, FE), \
+    V(F0, 50, 50, A0), V(44, 3C, 3C, 78), V(BA, 9F, 9F, 25), V(E3, A8, A8, 4B), \
+    V(F3, 51, 51, A2), V(FE, A3, A3, 5D), V(C0, 40, 40, 80), V(8A, 8F, 8F, 05), \
+    V(AD, 92, 92, 3F), V(BC, 9D, 9D, 21), V(48, 38, 38, 70), V(04, F5, F5, F1), \
+    V(DF, BC, BC, 63), V(C1, B6, B6, 77), V(75, DA, DA, AF), V(63, 21, 21, 42), \
+    V(30, 10, 10, 20), V(1A, FF, FF, E5), V(0E, F3, F3, FD), V(6D, D2, D2, BF), \
+    V(4C, CD, CD, 81), V(14, 0C, 0C, 18), V(35, 13, 13, 26), V(2F, EC, EC, C3), \
+    V(E1, 5F, 5F, BE), V(A2, 97, 97, 35), V(CC, 44, 44, 88), V(39, 17, 17, 2E), \
+    V(57, C4, C4, 93), V(F2, A7, A7, 55), V(82, 7E, 7E, FC), V(47, 3D, 3D, 7A), \
+    V(AC, 64, 64, C8), V(E7, 5D, 5D, BA), V(2B, 19, 19, 32), V(95, 73, 73, E6), \
+    V(A0, 60, 60, C0), V(98, 81, 81, 19), V(D1, 4F, 4F, 9E), V(7F, DC, DC, A3), \
+    V(66, 22, 22, 44), V(7E, 2A, 2A, 54), V(AB, 90, 90, 3B), V(83, 88, 88, 0B), \
+    V(CA, 46, 46, 8C), V(29, EE, EE, C7), V(D3, B8, B8, 6B), V(3C, 14, 14, 28), \
+    V(79, DE, DE, A7), V(E2, 5E, 5E, BC), V(1D, 0B, 0B, 16), V(76, DB, DB, AD), \
+    V(3B, E0, E0, DB), V(56, 32, 32, 64), V(4E, 3A, 3A, 74), V(1E, 0A, 0A, 14), \
+    V(DB, 49, 49, 92), V(0A, 06, 06, 0C), V(6C, 24, 24, 48), V(E4, 5C, 5C, B8), \
+    V(5D, C2, C2, 9F), V(6E, D3, D3, BD), V(EF, AC, AC, 43), V(A6, 62, 62, C4), \
+    V(A8, 91, 91, 39), V(A4, 95, 95, 31), V(37, E4, E4, D3), V(8B, 79, 79, F2), \
+    V(32, E7, E7, D5), V(43, C8, C8, 8B), V(59, 37, 37, 6E), V(B7, 6D, 6D, DA), \
+    V(8C, 8D, 8D, 01), V(64, D5, D5, B1), V(D2, 4E, 4E, 9C), V(E0, A9, A9, 49), \
+    V(B4, 6C, 6C, D8), V(FA, 56, 56, AC), V(07, F4, F4, F3), V(25, EA, EA, CF), \
+    V(AF, 65, 65, CA), V(8E, 7A, 7A, F4), V(E9, AE, AE, 47), V(18, 08, 08, 10), \
+    V(D5, BA, BA, 6F), V(88, 78, 78, F0), V(6F, 25, 25, 4A), V(72, 2E, 2E, 5C), \
+    V(24, 1C, 1C, 38), V(F1, A6, A6, 57), V(C7, B4, B4, 73), V(51, C6, C6, 97), \
+    V(23, E8, E8, CB), V(7C, DD, DD, A1), V(9C, 74, 74, E8), V(21, 1F, 1F, 3E), \
+    V(DD, 4B, 4B, 96), V(DC, BD, BD, 61), V(86, 8B, 8B, 0D), V(85, 8A, 8A, 0F), \
+    V(90, 70, 70, E0), V(42, 3E, 3E, 7C), V(C4, B5, B5, 71), V(AA, 66, 66, CC), \
+    V(D8, 48, 48, 90), V(05, 03, 03, 06), V(01, F6, F6, F7), V(12, 0E, 0E, 1C), \
+    V(A3, 61, 61, C2), V(5F, 35, 35, 6A), V(F9, 57, 57, AE), V(D0, B9, B9, 69), \
+    V(91, 86, 86, 17), V(58, C1, C1, 99), V(27, 1D, 1D, 3A), V(B9, 9E, 9E, 27), \
+    V(38, E1, E1, D9), V(13, F8, F8, EB), V(B3, 98, 98, 2B), V(33, 11, 11, 22), \
+    V(BB, 69, 69, D2), V(70, D9, D9, A9), V(89, 8E, 8E, 07), V(A7, 94, 94, 33), \
+    V(B6, 9B, 9B, 2D), V(22, 1E, 1E, 3C), V(92, 87, 87, 15), V(20, E9, E9, C9), \
+    V(49, CE, CE, 87), V(FF, 55, 55, AA), V(78, 28, 28, 50), V(7A, DF, DF, A5), \
+    V(8F, 8C, 8C, 03), V(F8, A1, A1, 59), V(80, 89, 89, 09), V(17, 0D, 0D, 1A), \
+    V(DA, BF, BF, 65), V(31, E6, E6, D7), V(C6, 42, 42, 84), V(B8, 68, 68, D0), \
+    V(C3, 41, 41, 82), V(B0, 99, 99, 29), V(77, 2D, 2D, 5A), V(11, 0F, 0F, 1E), \
+    V(CB, B0, B0, 7B), V(FC, 54, 54, A8), V(D6, BB, BB, 6D), V(3A, 16, 16, 2C)
 
-#define V(a,b,c,d) 0x##a##b##c##d
+#define V(a, b, c, d) 0x##a##b##c##d
 static const uint32_t FT0[256] = { FT };
 #undef V
 
 #if !defined(MBEDTLS_AES_FEWER_TABLES)
 
-#define V(a,b,c,d) 0x##b##c##d##a
+#define V(a, b, c, d) 0x##b##c##d##a
 static const uint32_t FT1[256] = { FT };
 #undef V
 
-#define V(a,b,c,d) 0x##c##d##a##b
+#define V(a, b, c, d) 0x##c##d##a##b
 static const uint32_t FT2[256] = { FT };
 #undef V
 
-#define V(a,b,c,d) 0x##d##a##b##c
+#define V(a, b, c, d) 0x##d##a##b##c
 static const uint32_t FT3[256] = { FT };
 #undef V
 
@@ -238,86 +227,86 @@
  */
 #define RT \
 \
-    V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \
-    V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \
-    V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \
-    V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \
-    V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \
-    V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \
-    V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \
-    V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \
-    V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \
-    V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \
-    V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \
-    V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \
-    V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \
-    V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \
-    V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \
-    V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \
-    V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \
-    V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \
-    V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \
-    V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \
-    V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \
-    V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \
-    V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \
-    V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \
-    V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \
-    V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \
-    V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \
-    V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \
-    V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \
-    V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \
-    V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \
-    V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \
-    V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \
-    V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \
-    V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \
-    V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \
-    V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \
-    V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \
-    V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \
-    V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \
-    V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \
-    V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \
-    V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \
-    V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \
-    V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \
-    V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \
-    V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \
-    V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \
-    V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \
-    V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \
-    V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \
-    V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \
-    V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \
-    V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \
-    V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \
-    V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \
-    V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \
-    V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \
-    V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \
-    V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \
-    V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \
-    V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \
-    V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \
-    V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0)
+    V(50, A7, F4, 51), V(53, 65, 41, 7E), V(C3, A4, 17, 1A), V(96, 5E, 27, 3A), \
+    V(CB, 6B, AB, 3B), V(F1, 45, 9D, 1F), V(AB, 58, FA, AC), V(93, 03, E3, 4B), \
+    V(55, FA, 30, 20), V(F6, 6D, 76, AD), V(91, 76, CC, 88), V(25, 4C, 02, F5), \
+    V(FC, D7, E5, 4F), V(D7, CB, 2A, C5), V(80, 44, 35, 26), V(8F, A3, 62, B5), \
+    V(49, 5A, B1, DE), V(67, 1B, BA, 25), V(98, 0E, EA, 45), V(E1, C0, FE, 5D), \
+    V(02, 75, 2F, C3), V(12, F0, 4C, 81), V(A3, 97, 46, 8D), V(C6, F9, D3, 6B), \
+    V(E7, 5F, 8F, 03), V(95, 9C, 92, 15), V(EB, 7A, 6D, BF), V(DA, 59, 52, 95), \
+    V(2D, 83, BE, D4), V(D3, 21, 74, 58), V(29, 69, E0, 49), V(44, C8, C9, 8E), \
+    V(6A, 89, C2, 75), V(78, 79, 8E, F4), V(6B, 3E, 58, 99), V(DD, 71, B9, 27), \
+    V(B6, 4F, E1, BE), V(17, AD, 88, F0), V(66, AC, 20, C9), V(B4, 3A, CE, 7D), \
+    V(18, 4A, DF, 63), V(82, 31, 1A, E5), V(60, 33, 51, 97), V(45, 7F, 53, 62), \
+    V(E0, 77, 64, B1), V(84, AE, 6B, BB), V(1C, A0, 81, FE), V(94, 2B, 08, F9), \
+    V(58, 68, 48, 70), V(19, FD, 45, 8F), V(87, 6C, DE, 94), V(B7, F8, 7B, 52), \
+    V(23, D3, 73, AB), V(E2, 02, 4B, 72), V(57, 8F, 1F, E3), V(2A, AB, 55, 66), \
+    V(07, 28, EB, B2), V(03, C2, B5, 2F), V(9A, 7B, C5, 86), V(A5, 08, 37, D3), \
+    V(F2, 87, 28, 30), V(B2, A5, BF, 23), V(BA, 6A, 03, 02), V(5C, 82, 16, ED), \
+    V(2B, 1C, CF, 8A), V(92, B4, 79, A7), V(F0, F2, 07, F3), V(A1, E2, 69, 4E), \
+    V(CD, F4, DA, 65), V(D5, BE, 05, 06), V(1F, 62, 34, D1), V(8A, FE, A6, C4), \
+    V(9D, 53, 2E, 34), V(A0, 55, F3, A2), V(32, E1, 8A, 05), V(75, EB, F6, A4), \
+    V(39, EC, 83, 0B), V(AA, EF, 60, 40), V(06, 9F, 71, 5E), V(51, 10, 6E, BD), \
+    V(F9, 8A, 21, 3E), V(3D, 06, DD, 96), V(AE, 05, 3E, DD), V(46, BD, E6, 4D), \
+    V(B5, 8D, 54, 91), V(05, 5D, C4, 71), V(6F, D4, 06, 04), V(FF, 15, 50, 60), \
+    V(24, FB, 98, 19), V(97, E9, BD, D6), V(CC, 43, 40, 89), V(77, 9E, D9, 67), \
+    V(BD, 42, E8, B0), V(88, 8B, 89, 07), V(38, 5B, 19, E7), V(DB, EE, C8, 79), \
+    V(47, 0A, 7C, A1), V(E9, 0F, 42, 7C), V(C9, 1E, 84, F8), V(00, 00, 00, 00), \
+    V(83, 86, 80, 09), V(48, ED, 2B, 32), V(AC, 70, 11, 1E), V(4E, 72, 5A, 6C), \
+    V(FB, FF, 0E, FD), V(56, 38, 85, 0F), V(1E, D5, AE, 3D), V(27, 39, 2D, 36), \
+    V(64, D9, 0F, 0A), V(21, A6, 5C, 68), V(D1, 54, 5B, 9B), V(3A, 2E, 36, 24), \
+    V(B1, 67, 0A, 0C), V(0F, E7, 57, 93), V(D2, 96, EE, B4), V(9E, 91, 9B, 1B), \
+    V(4F, C5, C0, 80), V(A2, 20, DC, 61), V(69, 4B, 77, 5A), V(16, 1A, 12, 1C), \
+    V(0A, BA, 93, E2), V(E5, 2A, A0, C0), V(43, E0, 22, 3C), V(1D, 17, 1B, 12), \
+    V(0B, 0D, 09, 0E), V(AD, C7, 8B, F2), V(B9, A8, B6, 2D), V(C8, A9, 1E, 14), \
+    V(85, 19, F1, 57), V(4C, 07, 75, AF), V(BB, DD, 99, EE), V(FD, 60, 7F, A3), \
+    V(9F, 26, 01, F7), V(BC, F5, 72, 5C), V(C5, 3B, 66, 44), V(34, 7E, FB, 5B), \
+    V(76, 29, 43, 8B), V(DC, C6, 23, CB), V(68, FC, ED, B6), V(63, F1, E4, B8), \
+    V(CA, DC, 31, D7), V(10, 85, 63, 42), V(40, 22, 97, 13), V(20, 11, C6, 84), \
+    V(7D, 24, 4A, 85), V(F8, 3D, BB, D2), V(11, 32, F9, AE), V(6D, A1, 29, C7), \
+    V(4B, 2F, 9E, 1D), V(F3, 30, B2, DC), V(EC, 52, 86, 0D), V(D0, E3, C1, 77), \
+    V(6C, 16, B3, 2B), V(99, B9, 70, A9), V(FA, 48, 94, 11), V(22, 64, E9, 47), \
+    V(C4, 8C, FC, A8), V(1A, 3F, F0, A0), V(D8, 2C, 7D, 56), V(EF, 90, 33, 22), \
+    V(C7, 4E, 49, 87), V(C1, D1, 38, D9), V(FE, A2, CA, 8C), V(36, 0B, D4, 98), \
+    V(CF, 81, F5, A6), V(28, DE, 7A, A5), V(26, 8E, B7, DA), V(A4, BF, AD, 3F), \
+    V(E4, 9D, 3A, 2C), V(0D, 92, 78, 50), V(9B, CC, 5F, 6A), V(62, 46, 7E, 54), \
+    V(C2, 13, 8D, F6), V(E8, B8, D8, 90), V(5E, F7, 39, 2E), V(F5, AF, C3, 82), \
+    V(BE, 80, 5D, 9F), V(7C, 93, D0, 69), V(A9, 2D, D5, 6F), V(B3, 12, 25, CF), \
+    V(3B, 99, AC, C8), V(A7, 7D, 18, 10), V(6E, 63, 9C, E8), V(7B, BB, 3B, DB), \
+    V(09, 78, 26, CD), V(F4, 18, 59, 6E), V(01, B7, 9A, EC), V(A8, 9A, 4F, 83), \
+    V(65, 6E, 95, E6), V(7E, E6, FF, AA), V(08, CF, BC, 21), V(E6, E8, 15, EF), \
+    V(D9, 9B, E7, BA), V(CE, 36, 6F, 4A), V(D4, 09, 9F, EA), V(D6, 7C, B0, 29), \
+    V(AF, B2, A4, 31), V(31, 23, 3F, 2A), V(30, 94, A5, C6), V(C0, 66, A2, 35), \
+    V(37, BC, 4E, 74), V(A6, CA, 82, FC), V(B0, D0, 90, E0), V(15, D8, A7, 33), \
+    V(4A, 98, 04, F1), V(F7, DA, EC, 41), V(0E, 50, CD, 7F), V(2F, F6, 91, 17), \
+    V(8D, D6, 4D, 76), V(4D, B0, EF, 43), V(54, 4D, AA, CC), V(DF, 04, 96, E4), \
+    V(E3, B5, D1, 9E), V(1B, 88, 6A, 4C), V(B8, 1F, 2C, C1), V(7F, 51, 65, 46), \
+    V(04, EA, 5E, 9D), V(5D, 35, 8C, 01), V(73, 74, 87, FA), V(2E, 41, 0B, FB), \
+    V(5A, 1D, 67, B3), V(52, D2, DB, 92), V(33, 56, 10, E9), V(13, 47, D6, 6D), \
+    V(8C, 61, D7, 9A), V(7A, 0C, A1, 37), V(8E, 14, F8, 59), V(89, 3C, 13, EB), \
+    V(EE, 27, A9, CE), V(35, C9, 61, B7), V(ED, E5, 1C, E1), V(3C, B1, 47, 7A), \
+    V(59, DF, D2, 9C), V(3F, 73, F2, 55), V(79, CE, 14, 18), V(BF, 37, C7, 73), \
+    V(EA, CD, F7, 53), V(5B, AA, FD, 5F), V(14, 6F, 3D, DF), V(86, DB, 44, 78), \
+    V(81, F3, AF, CA), V(3E, C4, 68, B9), V(2C, 34, 24, 38), V(5F, 40, A3, C2), \
+    V(72, C3, 1D, 16), V(0C, 25, E2, BC), V(8B, 49, 3C, 28), V(41, 95, 0D, FF), \
+    V(71, 01, A8, 39), V(DE, B3, 0C, 08), V(9C, E4, B4, D8), V(90, C1, 56, 64), \
+    V(61, 84, CB, 7B), V(70, B6, 32, D5), V(74, 5C, 6C, 48), V(42, 57, B8, D0)
 
-#define V(a,b,c,d) 0x##a##b##c##d
+#define V(a, b, c, d) 0x##a##b##c##d
 static const uint32_t RT0[256] = { RT };
 #undef V
 
 #if !defined(MBEDTLS_AES_FEWER_TABLES)
 
-#define V(a,b,c,d) 0x##b##c##d##a
+#define V(a, b, c, d) 0x##b##c##d##a
 static const uint32_t RT1[256] = { RT };
 #undef V
 
-#define V(a,b,c,d) 0x##c##d##a##b
+#define V(a, b, c, d) 0x##c##d##a##b
 static const uint32_t RT2[256] = { RT };
 #undef V
 
-#define V(a,b,c,d) 0x##d##a##b##c
+#define V(a, b, c, d) 0x##d##a##b##c
 static const uint32_t RT3[256] = { RT };
 #undef V
 
@@ -367,13 +356,13 @@
 /*
  * Tables generation code
  */
-#define ROTL8(x) ( ( (x) << 8 ) & 0xFFFFFFFF ) | ( (x) >> 24 )
-#define XTIME(x) ( ( (x) << 1 ) ^ ( ( (x) & 0x80 ) ? 0x1B : 0x00 ) )
-#define MUL(x,y) ( ( (x) && (y) ) ? pow[(log[(x)]+log[(y)]) % 255] : 0 )
+#define ROTL8(x) (((x) << 8) & 0xFFFFFFFF) | ((x) >> 24)
+#define XTIME(x) (((x) << 1) ^ (((x) & 0x80) ? 0x1B : 0x00))
+#define MUL(x, y) (((x) && (y)) ? pow[(log[(x)]+log[(y)]) % 255] : 0)
 
 static int aes_init_done = 0;
 
-static void aes_gen_tables( void )
+static void aes_gen_tables(void)
 {
     int i, x, y, z;
     int pow[256];
@@ -382,20 +371,18 @@
     /*
      * compute pow and log tables over GF(2^8)
      */
-    for( i = 0, x = 1; i < 256; i++ )
-    {
+    for (i = 0, x = 1; i < 256; i++) {
         pow[i] = x;
         log[x] = i;
-        x = MBEDTLS_BYTE_0( x ^ XTIME( x ) );
+        x = MBEDTLS_BYTE_0(x ^ XTIME(x));
     }
 
     /*
      * calculate the round constants
      */
-    for( i = 0, x = 1; i < 10; i++ )
-    {
+    for (i = 0, x = 1; i < 10; i++) {
         RCON[i] = (uint32_t) x;
-        x = MBEDTLS_BYTE_0( XTIME( x ) );
+        x = MBEDTLS_BYTE_0(XTIME(x));
     }
 
     /*
@@ -404,14 +391,13 @@
     FSb[0x00] = 0x63;
     RSb[0x63] = 0x00;
 
-    for( i = 1; i < 256; i++ )
-    {
+    for (i = 1; i < 256; i++) {
         x = pow[255 - log[i]];
 
-        y  = x; y = MBEDTLS_BYTE_0( ( y << 1 ) | ( y >> 7 ) );
-        x ^= y; y = MBEDTLS_BYTE_0( ( y << 1 ) | ( y >> 7 ) );
-        x ^= y; y = MBEDTLS_BYTE_0( ( y << 1 ) | ( y >> 7 ) );
-        x ^= y; y = MBEDTLS_BYTE_0( ( y << 1 ) | ( y >> 7 ) );
+        y  = x; y = MBEDTLS_BYTE_0((y << 1) | (y >> 7));
+        x ^= y; y = MBEDTLS_BYTE_0((y << 1) | (y >> 7));
+        x ^= y; y = MBEDTLS_BYTE_0((y << 1) | (y >> 7));
+        x ^= y; y = MBEDTLS_BYTE_0((y << 1) | (y >> 7));
         x ^= y ^ 0x63;
 
         FSb[i] = (unsigned char) x;
@@ -421,34 +407,33 @@
     /*
      * generate the forward and reverse tables
      */
-    for( i = 0; i < 256; i++ )
-    {
+    for (i = 0; i < 256; i++) {
         x = FSb[i];
-        y = MBEDTLS_BYTE_0( XTIME( x ) );
-        z = MBEDTLS_BYTE_0( y ^ x );
+        y = MBEDTLS_BYTE_0(XTIME(x));
+        z = MBEDTLS_BYTE_0(y ^ x);
 
-        FT0[i] = ( (uint32_t) y       ) ^
-                 ( (uint32_t) x <<  8 ) ^
-                 ( (uint32_t) x << 16 ) ^
-                 ( (uint32_t) z << 24 );
+        FT0[i] = ((uint32_t) y) ^
+                 ((uint32_t) x <<  8) ^
+                 ((uint32_t) x << 16) ^
+                 ((uint32_t) z << 24);
 
 #if !defined(MBEDTLS_AES_FEWER_TABLES)
-        FT1[i] = ROTL8( FT0[i] );
-        FT2[i] = ROTL8( FT1[i] );
-        FT3[i] = ROTL8( FT2[i] );
+        FT1[i] = ROTL8(FT0[i]);
+        FT2[i] = ROTL8(FT1[i]);
+        FT3[i] = ROTL8(FT2[i]);
 #endif /* !MBEDTLS_AES_FEWER_TABLES */
 
         x = RSb[i];
 
-        RT0[i] = ( (uint32_t) MUL( 0x0E, x )       ) ^
-                 ( (uint32_t) MUL( 0x09, x ) <<  8 ) ^
-                 ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^
-                 ( (uint32_t) MUL( 0x0B, x ) << 24 );
+        RT0[i] = ((uint32_t) MUL(0x0E, x)) ^
+                 ((uint32_t) MUL(0x09, x) <<  8) ^
+                 ((uint32_t) MUL(0x0D, x) << 16) ^
+                 ((uint32_t) MUL(0x0B, x) << 24);
 
 #if !defined(MBEDTLS_AES_FEWER_TABLES)
-        RT1[i] = ROTL8( RT0[i] );
-        RT2[i] = ROTL8( RT1[i] );
-        RT3[i] = ROTL8( RT2[i] );
+        RT1[i] = ROTL8(RT0[i]);
+        RT2[i] = ROTL8(RT1[i]);
+        RT3[i] = ROTL8(RT2[i]);
 #endif /* !MBEDTLS_AES_FEWER_TABLES */
     }
 }
@@ -459,19 +444,19 @@
 
 #if defined(MBEDTLS_AES_FEWER_TABLES)
 
-#define ROTL8(x)  ( (uint32_t)( ( x ) <<  8 ) + (uint32_t)( ( x ) >> 24 ) )
-#define ROTL16(x) ( (uint32_t)( ( x ) << 16 ) + (uint32_t)( ( x ) >> 16 ) )
-#define ROTL24(x) ( (uint32_t)( ( x ) << 24 ) + (uint32_t)( ( x ) >>  8 ) )
+#define ROTL8(x)  ((uint32_t) ((x) <<  8) + (uint32_t) ((x) >> 24))
+#define ROTL16(x) ((uint32_t) ((x) << 16) + (uint32_t) ((x) >> 16))
+#define ROTL24(x) ((uint32_t) ((x) << 24) + (uint32_t) ((x) >>  8))
 
 #define AES_RT0(idx) RT0[idx]
-#define AES_RT1(idx) ROTL8(  RT0[idx] )
-#define AES_RT2(idx) ROTL16( RT0[idx] )
-#define AES_RT3(idx) ROTL24( RT0[idx] )
+#define AES_RT1(idx) ROTL8(RT0[idx])
+#define AES_RT2(idx) ROTL16(RT0[idx])
+#define AES_RT3(idx) ROTL24(RT0[idx])
 
 #define AES_FT0(idx) FT0[idx]
-#define AES_FT1(idx) ROTL8(  FT0[idx] )
-#define AES_FT2(idx) ROTL16( FT0[idx] )
-#define AES_FT3(idx) ROTL24( FT0[idx] )
+#define AES_FT1(idx) ROTL8(FT0[idx])
+#define AES_FT2(idx) ROTL16(FT0[idx])
+#define AES_FT3(idx) ROTL24(FT0[idx])
 
 #else /* MBEDTLS_AES_FEWER_TABLES */
 
@@ -487,100 +472,137 @@
 
 #endif /* MBEDTLS_AES_FEWER_TABLES */
 
-void mbedtls_aes_init( mbedtls_aes_context *ctx )
+void mbedtls_aes_init(mbedtls_aes_context *ctx)
 {
-    AES_VALIDATE( ctx != NULL );
-
-    memset( ctx, 0, sizeof( mbedtls_aes_context ) );
+    memset(ctx, 0, sizeof(mbedtls_aes_context));
 }
 
-void mbedtls_aes_free( mbedtls_aes_context *ctx )
+void mbedtls_aes_free(mbedtls_aes_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_aes_context));
 }
 
 #if defined(MBEDTLS_CIPHER_MODE_XTS)
-void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx )
+void mbedtls_aes_xts_init(mbedtls_aes_xts_context *ctx)
 {
-    AES_VALIDATE( ctx != NULL );
-
-    mbedtls_aes_init( &ctx->crypt );
-    mbedtls_aes_init( &ctx->tweak );
+    mbedtls_aes_init(&ctx->crypt);
+    mbedtls_aes_init(&ctx->tweak);
 }
 
-void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx )
+void mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_aes_free( &ctx->crypt );
-    mbedtls_aes_free( &ctx->tweak );
+    mbedtls_aes_free(&ctx->crypt);
+    mbedtls_aes_free(&ctx->tweak);
 }
 #endif /* MBEDTLS_CIPHER_MODE_XTS */
 
+/* Some implementations need the round keys to be aligned.
+ * Return an offset to be added to buf, such that (buf + offset) is
+ * correctly aligned.
+ * Note that the offset is in units of elements of buf, i.e. 32-bit words,
+ * i.e. an offset of 1 means 4 bytes and so on.
+ */
+#if (defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)) ||        \
+    (defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2)
+#define MAY_NEED_TO_ALIGN
+#endif
+static unsigned mbedtls_aes_rk_offset(uint32_t *buf)
+{
+#if defined(MAY_NEED_TO_ALIGN)
+    int align_16_bytes = 0;
+
+#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
+    if (aes_padlock_ace == -1) {
+        aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE);
+    }
+    if (aes_padlock_ace) {
+        align_16_bytes = 1;
+    }
+#endif
+
+#if defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2
+    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {
+        align_16_bytes = 1;
+    }
+#endif
+
+    if (align_16_bytes) {
+        /* These implementations needs 16-byte alignment
+         * for the round key array. */
+        unsigned delta = ((uintptr_t) buf & 0x0000000fU) / 4;
+        if (delta == 0) {
+            return 0;
+        } else {
+            return 4 - delta; // 16 bytes = 4 uint32_t
+        }
+    }
+#else /* MAY_NEED_TO_ALIGN */
+    (void) buf;
+#endif /* MAY_NEED_TO_ALIGN */
+
+    return 0;
+}
+
 /*
  * AES key schedule (encryption)
  */
 #if !defined(MBEDTLS_AES_SETKEY_ENC_ALT)
-int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
-                    unsigned int keybits )
+int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
+                           unsigned int keybits)
 {
     unsigned int i;
     uint32_t *RK;
 
-    AES_VALIDATE_RET( ctx != NULL );
-    AES_VALIDATE_RET( key != NULL );
-
-    switch( keybits )
-    {
+    switch (keybits) {
         case 128: ctx->nr = 10; break;
         case 192: ctx->nr = 12; break;
         case 256: ctx->nr = 14; break;
-        default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
+        default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
     }
 
 #if !defined(MBEDTLS_AES_ROM_TABLES)
-    if( aes_init_done == 0 )
-    {
+    if (aes_init_done == 0) {
         aes_gen_tables();
         aes_init_done = 1;
     }
 #endif
 
-#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16)
-    if( aes_padlock_ace == -1 )
-        aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE );
+    ctx->rk_offset = mbedtls_aes_rk_offset(ctx->buf);
+    RK = ctx->buf + ctx->rk_offset;
 
-    if( aes_padlock_ace )
-        ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf );
-    else
-#endif
-    ctx->rk = RK = ctx->buf;
-
-#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
-    if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) )
-        return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) );
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
+    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {
+        return mbedtls_aesni_setkey_enc((unsigned char *) RK, key, keybits);
+    }
 #endif
 
-    for( i = 0; i < ( keybits >> 5 ); i++ )
-    {
-        RK[i] = MBEDTLS_GET_UINT32_LE( key, i << 2 );
+#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
+    if (mbedtls_aesce_has_support()) {
+        return mbedtls_aesce_setkey_enc((unsigned char *) RK, key, keybits);
+    }
+#endif
+
+    for (i = 0; i < (keybits >> 5); i++) {
+        RK[i] = MBEDTLS_GET_UINT32_LE(key, i << 2);
     }
 
-    switch( ctx->nr )
-    {
+    switch (ctx->nr) {
         case 10:
 
-            for( i = 0; i < 10; i++, RK += 4 )
-            {
+            for (i = 0; i < 10; i++, RK += 4) {
                 RK[4]  = RK[0] ^ RCON[i] ^
-                ( (uint32_t) FSb[ MBEDTLS_BYTE_1( RK[3] ) ]       ) ^
-                ( (uint32_t) FSb[ MBEDTLS_BYTE_2( RK[3] ) ] <<  8 ) ^
-                ( (uint32_t) FSb[ MBEDTLS_BYTE_3( RK[3] ) ] << 16 ) ^
-                ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[3] ) ] << 24 );
+                         ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[3])]) ^
+                         ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[3])] <<  8) ^
+                         ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[3])] << 16) ^
+                         ((uint32_t) FSb[MBEDTLS_BYTE_0(RK[3])] << 24);
 
                 RK[5]  = RK[1] ^ RK[4];
                 RK[6]  = RK[2] ^ RK[5];
@@ -590,13 +612,12 @@
 
         case 12:
 
-            for( i = 0; i < 8; i++, RK += 6 )
-            {
+            for (i = 0; i < 8; i++, RK += 6) {
                 RK[6]  = RK[0] ^ RCON[i] ^
-                ( (uint32_t) FSb[ MBEDTLS_BYTE_1( RK[5] ) ]       ) ^
-                ( (uint32_t) FSb[ MBEDTLS_BYTE_2( RK[5] ) ] <<  8 ) ^
-                ( (uint32_t) FSb[ MBEDTLS_BYTE_3( RK[5] ) ] << 16 ) ^
-                ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[5] ) ] << 24 );
+                         ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[5])]) ^
+                         ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[5])] <<  8) ^
+                         ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[5])] << 16) ^
+                         ((uint32_t) FSb[MBEDTLS_BYTE_0(RK[5])] << 24);
 
                 RK[7]  = RK[1] ^ RK[6];
                 RK[8]  = RK[2] ^ RK[7];
@@ -608,23 +629,22 @@
 
         case 14:
 
-            for( i = 0; i < 7; i++, RK += 8 )
-            {
+            for (i = 0; i < 7; i++, RK += 8) {
                 RK[8]  = RK[0] ^ RCON[i] ^
-                ( (uint32_t) FSb[ MBEDTLS_BYTE_1( RK[7] ) ]       ) ^
-                ( (uint32_t) FSb[ MBEDTLS_BYTE_2( RK[7] ) ] <<  8 ) ^
-                ( (uint32_t) FSb[ MBEDTLS_BYTE_3( RK[7] ) ] << 16 ) ^
-                ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[7] ) ] << 24 );
+                         ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[7])]) ^
+                         ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[7])] <<  8) ^
+                         ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[7])] << 16) ^
+                         ((uint32_t) FSb[MBEDTLS_BYTE_0(RK[7])] << 24);
 
                 RK[9]  = RK[1] ^ RK[8];
                 RK[10] = RK[2] ^ RK[9];
                 RK[11] = RK[3] ^ RK[10];
 
                 RK[12] = RK[4] ^
-                ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[11] ) ]       ) ^
-                ( (uint32_t) FSb[ MBEDTLS_BYTE_1( RK[11] ) ] <<  8 ) ^
-                ( (uint32_t) FSb[ MBEDTLS_BYTE_2( RK[11] ) ] << 16 ) ^
-                ( (uint32_t) FSb[ MBEDTLS_BYTE_3( RK[11] ) ] << 24 );
+                         ((uint32_t) FSb[MBEDTLS_BYTE_0(RK[11])]) ^
+                         ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[11])] <<  8) ^
+                         ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[11])] << 16) ^
+                         ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[11])] << 24);
 
                 RK[13] = RK[5] ^ RK[12];
                 RK[14] = RK[6] ^ RK[13];
@@ -633,7 +653,7 @@
             break;
     }
 
-    return( 0 );
+    return 0;
 }
 #endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */
 
@@ -641,59 +661,57 @@
  * AES key schedule (decryption)
  */
 #if !defined(MBEDTLS_AES_SETKEY_DEC_ALT)
-int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
-                    unsigned int keybits )
+int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
+                           unsigned int keybits)
 {
     int i, j, ret;
     mbedtls_aes_context cty;
     uint32_t *RK;
     uint32_t *SK;
 
-    AES_VALIDATE_RET( ctx != NULL );
-    AES_VALIDATE_RET( key != NULL );
+    mbedtls_aes_init(&cty);
 
-    mbedtls_aes_init( &cty );
-
-#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16)
-    if( aes_padlock_ace == -1 )
-        aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE );
-
-    if( aes_padlock_ace )
-        ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf );
-    else
-#endif
-    ctx->rk = RK = ctx->buf;
+    ctx->rk_offset = mbedtls_aes_rk_offset(ctx->buf);
+    RK = ctx->buf + ctx->rk_offset;
 
     /* Also checks keybits */
-    if( ( ret = mbedtls_aes_setkey_enc( &cty, key, keybits ) ) != 0 )
+    if ((ret = mbedtls_aes_setkey_enc(&cty, key, keybits)) != 0) {
         goto exit;
+    }
 
     ctx->nr = cty.nr;
 
-#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
-    if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) )
-    {
-        mbedtls_aesni_inverse_key( (unsigned char *) ctx->rk,
-                           (const unsigned char *) cty.rk, ctx->nr );
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
+    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {
+        mbedtls_aesni_inverse_key((unsigned char *) RK,
+                                  (const unsigned char *) (cty.buf + cty.rk_offset), ctx->nr);
         goto exit;
     }
 #endif
 
-    SK = cty.rk + cty.nr * 4;
+#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
+    if (mbedtls_aesce_has_support()) {
+        mbedtls_aesce_inverse_key(
+            (unsigned char *) RK,
+            (const unsigned char *) (cty.buf + cty.rk_offset),
+            ctx->nr);
+        goto exit;
+    }
+#endif
+
+    SK = cty.buf + cty.rk_offset + cty.nr * 4;
 
     *RK++ = *SK++;
     *RK++ = *SK++;
     *RK++ = *SK++;
     *RK++ = *SK++;
 
-    for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 )
-    {
-        for( j = 0; j < 4; j++, SK++ )
-        {
-            *RK++ = AES_RT0( FSb[ MBEDTLS_BYTE_0( *SK ) ] ) ^
-                    AES_RT1( FSb[ MBEDTLS_BYTE_1( *SK ) ] ) ^
-                    AES_RT2( FSb[ MBEDTLS_BYTE_2( *SK ) ] ) ^
-                    AES_RT3( FSb[ MBEDTLS_BYTE_3( *SK ) ] );
+    for (i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8) {
+        for (j = 0; j < 4; j++, SK++) {
+            *RK++ = AES_RT0(FSb[MBEDTLS_BYTE_0(*SK)]) ^
+                    AES_RT1(FSb[MBEDTLS_BYTE_1(*SK)]) ^
+                    AES_RT2(FSb[MBEDTLS_BYTE_2(*SK)]) ^
+                    AES_RT3(FSb[MBEDTLS_BYTE_3(*SK)]);
         }
     }
 
@@ -703,28 +721,27 @@
     *RK++ = *SK++;
 
 exit:
-    mbedtls_aes_free( &cty );
+    mbedtls_aes_free(&cty);
 
-    return( ret );
+    return ret;
 }
 #endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */
 
 #if defined(MBEDTLS_CIPHER_MODE_XTS)
-static int mbedtls_aes_xts_decode_keys( const unsigned char *key,
-                                        unsigned int keybits,
-                                        const unsigned char **key1,
-                                        unsigned int *key1bits,
-                                        const unsigned char **key2,
-                                        unsigned int *key2bits )
+static int mbedtls_aes_xts_decode_keys(const unsigned char *key,
+                                       unsigned int keybits,
+                                       const unsigned char **key1,
+                                       unsigned int *key1bits,
+                                       const unsigned char **key2,
+                                       unsigned int *key2bits)
 {
     const unsigned int half_keybits = keybits / 2;
     const unsigned int half_keybytes = half_keybits / 8;
 
-    switch( keybits )
-    {
+    switch (keybits) {
         case 256: break;
         case 512: break;
-        default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
+        default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
     }
 
     *key1bits = half_keybits;
@@ -735,318 +752,315 @@
     return 0;
 }
 
-int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
-                                const unsigned char *key,
-                                unsigned int keybits)
+int mbedtls_aes_xts_setkey_enc(mbedtls_aes_xts_context *ctx,
+                               const unsigned char *key,
+                               unsigned int keybits)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const unsigned char *key1, *key2;
     unsigned int key1bits, key2bits;
 
-    AES_VALIDATE_RET( ctx != NULL );
-    AES_VALIDATE_RET( key != NULL );
-
-    ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
-                                       &key2, &key2bits );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_aes_xts_decode_keys(key, keybits, &key1, &key1bits,
+                                      &key2, &key2bits);
+    if (ret != 0) {
+        return ret;
+    }
 
     /* Set the tweak key. Always set tweak key for the encryption mode. */
-    ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_aes_setkey_enc(&ctx->tweak, key2, key2bits);
+    if (ret != 0) {
+        return ret;
+    }
 
     /* Set crypt key for encryption. */
-    return mbedtls_aes_setkey_enc( &ctx->crypt, key1, key1bits );
+    return mbedtls_aes_setkey_enc(&ctx->crypt, key1, key1bits);
 }
 
-int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
-                                const unsigned char *key,
-                                unsigned int keybits)
+int mbedtls_aes_xts_setkey_dec(mbedtls_aes_xts_context *ctx,
+                               const unsigned char *key,
+                               unsigned int keybits)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const unsigned char *key1, *key2;
     unsigned int key1bits, key2bits;
 
-    AES_VALIDATE_RET( ctx != NULL );
-    AES_VALIDATE_RET( key != NULL );
-
-    ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
-                                       &key2, &key2bits );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_aes_xts_decode_keys(key, keybits, &key1, &key1bits,
+                                      &key2, &key2bits);
+    if (ret != 0) {
+        return ret;
+    }
 
     /* Set the tweak key. Always set tweak key for encryption. */
-    ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_aes_setkey_enc(&ctx->tweak, key2, key2bits);
+    if (ret != 0) {
+        return ret;
+    }
 
     /* Set crypt key for decryption. */
-    return mbedtls_aes_setkey_dec( &ctx->crypt, key1, key1bits );
+    return mbedtls_aes_setkey_dec(&ctx->crypt, key1, key1bits);
 }
 #endif /* MBEDTLS_CIPHER_MODE_XTS */
 
-#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)                 \
+#define AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3)                 \
     do                                                      \
     {                                                       \
-        (X0) = *RK++ ^ AES_FT0( MBEDTLS_BYTE_0( Y0 ) ) ^    \
-                       AES_FT1( MBEDTLS_BYTE_1( Y1 ) ) ^    \
-                       AES_FT2( MBEDTLS_BYTE_2( Y2 ) ) ^    \
-                       AES_FT3( MBEDTLS_BYTE_3( Y3 ) );     \
+        (X0) = *RK++ ^ AES_FT0(MBEDTLS_BYTE_0(Y0)) ^    \
+               AES_FT1(MBEDTLS_BYTE_1(Y1)) ^    \
+               AES_FT2(MBEDTLS_BYTE_2(Y2)) ^    \
+               AES_FT3(MBEDTLS_BYTE_3(Y3));     \
                                                             \
-        (X1) = *RK++ ^ AES_FT0( MBEDTLS_BYTE_0( Y1 ) ) ^    \
-                       AES_FT1( MBEDTLS_BYTE_1( Y2 ) ) ^    \
-                       AES_FT2( MBEDTLS_BYTE_2( Y3 ) ) ^    \
-                       AES_FT3( MBEDTLS_BYTE_3( Y0 ) );     \
+        (X1) = *RK++ ^ AES_FT0(MBEDTLS_BYTE_0(Y1)) ^    \
+               AES_FT1(MBEDTLS_BYTE_1(Y2)) ^    \
+               AES_FT2(MBEDTLS_BYTE_2(Y3)) ^    \
+               AES_FT3(MBEDTLS_BYTE_3(Y0));     \
                                                             \
-        (X2) = *RK++ ^ AES_FT0( MBEDTLS_BYTE_0( Y2 ) ) ^    \
-                       AES_FT1( MBEDTLS_BYTE_1( Y3 ) ) ^    \
-                       AES_FT2( MBEDTLS_BYTE_2( Y0 ) ) ^    \
-                       AES_FT3( MBEDTLS_BYTE_3( Y1 ) );     \
+        (X2) = *RK++ ^ AES_FT0(MBEDTLS_BYTE_0(Y2)) ^    \
+               AES_FT1(MBEDTLS_BYTE_1(Y3)) ^    \
+               AES_FT2(MBEDTLS_BYTE_2(Y0)) ^    \
+               AES_FT3(MBEDTLS_BYTE_3(Y1));     \
                                                             \
-        (X3) = *RK++ ^ AES_FT0( MBEDTLS_BYTE_0( Y3 ) ) ^    \
-                       AES_FT1( MBEDTLS_BYTE_1( Y0 ) ) ^    \
-                       AES_FT2( MBEDTLS_BYTE_2( Y1 ) ) ^    \
-                       AES_FT3( MBEDTLS_BYTE_3( Y2 ) );     \
-    } while( 0 )
+        (X3) = *RK++ ^ AES_FT0(MBEDTLS_BYTE_0(Y3)) ^    \
+               AES_FT1(MBEDTLS_BYTE_1(Y0)) ^    \
+               AES_FT2(MBEDTLS_BYTE_2(Y1)) ^    \
+               AES_FT3(MBEDTLS_BYTE_3(Y2));     \
+    } while (0)
 
-#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)                 \
+#define AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3)                 \
     do                                                      \
     {                                                       \
-        (X0) = *RK++ ^ AES_RT0( MBEDTLS_BYTE_0( Y0 ) ) ^    \
-                       AES_RT1( MBEDTLS_BYTE_1( Y3 ) ) ^    \
-                       AES_RT2( MBEDTLS_BYTE_2( Y2 ) ) ^    \
-                       AES_RT3( MBEDTLS_BYTE_3( Y1 ) );     \
+        (X0) = *RK++ ^ AES_RT0(MBEDTLS_BYTE_0(Y0)) ^    \
+               AES_RT1(MBEDTLS_BYTE_1(Y3)) ^    \
+               AES_RT2(MBEDTLS_BYTE_2(Y2)) ^    \
+               AES_RT3(MBEDTLS_BYTE_3(Y1));     \
                                                             \
-        (X1) = *RK++ ^ AES_RT0( MBEDTLS_BYTE_0( Y1 ) ) ^    \
-                       AES_RT1( MBEDTLS_BYTE_1( Y0 ) ) ^    \
-                       AES_RT2( MBEDTLS_BYTE_2( Y3 ) ) ^    \
-                       AES_RT3( MBEDTLS_BYTE_3( Y2 ) );     \
+        (X1) = *RK++ ^ AES_RT0(MBEDTLS_BYTE_0(Y1)) ^    \
+               AES_RT1(MBEDTLS_BYTE_1(Y0)) ^    \
+               AES_RT2(MBEDTLS_BYTE_2(Y3)) ^    \
+               AES_RT3(MBEDTLS_BYTE_3(Y2));     \
                                                             \
-        (X2) = *RK++ ^ AES_RT0( MBEDTLS_BYTE_0( Y2 ) ) ^    \
-                       AES_RT1( MBEDTLS_BYTE_1( Y1 ) ) ^    \
-                       AES_RT2( MBEDTLS_BYTE_2( Y0 ) ) ^    \
-                       AES_RT3( MBEDTLS_BYTE_3( Y3 ) );     \
+        (X2) = *RK++ ^ AES_RT0(MBEDTLS_BYTE_0(Y2)) ^    \
+               AES_RT1(MBEDTLS_BYTE_1(Y1)) ^    \
+               AES_RT2(MBEDTLS_BYTE_2(Y0)) ^    \
+               AES_RT3(MBEDTLS_BYTE_3(Y3));     \
                                                             \
-        (X3) = *RK++ ^ AES_RT0( MBEDTLS_BYTE_0( Y3 ) ) ^    \
-                       AES_RT1( MBEDTLS_BYTE_1( Y2 ) ) ^    \
-                       AES_RT2( MBEDTLS_BYTE_2( Y1 ) ) ^    \
-                       AES_RT3( MBEDTLS_BYTE_3( Y0 ) );     \
-    } while( 0 )
+        (X3) = *RK++ ^ AES_RT0(MBEDTLS_BYTE_0(Y3)) ^    \
+               AES_RT1(MBEDTLS_BYTE_1(Y2)) ^    \
+               AES_RT2(MBEDTLS_BYTE_2(Y1)) ^    \
+               AES_RT3(MBEDTLS_BYTE_3(Y0));     \
+    } while (0)
 
 /*
  * AES-ECB block encryption
  */
 #if !defined(MBEDTLS_AES_ENCRYPT_ALT)
-int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx,
-                                  const unsigned char input[16],
-                                  unsigned char output[16] )
+int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx,
+                                 const unsigned char input[16],
+                                 unsigned char output[16])
 {
     int i;
-    uint32_t *RK = ctx->rk;
-    struct
-    {
+    uint32_t *RK = ctx->buf + ctx->rk_offset;
+    struct {
         uint32_t X[4];
         uint32_t Y[4];
     } t;
 
-    t.X[0] = MBEDTLS_GET_UINT32_LE( input,  0 ); t.X[0] ^= *RK++;
-    t.X[1] = MBEDTLS_GET_UINT32_LE( input,  4 ); t.X[1] ^= *RK++;
-    t.X[2] = MBEDTLS_GET_UINT32_LE( input,  8 ); t.X[2] ^= *RK++;
-    t.X[3] = MBEDTLS_GET_UINT32_LE( input, 12 ); t.X[3] ^= *RK++;
+    t.X[0] = MBEDTLS_GET_UINT32_LE(input,  0); t.X[0] ^= *RK++;
+    t.X[1] = MBEDTLS_GET_UINT32_LE(input,  4); t.X[1] ^= *RK++;
+    t.X[2] = MBEDTLS_GET_UINT32_LE(input,  8); t.X[2] ^= *RK++;
+    t.X[3] = MBEDTLS_GET_UINT32_LE(input, 12); t.X[3] ^= *RK++;
 
-    for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
-    {
-        AES_FROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] );
-        AES_FROUND( t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3] );
+    for (i = (ctx->nr >> 1) - 1; i > 0; i--) {
+        AES_FROUND(t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3]);
+        AES_FROUND(t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3]);
     }
 
-    AES_FROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] );
+    AES_FROUND(t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3]);
 
     t.X[0] = *RK++ ^ \
-            ( (uint32_t) FSb[ MBEDTLS_BYTE_0( t.Y[0] ) ]       ) ^
-            ( (uint32_t) FSb[ MBEDTLS_BYTE_1( t.Y[1] ) ] <<  8 ) ^
-            ( (uint32_t) FSb[ MBEDTLS_BYTE_2( t.Y[2] ) ] << 16 ) ^
-            ( (uint32_t) FSb[ MBEDTLS_BYTE_3( t.Y[3] ) ] << 24 );
+             ((uint32_t) FSb[MBEDTLS_BYTE_0(t.Y[0])]) ^
+             ((uint32_t) FSb[MBEDTLS_BYTE_1(t.Y[1])] <<  8) ^
+             ((uint32_t) FSb[MBEDTLS_BYTE_2(t.Y[2])] << 16) ^
+             ((uint32_t) FSb[MBEDTLS_BYTE_3(t.Y[3])] << 24);
 
     t.X[1] = *RK++ ^ \
-            ( (uint32_t) FSb[ MBEDTLS_BYTE_0( t.Y[1] ) ]       ) ^
-            ( (uint32_t) FSb[ MBEDTLS_BYTE_1( t.Y[2] ) ] <<  8 ) ^
-            ( (uint32_t) FSb[ MBEDTLS_BYTE_2( t.Y[3] ) ] << 16 ) ^
-            ( (uint32_t) FSb[ MBEDTLS_BYTE_3( t.Y[0] ) ] << 24 );
+             ((uint32_t) FSb[MBEDTLS_BYTE_0(t.Y[1])]) ^
+             ((uint32_t) FSb[MBEDTLS_BYTE_1(t.Y[2])] <<  8) ^
+             ((uint32_t) FSb[MBEDTLS_BYTE_2(t.Y[3])] << 16) ^
+             ((uint32_t) FSb[MBEDTLS_BYTE_3(t.Y[0])] << 24);
 
     t.X[2] = *RK++ ^ \
-            ( (uint32_t) FSb[ MBEDTLS_BYTE_0( t.Y[2] ) ]       ) ^
-            ( (uint32_t) FSb[ MBEDTLS_BYTE_1( t.Y[3] ) ] <<  8 ) ^
-            ( (uint32_t) FSb[ MBEDTLS_BYTE_2( t.Y[0] ) ] << 16 ) ^
-            ( (uint32_t) FSb[ MBEDTLS_BYTE_3( t.Y[1] ) ] << 24 );
+             ((uint32_t) FSb[MBEDTLS_BYTE_0(t.Y[2])]) ^
+             ((uint32_t) FSb[MBEDTLS_BYTE_1(t.Y[3])] <<  8) ^
+             ((uint32_t) FSb[MBEDTLS_BYTE_2(t.Y[0])] << 16) ^
+             ((uint32_t) FSb[MBEDTLS_BYTE_3(t.Y[1])] << 24);
 
     t.X[3] = *RK++ ^ \
-            ( (uint32_t) FSb[ MBEDTLS_BYTE_0( t.Y[3] ) ]       ) ^
-            ( (uint32_t) FSb[ MBEDTLS_BYTE_1( t.Y[0] ) ] <<  8 ) ^
-            ( (uint32_t) FSb[ MBEDTLS_BYTE_2( t.Y[1] ) ] << 16 ) ^
-            ( (uint32_t) FSb[ MBEDTLS_BYTE_3( t.Y[2] ) ] << 24 );
+             ((uint32_t) FSb[MBEDTLS_BYTE_0(t.Y[3])]) ^
+             ((uint32_t) FSb[MBEDTLS_BYTE_1(t.Y[0])] <<  8) ^
+             ((uint32_t) FSb[MBEDTLS_BYTE_2(t.Y[1])] << 16) ^
+             ((uint32_t) FSb[MBEDTLS_BYTE_3(t.Y[2])] << 24);
 
-    MBEDTLS_PUT_UINT32_LE( t.X[0], output,  0 );
-    MBEDTLS_PUT_UINT32_LE( t.X[1], output,  4 );
-    MBEDTLS_PUT_UINT32_LE( t.X[2], output,  8 );
-    MBEDTLS_PUT_UINT32_LE( t.X[3], output, 12 );
+    MBEDTLS_PUT_UINT32_LE(t.X[0], output,  0);
+    MBEDTLS_PUT_UINT32_LE(t.X[1], output,  4);
+    MBEDTLS_PUT_UINT32_LE(t.X[2], output,  8);
+    MBEDTLS_PUT_UINT32_LE(t.X[3], output, 12);
 
-    mbedtls_platform_zeroize( &t, sizeof( t ) );
+    mbedtls_platform_zeroize(&t, sizeof(t));
 
-    return( 0 );
+    return 0;
 }
 #endif /* !MBEDTLS_AES_ENCRYPT_ALT */
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
-                          const unsigned char input[16],
-                          unsigned char output[16] )
-{
-    MBEDTLS_IGNORE_RETURN( mbedtls_internal_aes_encrypt( ctx, input, output ) );
-}
-#endif /* !MBEDTLS_DEPRECATED_REMOVED */
-
 /*
  * AES-ECB block decryption
  */
 #if !defined(MBEDTLS_AES_DECRYPT_ALT)
-int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx,
-                                  const unsigned char input[16],
-                                  unsigned char output[16] )
+int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx,
+                                 const unsigned char input[16],
+                                 unsigned char output[16])
 {
     int i;
-    uint32_t *RK = ctx->rk;
-    struct
-    {
+    uint32_t *RK = ctx->buf + ctx->rk_offset;
+    struct {
         uint32_t X[4];
         uint32_t Y[4];
     } t;
 
-    t.X[0] = MBEDTLS_GET_UINT32_LE( input,  0 ); t.X[0] ^= *RK++;
-    t.X[1] = MBEDTLS_GET_UINT32_LE( input,  4 ); t.X[1] ^= *RK++;
-    t.X[2] = MBEDTLS_GET_UINT32_LE( input,  8 ); t.X[2] ^= *RK++;
-    t.X[3] = MBEDTLS_GET_UINT32_LE( input, 12 ); t.X[3] ^= *RK++;
+    t.X[0] = MBEDTLS_GET_UINT32_LE(input,  0); t.X[0] ^= *RK++;
+    t.X[1] = MBEDTLS_GET_UINT32_LE(input,  4); t.X[1] ^= *RK++;
+    t.X[2] = MBEDTLS_GET_UINT32_LE(input,  8); t.X[2] ^= *RK++;
+    t.X[3] = MBEDTLS_GET_UINT32_LE(input, 12); t.X[3] ^= *RK++;
 
-    for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
-    {
-        AES_RROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] );
-        AES_RROUND( t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3] );
+    for (i = (ctx->nr >> 1) - 1; i > 0; i--) {
+        AES_RROUND(t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3]);
+        AES_RROUND(t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3]);
     }
 
-    AES_RROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] );
+    AES_RROUND(t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3]);
 
     t.X[0] = *RK++ ^ \
-            ( (uint32_t) RSb[ MBEDTLS_BYTE_0( t.Y[0] ) ]       ) ^
-            ( (uint32_t) RSb[ MBEDTLS_BYTE_1( t.Y[3] ) ] <<  8 ) ^
-            ( (uint32_t) RSb[ MBEDTLS_BYTE_2( t.Y[2] ) ] << 16 ) ^
-            ( (uint32_t) RSb[ MBEDTLS_BYTE_3( t.Y[1] ) ] << 24 );
+             ((uint32_t) RSb[MBEDTLS_BYTE_0(t.Y[0])]) ^
+             ((uint32_t) RSb[MBEDTLS_BYTE_1(t.Y[3])] <<  8) ^
+             ((uint32_t) RSb[MBEDTLS_BYTE_2(t.Y[2])] << 16) ^
+             ((uint32_t) RSb[MBEDTLS_BYTE_3(t.Y[1])] << 24);
 
     t.X[1] = *RK++ ^ \
-            ( (uint32_t) RSb[ MBEDTLS_BYTE_0( t.Y[1] ) ]       ) ^
-            ( (uint32_t) RSb[ MBEDTLS_BYTE_1( t.Y[0] ) ] <<  8 ) ^
-            ( (uint32_t) RSb[ MBEDTLS_BYTE_2( t.Y[3] ) ] << 16 ) ^
-            ( (uint32_t) RSb[ MBEDTLS_BYTE_3( t.Y[2] ) ] << 24 );
+             ((uint32_t) RSb[MBEDTLS_BYTE_0(t.Y[1])]) ^
+             ((uint32_t) RSb[MBEDTLS_BYTE_1(t.Y[0])] <<  8) ^
+             ((uint32_t) RSb[MBEDTLS_BYTE_2(t.Y[3])] << 16) ^
+             ((uint32_t) RSb[MBEDTLS_BYTE_3(t.Y[2])] << 24);
 
     t.X[2] = *RK++ ^ \
-            ( (uint32_t) RSb[ MBEDTLS_BYTE_0( t.Y[2] ) ]       ) ^
-            ( (uint32_t) RSb[ MBEDTLS_BYTE_1( t.Y[1] ) ] <<  8 ) ^
-            ( (uint32_t) RSb[ MBEDTLS_BYTE_2( t.Y[0] ) ] << 16 ) ^
-            ( (uint32_t) RSb[ MBEDTLS_BYTE_3( t.Y[3] ) ] << 24 );
+             ((uint32_t) RSb[MBEDTLS_BYTE_0(t.Y[2])]) ^
+             ((uint32_t) RSb[MBEDTLS_BYTE_1(t.Y[1])] <<  8) ^
+             ((uint32_t) RSb[MBEDTLS_BYTE_2(t.Y[0])] << 16) ^
+             ((uint32_t) RSb[MBEDTLS_BYTE_3(t.Y[3])] << 24);
 
     t.X[3] = *RK++ ^ \
-            ( (uint32_t) RSb[ MBEDTLS_BYTE_0( t.Y[3] ) ]       ) ^
-            ( (uint32_t) RSb[ MBEDTLS_BYTE_1( t.Y[2] ) ] <<  8 ) ^
-            ( (uint32_t) RSb[ MBEDTLS_BYTE_2( t.Y[1] ) ] << 16 ) ^
-            ( (uint32_t) RSb[ MBEDTLS_BYTE_3( t.Y[0] ) ] << 24 );
+             ((uint32_t) RSb[MBEDTLS_BYTE_0(t.Y[3])]) ^
+             ((uint32_t) RSb[MBEDTLS_BYTE_1(t.Y[2])] <<  8) ^
+             ((uint32_t) RSb[MBEDTLS_BYTE_2(t.Y[1])] << 16) ^
+             ((uint32_t) RSb[MBEDTLS_BYTE_3(t.Y[0])] << 24);
 
-    MBEDTLS_PUT_UINT32_LE( t.X[0], output,  0 );
-    MBEDTLS_PUT_UINT32_LE( t.X[1], output,  4 );
-    MBEDTLS_PUT_UINT32_LE( t.X[2], output,  8 );
-    MBEDTLS_PUT_UINT32_LE( t.X[3], output, 12 );
+    MBEDTLS_PUT_UINT32_LE(t.X[0], output,  0);
+    MBEDTLS_PUT_UINT32_LE(t.X[1], output,  4);
+    MBEDTLS_PUT_UINT32_LE(t.X[2], output,  8);
+    MBEDTLS_PUT_UINT32_LE(t.X[3], output, 12);
 
-    mbedtls_platform_zeroize( &t, sizeof( t ) );
+    mbedtls_platform_zeroize(&t, sizeof(t));
 
-    return( 0 );
+    return 0;
 }
 #endif /* !MBEDTLS_AES_DECRYPT_ALT */
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
-                          const unsigned char input[16],
-                          unsigned char output[16] )
+#if defined(MAY_NEED_TO_ALIGN)
+/* VIA Padlock and our intrinsics-based implementation of AESNI require
+ * the round keys to be aligned on a 16-byte boundary. We take care of this
+ * before creating them, but the AES context may have moved (this can happen
+ * if the library is called from a language with managed memory), and in later
+ * calls it might have a different alignment with respect to 16-byte memory.
+ * So we may need to realign.
+ */
+static void aes_maybe_realign(mbedtls_aes_context *ctx)
 {
-    MBEDTLS_IGNORE_RETURN( mbedtls_internal_aes_decrypt( ctx, input, output ) );
+    unsigned new_offset = mbedtls_aes_rk_offset(ctx->buf);
+    if (new_offset != ctx->rk_offset) {
+        memmove(ctx->buf + new_offset,     // new address
+                ctx->buf + ctx->rk_offset, // current address
+                (ctx->nr + 1) * 16);       // number of round keys * bytes per rk
+        ctx->rk_offset = new_offset;
+    }
 }
-#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+#endif
 
 /*
  * AES-ECB block encryption/decryption
  */
-int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
-                           int mode,
-                           const unsigned char input[16],
-                           unsigned char output[16] )
+int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx,
+                          int mode,
+                          const unsigned char input[16],
+                          unsigned char output[16])
 {
-    AES_VALIDATE_RET( ctx != NULL );
-    AES_VALIDATE_RET( input != NULL );
-    AES_VALIDATE_RET( output != NULL );
-    AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
-                      mode == MBEDTLS_AES_DECRYPT );
+    if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) {
+        return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
+    }
 
-#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
-    if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) )
-        return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) );
+#if defined(MAY_NEED_TO_ALIGN)
+    aes_maybe_realign(ctx);
 #endif
 
-#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
-    if( aes_padlock_ace )
-    {
-        if( mbedtls_padlock_xcryptecb( ctx, mode, input, output ) == 0 )
-            return( 0 );
-
-        // If padlock data misaligned, we just fall back to
-        // unaccelerated mode
-        //
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
+    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {
+        return mbedtls_aesni_crypt_ecb(ctx, mode, input, output);
     }
 #endif
 
-    if( mode == MBEDTLS_AES_ENCRYPT )
-        return( mbedtls_internal_aes_encrypt( ctx, input, output ) );
-    else
-        return( mbedtls_internal_aes_decrypt( ctx, input, output ) );
+#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
+    if (mbedtls_aesce_has_support()) {
+        return mbedtls_aesce_crypt_ecb(ctx, mode, input, output);
+    }
+#endif
+
+#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
+    if (aes_padlock_ace > 0) {
+        return mbedtls_padlock_xcryptecb(ctx, mode, input, output);
+    }
+#endif
+
+    if (mode == MBEDTLS_AES_ENCRYPT) {
+        return mbedtls_internal_aes_encrypt(ctx, input, output);
+    } else {
+        return mbedtls_internal_aes_decrypt(ctx, input, output);
+    }
 }
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
 /*
  * AES-CBC buffer encryption/decryption
  */
-int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
-                    int mode,
-                    size_t length,
-                    unsigned char iv[16],
-                    const unsigned char *input,
-                    unsigned char *output )
+int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx,
+                          int mode,
+                          size_t length,
+                          unsigned char iv[16],
+                          const unsigned char *input,
+                          unsigned char *output)
 {
-    int i;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char temp[16];
 
-    AES_VALIDATE_RET( ctx != NULL );
-    AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
-                      mode == MBEDTLS_AES_DECRYPT );
-    AES_VALIDATE_RET( iv != NULL );
-    AES_VALIDATE_RET( input != NULL );
-    AES_VALIDATE_RET( output != NULL );
+    if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) {
+        return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
+    }
 
-    if( length % 16 )
-        return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
+    if (length % 16) {
+        return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
+    }
 
 #if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
-    if( aes_padlock_ace )
-    {
-        if( mbedtls_padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 )
-            return( 0 );
+    if (aes_padlock_ace > 0) {
+        if (mbedtls_padlock_xcryptcbc(ctx, mode, length, iv, input, output) == 0) {
+            return 0;
+        }
 
         // If padlock data misaligned, we just fall back to
         // unaccelerated mode
@@ -1054,36 +1068,31 @@
     }
 #endif
 
-    if( mode == MBEDTLS_AES_DECRYPT )
-    {
-        while( length > 0 )
-        {
-            memcpy( temp, input, 16 );
-            ret = mbedtls_aes_crypt_ecb( ctx, mode, input, output );
-            if( ret != 0 )
+    if (mode == MBEDTLS_AES_DECRYPT) {
+        while (length > 0) {
+            memcpy(temp, input, 16);
+            ret = mbedtls_aes_crypt_ecb(ctx, mode, input, output);
+            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 );
+            memcpy(iv, temp, 16);
 
             input  += 16;
             output += 16;
             length -= 16;
         }
-    }
-    else
-    {
-        while( length > 0 )
-        {
-            for( i = 0; i < 16; i++ )
-                output[i] = (unsigned char)( input[i] ^ iv[i] );
+    } else {
+        while (length > 0) {
+            mbedtls_xor(output, input, iv, 16);
 
-            ret = mbedtls_aes_crypt_ecb( ctx, mode, output, output );
-            if( ret != 0 )
+            ret = mbedtls_aes_crypt_ecb(ctx, mode, output, output);
+            if (ret != 0) {
                 goto exit;
-            memcpy( iv, output, 16 );
+            }
+            memcpy(iv, output, 16);
 
             input  += 16;
             output += 16;
@@ -1093,7 +1102,7 @@
     ret = 0;
 
 exit:
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
@@ -1109,30 +1118,30 @@
  * for machine endianness and hence works correctly on both big and little
  * endian machines.
  */
-static void mbedtls_gf128mul_x_ble( unsigned char r[16],
-                                    const unsigned char x[16] )
+static void mbedtls_gf128mul_x_ble(unsigned char r[16],
+                                   const unsigned char x[16])
 {
     uint64_t a, b, ra, rb;
 
-    a = MBEDTLS_GET_UINT64_LE( x, 0 );
-    b = MBEDTLS_GET_UINT64_LE( x, 8 );
+    a = MBEDTLS_GET_UINT64_LE(x, 0);
+    b = MBEDTLS_GET_UINT64_LE(x, 8);
 
-    ra = ( a << 1 )  ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) );
-    rb = ( a >> 63 ) | ( b << 1 );
+    ra = (a << 1)  ^ 0x0087 >> (8 - ((b >> 63) << 3));
+    rb = (a >> 63) | (b << 1);
 
-    MBEDTLS_PUT_UINT64_LE( ra, r, 0 );
-    MBEDTLS_PUT_UINT64_LE( rb, r, 8 );
+    MBEDTLS_PUT_UINT64_LE(ra, r, 0);
+    MBEDTLS_PUT_UINT64_LE(rb, r, 8);
 }
 
 /*
  * AES-XTS buffer encryption/decryption
  */
-int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
-                           int mode,
-                           size_t length,
-                           const unsigned char data_unit[16],
-                           const unsigned char *input,
-                           unsigned char *output )
+int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx,
+                          int mode,
+                          size_t length,
+                          const unsigned char data_unit[16],
+                          const unsigned char *input,
+                          unsigned char *output)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t blocks = length / 16;
@@ -1141,61 +1150,55 @@
     unsigned char prev_tweak[16];
     unsigned char tmp[16];
 
-    AES_VALIDATE_RET( ctx != NULL );
-    AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
-                      mode == MBEDTLS_AES_DECRYPT );
-    AES_VALIDATE_RET( data_unit != NULL );
-    AES_VALIDATE_RET( input != NULL );
-    AES_VALIDATE_RET( output != NULL );
+    if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) {
+        return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
+    }
 
     /* Data units must be at least 16 bytes long. */
-    if( length < 16 )
+    if (length < 16) {
         return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
+    }
 
     /* NIST SP 800-38E disallows data units larger than 2**20 blocks. */
-    if( length > ( 1 << 20 ) * 16 )
+    if (length > (1 << 20) * 16) {
         return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
+    }
 
     /* Compute the tweak. */
-    ret = mbedtls_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT,
-                                 data_unit, tweak );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_aes_crypt_ecb(&ctx->tweak, MBEDTLS_AES_ENCRYPT,
+                                data_unit, tweak);
+    if (ret != 0) {
+        return ret;
+    }
 
-    while( blocks-- )
-    {
-        size_t i;
-
-        if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 )
-        {
+    while (blocks--) {
+        if (leftover && (mode == MBEDTLS_AES_DECRYPT) && blocks == 0) {
             /* We are on the last block in a decrypt operation that has
              * leftover bytes, so we need to use the next tweak for this block,
-             * and this tweak for the lefover bytes. Save the current tweak for
+             * and this tweak for the leftover bytes. Save the current tweak for
              * the leftovers and then update the current tweak for use on this,
              * the last full block. */
-            memcpy( prev_tweak, tweak, sizeof( tweak ) );
-            mbedtls_gf128mul_x_ble( tweak, tweak );
+            memcpy(prev_tweak, tweak, sizeof(tweak));
+            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 );
+        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 );
+        mbedtls_gf128mul_x_ble(tweak, tweak);
 
         output += 16;
         input += 16;
     }
 
-    if( leftover )
-    {
+    if (leftover) {
         /* If we are on the leftover bytes in a decrypt operation, we need to
          * use the previous tweak for these bytes (as saved in prev_tweak). */
         unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak;
@@ -1206,31 +1209,29 @@
         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). */
-        for( i = 0; i < leftover; i++ )
-        {
+         * 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 )
+        ret = mbedtls_aes_crypt_ecb(&ctx->crypt, mode, tmp, tmp);
+        if (ret != 0) {
             return ret;
+        }
 
         /* 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 );
+    return 0;
 }
 #endif /* MBEDTLS_CIPHER_MODE_XTS */
 
@@ -1238,63 +1239,55 @@
 /*
  * AES-CFB128 buffer encryption/decryption
  */
-int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
-                       int mode,
-                       size_t length,
-                       size_t *iv_off,
-                       unsigned char iv[16],
-                       const unsigned char *input,
-                       unsigned char *output )
+int mbedtls_aes_crypt_cfb128(mbedtls_aes_context *ctx,
+                             int mode,
+                             size_t length,
+                             size_t *iv_off,
+                             unsigned char iv[16],
+                             const unsigned char *input,
+                             unsigned char *output)
 {
     int c;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
 
-    AES_VALIDATE_RET( ctx != NULL );
-    AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
-                      mode == MBEDTLS_AES_DECRYPT );
-    AES_VALIDATE_RET( iv_off != NULL );
-    AES_VALIDATE_RET( iv != NULL );
-    AES_VALIDATE_RET( input != NULL );
-    AES_VALIDATE_RET( output != NULL );
+    if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) {
+        return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
+    }
 
     n = *iv_off;
 
-    if( n > 15 )
-        return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
+    if (n > 15) {
+        return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
+    }
 
-    if( mode == MBEDTLS_AES_DECRYPT )
-    {
-        while( length-- )
-        {
-            if( n == 0 )
-            {
-                ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
-                if( ret != 0 )
+    if (mode == MBEDTLS_AES_DECRYPT) {
+        while (length--) {
+            if (n == 0) {
+                ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv);
+                if (ret != 0) {
                     goto exit;
+                }
             }
 
             c = *input++;
-            *output++ = (unsigned char)( c ^ iv[n] );
+            *output++ = (unsigned char) (c ^ iv[n]);
             iv[n] = (unsigned char) c;
 
-            n = ( n + 1 ) & 0x0F;
+            n = (n + 1) & 0x0F;
         }
-    }
-    else
-    {
-        while( length-- )
-        {
-            if( n == 0 )
-            {
-                ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
-                if( ret != 0 )
+    } else {
+        while (length--) {
+            if (n == 0) {
+                ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv);
+                if (ret != 0) {
                     goto exit;
+                }
             }
 
-            iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+            iv[n] = *output++ = (unsigned char) (iv[n] ^ *input++);
 
-            n = ( n + 1 ) & 0x0F;
+            n = (n + 1) & 0x0F;
         }
     }
 
@@ -1302,50 +1295,49 @@
     ret = 0;
 
 exit:
-    return( ret );
+    return ret;
 }
 
 /*
  * AES-CFB8 buffer encryption/decryption
  */
-int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
-                            int mode,
-                            size_t length,
-                            unsigned char iv[16],
-                            const unsigned char *input,
-                            unsigned char *output )
+int mbedtls_aes_crypt_cfb8(mbedtls_aes_context *ctx,
+                           int mode,
+                           size_t length,
+                           unsigned char iv[16],
+                           const unsigned char *input,
+                           unsigned char *output)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char c;
     unsigned char ov[17];
 
-    AES_VALIDATE_RET( ctx != NULL );
-    AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
-                      mode == MBEDTLS_AES_DECRYPT );
-    AES_VALIDATE_RET( iv != NULL );
-    AES_VALIDATE_RET( input != NULL );
-    AES_VALIDATE_RET( output != NULL );
-    while( length-- )
-    {
-        memcpy( ov, iv, 16 );
-        ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
-        if( ret != 0 )
+    if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) {
+        return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
+    }
+    while (length--) {
+        memcpy(ov, iv, 16);
+        ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv);
+        if (ret != 0) {
             goto exit;
+        }
 
-        if( mode == MBEDTLS_AES_DECRYPT )
+        if (mode == MBEDTLS_AES_DECRYPT) {
             ov[16] = *input;
+        }
 
-        c = *output++ = (unsigned char)( iv[0] ^ *input++ );
+        c = *output++ = (unsigned char) (iv[0] ^ *input++);
 
-        if( mode == MBEDTLS_AES_ENCRYPT )
+        if (mode == MBEDTLS_AES_ENCRYPT) {
             ov[16] = c;
+        }
 
-        memcpy( iv, ov + 1, 16 );
+        memcpy(iv, ov + 1, 16);
     }
     ret = 0;
 
 exit:
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
@@ -1353,44 +1345,38 @@
 /*
  * AES-OFB (Output Feedback Mode) buffer encryption/decryption
  */
-int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
-                           size_t length,
-                           size_t *iv_off,
-                           unsigned char iv[16],
-                           const unsigned char *input,
-                           unsigned char *output )
+int mbedtls_aes_crypt_ofb(mbedtls_aes_context *ctx,
+                          size_t length,
+                          size_t *iv_off,
+                          unsigned char iv[16],
+                          const unsigned char *input,
+                          unsigned char *output)
 {
     int ret = 0;
     size_t n;
 
-    AES_VALIDATE_RET( ctx != NULL );
-    AES_VALIDATE_RET( iv_off != NULL );
-    AES_VALIDATE_RET( iv != NULL );
-    AES_VALIDATE_RET( input != NULL );
-    AES_VALIDATE_RET( output != NULL );
-
     n = *iv_off;
 
-    if( n > 15 )
-        return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
+    if (n > 15) {
+        return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
+    }
 
-    while( length-- )
-    {
-        if( n == 0 )
-        {
-            ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
-            if( ret != 0 )
+    while (length--) {
+        if (n == 0) {
+            ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv);
+            if (ret != 0) {
                 goto exit;
+            }
         }
         *output++ =  *input++ ^ iv[n];
 
-        n = ( n + 1 ) & 0x0F;
+        n = (n + 1) & 0x0F;
     }
 
     *iv_off = n;
 
 exit:
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_CIPHER_MODE_OFB */
 
@@ -1398,52 +1384,48 @@
 /*
  * AES-CTR buffer encryption/decryption
  */
-int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
-                       size_t length,
-                       size_t *nc_off,
-                       unsigned char nonce_counter[16],
-                       unsigned char stream_block[16],
-                       const unsigned char *input,
-                       unsigned char *output )
+int mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx,
+                          size_t length,
+                          size_t *nc_off,
+                          unsigned char nonce_counter[16],
+                          unsigned char stream_block[16],
+                          const unsigned char *input,
+                          unsigned char *output)
 {
     int c, i;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
 
-    AES_VALIDATE_RET( ctx != NULL );
-    AES_VALIDATE_RET( nc_off != NULL );
-    AES_VALIDATE_RET( nonce_counter != NULL );
-    AES_VALIDATE_RET( stream_block != NULL );
-    AES_VALIDATE_RET( input != NULL );
-    AES_VALIDATE_RET( output != NULL );
-
     n = *nc_off;
 
-    if ( n > 0x0F )
-        return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
+    if (n > 0x0F) {
+        return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
+    }
 
-    while( length-- )
-    {
-        if( n == 0 ) {
-            ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block );
-            if( ret != 0 )
+    while (length--) {
+        if (n == 0) {
+            ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block);
+            if (ret != 0) {
                 goto exit;
+            }
 
-            for( i = 16; i > 0; i-- )
-                if( ++nonce_counter[i - 1] != 0 )
+            for (i = 16; i > 0; i--) {
+                if (++nonce_counter[i - 1] != 0) {
                     break;
+                }
+            }
         }
         c = *input++;
-        *output++ = (unsigned char)( c ^ stream_block[n] );
+        *output++ = (unsigned char) (c ^ stream_block[n]);
 
-        n = ( n + 1 ) & 0x0F;
+        n = (n + 1) & 0x0F;
     }
 
     *nc_off = n;
     ret = 0;
 
 exit:
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
@@ -1689,7 +1671,7 @@
 };
 
 static const int aes_test_ctr_len[3] =
-    { 16, 32, 36 };
+{ 16, 32, 36 };
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
 #if defined(MBEDTLS_CIPHER_MODE_XTS)
@@ -1750,12 +1732,12 @@
 
 static const unsigned char aes_test_xts_data_unit[][16] =
 {
-   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-   { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
-     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-   { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
-     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
 };
 
 #endif /* MBEDTLS_CIPHER_MODE_XTS */
@@ -1763,14 +1745,15 @@
 /*
  * Checkup routine
  */
-int mbedtls_aes_self_test( int verbose )
+int mbedtls_aes_self_test(int verbose)
 {
     int ret = 0, i, j, u, mode;
     unsigned int keybits;
     unsigned char key[32];
     unsigned char buf[64];
     const unsigned char *aes_tests;
-#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)
+#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \
+    defined(MBEDTLS_CIPHER_MODE_OFB)
     unsigned char iv[16];
 #endif
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
@@ -1789,32 +1772,52 @@
 #endif
     mbedtls_aes_context ctx;
 
-    memset( key, 0, 32 );
-    mbedtls_aes_init( &ctx );
+    memset(key, 0, 32);
+    mbedtls_aes_init(&ctx);
+
+    if (verbose != 0) {
+#if defined(MBEDTLS_AES_ALT)
+        mbedtls_printf("  AES note: alternative implementation.\n");
+#else /* MBEDTLS_AES_ALT */
+#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
+        if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) {
+            mbedtls_printf("  AES note: using VIA Padlock.\n");
+        } else
+#endif
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
+        if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {
+            mbedtls_printf("  AES note: using AESNI.\n");
+        } else
+#endif
+#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
+        if (mbedtls_aesce_has_support()) {
+            mbedtls_printf("  AES note: using AESCE.\n");
+        } else
+#endif
+        mbedtls_printf("  AES note: built-in implementation.\n");
+#endif /* MBEDTLS_AES_ALT */
+    }
 
     /*
      * ECB mode
      */
-    for( i = 0; i < 6; i++ )
-    {
+    for (i = 0; i < 6; i++) {
         u = i >> 1;
         keybits = 128 + u * 64;
         mode = i & 1;
 
-        if( verbose != 0 )
-            mbedtls_printf( "  AES-ECB-%3u (%s): ", keybits,
-                            ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
-
-        memset( buf, 0, 16 );
-
-        if( mode == MBEDTLS_AES_DECRYPT )
-        {
-            ret = mbedtls_aes_setkey_dec( &ctx, key, keybits );
-            aes_tests = aes_test_ecb_dec[u];
+        if (verbose != 0) {
+            mbedtls_printf("  AES-ECB-%3u (%s): ", keybits,
+                           (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
         }
-        else
-        {
-            ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
+
+        memset(buf, 0, 16);
+
+        if (mode == MBEDTLS_AES_DECRYPT) {
+            ret = mbedtls_aes_setkey_dec(&ctx, key, keybits);
+            aes_tests = aes_test_ecb_dec[u];
+        } else {
+            ret = mbedtls_aes_setkey_enc(&ctx, key, keybits);
             aes_tests = aes_test_ecb_enc[u];
         }
 
@@ -1823,62 +1826,57 @@
          * there is an alternative underlying implementation i.e. when
          * MBEDTLS_AES_ALT is defined.
          */
-        if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 )
-        {
-            mbedtls_printf( "skipped\n" );
+        if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) {
+            mbedtls_printf("skipped\n");
             continue;
-        }
-        else if( ret != 0 )
-        {
+        } else if (ret != 0) {
             goto exit;
         }
 
-        for( j = 0; j < 10000; j++ )
-        {
-            ret = mbedtls_aes_crypt_ecb( &ctx, mode, buf, buf );
-            if( ret != 0 )
+        for (j = 0; j < 10000; j++) {
+            ret = mbedtls_aes_crypt_ecb(&ctx, mode, buf, buf);
+            if (ret != 0) {
                 goto exit;
+            }
         }
 
-        if( memcmp( buf, aes_tests, 16 ) != 0 )
-        {
+        if (memcmp(buf, aes_tests, 16) != 0) {
             ret = 1;
             goto exit;
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     /*
      * CBC mode
      */
-    for( i = 0; i < 6; i++ )
-    {
+    for (i = 0; i < 6; i++) {
         u = i >> 1;
         keybits = 128 + u * 64;
         mode = i & 1;
 
-        if( verbose != 0 )
-            mbedtls_printf( "  AES-CBC-%3u (%s): ", keybits,
-                            ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
-
-        memset( iv , 0, 16 );
-        memset( prv, 0, 16 );
-        memset( buf, 0, 16 );
-
-        if( mode == MBEDTLS_AES_DECRYPT )
-        {
-            ret = mbedtls_aes_setkey_dec( &ctx, key, keybits );
-            aes_tests = aes_test_cbc_dec[u];
+        if (verbose != 0) {
+            mbedtls_printf("  AES-CBC-%3u (%s): ", keybits,
+                           (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
         }
-        else
-        {
-            ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
+
+        memset(iv, 0, 16);
+        memset(prv, 0, 16);
+        memset(buf, 0, 16);
+
+        if (mode == MBEDTLS_AES_DECRYPT) {
+            ret = mbedtls_aes_setkey_dec(&ctx, key, keybits);
+            aes_tests = aes_test_cbc_dec[u];
+        } else {
+            ret = mbedtls_aes_setkey_enc(&ctx, key, keybits);
             aes_tests = aes_test_cbc_enc[u];
         }
 
@@ -1887,301 +1885,292 @@
          * there is an alternative underlying implementation i.e. when
          * MBEDTLS_AES_ALT is defined.
          */
-        if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 )
-        {
-            mbedtls_printf( "skipped\n" );
+        if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) {
+            mbedtls_printf("skipped\n");
             continue;
-        }
-        else if( ret != 0 )
-        {
+        } else if (ret != 0) {
             goto exit;
         }
 
-        for( j = 0; j < 10000; j++ )
-        {
-            if( mode == MBEDTLS_AES_ENCRYPT )
-            {
+        for (j = 0; j < 10000; j++) {
+            if (mode == MBEDTLS_AES_ENCRYPT) {
                 unsigned char tmp[16];
 
-                memcpy( tmp, prv, 16 );
-                memcpy( prv, buf, 16 );
-                memcpy( buf, tmp, 16 );
+                memcpy(tmp, prv, 16);
+                memcpy(prv, buf, 16);
+                memcpy(buf, tmp, 16);
             }
 
-            ret = mbedtls_aes_crypt_cbc( &ctx, mode, 16, iv, buf, buf );
-            if( ret != 0 )
+            ret = mbedtls_aes_crypt_cbc(&ctx, mode, 16, iv, buf, buf);
+            if (ret != 0) {
                 goto exit;
+            }
 
         }
 
-        if( memcmp( buf, aes_tests, 16 ) != 0 )
-        {
+        if (memcmp(buf, aes_tests, 16) != 0) {
             ret = 1;
             goto exit;
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     /*
      * CFB128 mode
      */
-    for( i = 0; i < 6; i++ )
-    {
+    for (i = 0; i < 6; i++) {
         u = i >> 1;
         keybits = 128 + u * 64;
         mode = i & 1;
 
-        if( verbose != 0 )
-            mbedtls_printf( "  AES-CFB128-%3u (%s): ", keybits,
-                            ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+        if (verbose != 0) {
+            mbedtls_printf("  AES-CFB128-%3u (%s): ", keybits,
+                           (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
+        }
 
-        memcpy( iv,  aes_test_cfb128_iv, 16 );
-        memcpy( key, aes_test_cfb128_key[u], keybits / 8 );
+        memcpy(iv,  aes_test_cfb128_iv, 16);
+        memcpy(key, aes_test_cfb128_key[u], keybits / 8);
 
         offset = 0;
-        ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
+        ret = mbedtls_aes_setkey_enc(&ctx, key, keybits);
         /*
          * AES-192 is an optional feature that may be unavailable when
          * there is an alternative underlying implementation i.e. when
          * MBEDTLS_AES_ALT is defined.
          */
-        if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 )
-        {
-            mbedtls_printf( "skipped\n" );
+        if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) {
+            mbedtls_printf("skipped\n");
             continue;
-        }
-        else if( ret != 0 )
-        {
+        } else if (ret != 0) {
             goto exit;
         }
 
-        if( mode == MBEDTLS_AES_DECRYPT )
-        {
-            memcpy( buf, aes_test_cfb128_ct[u], 64 );
+        if (mode == MBEDTLS_AES_DECRYPT) {
+            memcpy(buf, aes_test_cfb128_ct[u], 64);
             aes_tests = aes_test_cfb128_pt;
-        }
-        else
-        {
-            memcpy( buf, aes_test_cfb128_pt, 64 );
+        } else {
+            memcpy(buf, aes_test_cfb128_pt, 64);
             aes_tests = aes_test_cfb128_ct[u];
         }
 
-        ret = mbedtls_aes_crypt_cfb128( &ctx, mode, 64, &offset, iv, buf, buf );
-        if( ret != 0 )
+        ret = mbedtls_aes_crypt_cfb128(&ctx, mode, 64, &offset, iv, buf, buf);
+        if (ret != 0) {
             goto exit;
+        }
 
-        if( memcmp( buf, aes_tests, 64 ) != 0 )
-        {
+        if (memcmp(buf, aes_tests, 64) != 0) {
             ret = 1;
             goto exit;
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_OFB)
     /*
      * OFB mode
      */
-    for( i = 0; i < 6; i++ )
-    {
+    for (i = 0; i < 6; i++) {
         u = i >> 1;
         keybits = 128 + u * 64;
         mode = i & 1;
 
-        if( verbose != 0 )
-            mbedtls_printf( "  AES-OFB-%3u (%s): ", keybits,
-                            ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+        if (verbose != 0) {
+            mbedtls_printf("  AES-OFB-%3u (%s): ", keybits,
+                           (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
+        }
 
-        memcpy( iv,  aes_test_ofb_iv, 16 );
-        memcpy( key, aes_test_ofb_key[u], keybits / 8 );
+        memcpy(iv,  aes_test_ofb_iv, 16);
+        memcpy(key, aes_test_ofb_key[u], keybits / 8);
 
         offset = 0;
-        ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
+        ret = mbedtls_aes_setkey_enc(&ctx, key, keybits);
         /*
          * AES-192 is an optional feature that may be unavailable when
          * there is an alternative underlying implementation i.e. when
          * MBEDTLS_AES_ALT is defined.
          */
-        if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 )
-        {
-            mbedtls_printf( "skipped\n" );
+        if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) {
+            mbedtls_printf("skipped\n");
             continue;
-        }
-        else if( ret != 0 )
-        {
+        } else if (ret != 0) {
             goto exit;
         }
 
-        if( mode == MBEDTLS_AES_DECRYPT )
-        {
-            memcpy( buf, aes_test_ofb_ct[u], 64 );
+        if (mode == MBEDTLS_AES_DECRYPT) {
+            memcpy(buf, aes_test_ofb_ct[u], 64);
             aes_tests = aes_test_ofb_pt;
-        }
-        else
-        {
-            memcpy( buf, aes_test_ofb_pt, 64 );
+        } else {
+            memcpy(buf, aes_test_ofb_pt, 64);
             aes_tests = aes_test_ofb_ct[u];
         }
 
-        ret = mbedtls_aes_crypt_ofb( &ctx, 64, &offset, iv, buf, buf );
-        if( ret != 0 )
+        ret = mbedtls_aes_crypt_ofb(&ctx, 64, &offset, iv, buf, buf);
+        if (ret != 0) {
             goto exit;
+        }
 
-        if( memcmp( buf, aes_tests, 64 ) != 0 )
-        {
+        if (memcmp(buf, aes_tests, 64) != 0) {
             ret = 1;
             goto exit;
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 #endif /* MBEDTLS_CIPHER_MODE_OFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     /*
      * CTR mode
      */
-    for( i = 0; i < 6; i++ )
-    {
+    for (i = 0; i < 6; i++) {
         u = i >> 1;
         mode = i & 1;
 
-        if( verbose != 0 )
-            mbedtls_printf( "  AES-CTR-128 (%s): ",
-                            ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+        if (verbose != 0) {
+            mbedtls_printf("  AES-CTR-128 (%s): ",
+                           (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
+        }
 
-        memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 );
-        memcpy( key, aes_test_ctr_key[u], 16 );
+        memcpy(nonce_counter, aes_test_ctr_nonce_counter[u], 16);
+        memcpy(key, aes_test_ctr_key[u], 16);
 
         offset = 0;
-        if( ( ret = mbedtls_aes_setkey_enc( &ctx, key, 128 ) ) != 0 )
+        if ((ret = mbedtls_aes_setkey_enc(&ctx, key, 128)) != 0) {
             goto exit;
+        }
 
         len = aes_test_ctr_len[u];
 
-        if( mode == MBEDTLS_AES_DECRYPT )
-        {
-            memcpy( buf, aes_test_ctr_ct[u], len );
+        if (mode == MBEDTLS_AES_DECRYPT) {
+            memcpy(buf, aes_test_ctr_ct[u], len);
             aes_tests = aes_test_ctr_pt[u];
-        }
-        else
-        {
-            memcpy( buf, aes_test_ctr_pt[u], len );
+        } else {
+            memcpy(buf, aes_test_ctr_pt[u], len);
             aes_tests = aes_test_ctr_ct[u];
         }
 
-        ret = mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter,
-                                     stream_block, buf, buf );
-        if( ret != 0 )
+        ret = mbedtls_aes_crypt_ctr(&ctx, len, &offset, nonce_counter,
+                                    stream_block, buf, buf);
+        if (ret != 0) {
             goto exit;
+        }
 
-        if( memcmp( buf, aes_tests, len ) != 0 )
-        {
+        if (memcmp(buf, aes_tests, len) != 0) {
             ret = 1;
             goto exit;
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
 #if defined(MBEDTLS_CIPHER_MODE_XTS)
     {
-    static const int num_tests =
-        sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key);
-    mbedtls_aes_xts_context ctx_xts;
+        static const int num_tests =
+            sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key);
+        mbedtls_aes_xts_context ctx_xts;
 
-    /*
-     * XTS mode
-     */
-    mbedtls_aes_xts_init( &ctx_xts );
+        /*
+         * XTS mode
+         */
+        mbedtls_aes_xts_init(&ctx_xts);
 
-    for( i = 0; i < num_tests << 1; i++ )
-    {
-        const unsigned char *data_unit;
-        u = i >> 1;
-        mode = i & 1;
+        for (i = 0; i < num_tests << 1; i++) {
+            const unsigned char *data_unit;
+            u = i >> 1;
+            mode = i & 1;
 
-        if( verbose != 0 )
-            mbedtls_printf( "  AES-XTS-128 (%s): ",
-                            ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+            if (verbose != 0) {
+                mbedtls_printf("  AES-XTS-128 (%s): ",
+                               (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
+            }
 
-        memset( key, 0, sizeof( key ) );
-        memcpy( key, aes_test_xts_key[u], 32 );
-        data_unit = aes_test_xts_data_unit[u];
+            memset(key, 0, sizeof(key));
+            memcpy(key, aes_test_xts_key[u], 32);
+            data_unit = aes_test_xts_data_unit[u];
 
-        len = sizeof( *aes_test_xts_ct32 );
+            len = sizeof(*aes_test_xts_ct32);
 
-        if( mode == MBEDTLS_AES_DECRYPT )
-        {
-            ret = mbedtls_aes_xts_setkey_dec( &ctx_xts, key, 256 );
-            if( ret != 0)
+            if (mode == MBEDTLS_AES_DECRYPT) {
+                ret = mbedtls_aes_xts_setkey_dec(&ctx_xts, key, 256);
+                if (ret != 0) {
+                    goto exit;
+                }
+                memcpy(buf, aes_test_xts_ct32[u], len);
+                aes_tests = aes_test_xts_pt32[u];
+            } else {
+                ret = mbedtls_aes_xts_setkey_enc(&ctx_xts, key, 256);
+                if (ret != 0) {
+                    goto exit;
+                }
+                memcpy(buf, aes_test_xts_pt32[u], len);
+                aes_tests = aes_test_xts_ct32[u];
+            }
+
+
+            ret = mbedtls_aes_crypt_xts(&ctx_xts, mode, len, data_unit,
+                                        buf, buf);
+            if (ret != 0) {
                 goto exit;
-            memcpy( buf, aes_test_xts_ct32[u], len );
-            aes_tests = aes_test_xts_pt32[u];
-        }
-        else
-        {
-            ret = mbedtls_aes_xts_setkey_enc( &ctx_xts, key, 256 );
-            if( ret != 0)
+            }
+
+            if (memcmp(buf, aes_tests, len) != 0) {
+                ret = 1;
                 goto exit;
-            memcpy( buf, aes_test_xts_pt32[u], len );
-            aes_tests = aes_test_xts_ct32[u];
+            }
+
+            if (verbose != 0) {
+                mbedtls_printf("passed\n");
+            }
         }
 
-
-        ret = mbedtls_aes_crypt_xts( &ctx_xts, mode, len, data_unit,
-                                     buf, buf );
-        if( ret != 0 )
-            goto exit;
-
-        if( memcmp( buf, aes_tests, len ) != 0 )
-        {
-            ret = 1;
-            goto exit;
+        if (verbose != 0) {
+            mbedtls_printf("\n");
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
-    }
-
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
-
-    mbedtls_aes_xts_free( &ctx_xts );
+        mbedtls_aes_xts_free(&ctx_xts);
     }
 #endif /* MBEDTLS_CIPHER_MODE_XTS */
 
     ret = 0;
 
 exit:
-    if( ret != 0 && verbose != 0 )
-        mbedtls_printf( "failed\n" );
+    if (ret != 0 && verbose != 0) {
+        mbedtls_printf("failed\n");
+    }
 
-    mbedtls_aes_free( &ctx );
+    mbedtls_aes_free(&ctx);
 
-    return( ret );
+    return ret;
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/lib/libmbedtls/mbedtls/library/aesce.c b/lib/libmbedtls/mbedtls/library/aesce.c
new file mode 100644
index 0000000..fe056dc
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/aesce.c
@@ -0,0 +1,411 @@
+/*
+ *  Armv8-A Cryptographic Extension support functions for Aarch64
+ *
+ *  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.
+ */
+
+#if defined(__aarch64__) && !defined(__ARM_FEATURE_CRYPTO) && \
+    defined(__clang__) && __clang_major__ >= 4
+/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged.
+ *
+ * The intrinsic declaration are guarded by predefined ACLE macros in clang:
+ * these are normally only enabled by the -march option on the command line.
+ * By defining the macros ourselves we gain access to those declarations without
+ * requiring -march on the command line.
+ *
+ * `arm_neon.h` could be included by any header file, so we put these defines
+ * at the top of this file, before any includes.
+ */
+#define __ARM_FEATURE_CRYPTO 1
+/* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions
+ *
+ * `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it
+ * for older compilers.
+ */
+#define __ARM_FEATURE_AES    1
+#define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG
+#endif
+
+#include <string.h>
+#include "common.h"
+
+#if defined(MBEDTLS_AESCE_C)
+
+#include "aesce.h"
+
+#if defined(MBEDTLS_HAVE_ARM64)
+
+#if !defined(__ARM_FEATURE_AES) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG)
+#   if defined(__clang__)
+#       if __clang_major__ < 4
+#           error "A more recent Clang is required for MBEDTLS_AESCE_C"
+#       endif
+#       pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function)
+#       define MBEDTLS_POP_TARGET_PRAGMA
+#   elif defined(__GNUC__)
+#       if __GNUC__ < 6
+#           error "A more recent GCC is required for MBEDTLS_AESCE_C"
+#       endif
+#       pragma GCC push_options
+#       pragma GCC target ("arch=armv8-a+crypto")
+#       define MBEDTLS_POP_TARGET_PRAGMA
+#   else
+#       error "Only GCC and Clang supported for MBEDTLS_AESCE_C"
+#   endif
+#endif /* !__ARM_FEATURE_AES || MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG */
+
+#include <arm_neon.h>
+
+#if defined(__linux__)
+#include <asm/hwcap.h>
+#include <sys/auxv.h>
+#endif
+
+/*
+ * AES instruction support detection routine
+ */
+int mbedtls_aesce_has_support(void)
+{
+#if defined(__linux__)
+    unsigned long auxval = getauxval(AT_HWCAP);
+    return (auxval & (HWCAP_ASIMD | HWCAP_AES)) ==
+           (HWCAP_ASIMD | HWCAP_AES);
+#else
+    /* Assume AES instructions are supported. */
+    return 1;
+#endif
+}
+
+static uint8x16_t aesce_encrypt_block(uint8x16_t block,
+                                      unsigned char *keys,
+                                      int rounds)
+{
+    for (int i = 0; i < rounds - 1; i++) {
+        /* AES AddRoundKey, SubBytes, ShiftRows (in this order).
+         * AddRoundKey adds the round key for the previous round. */
+        block = vaeseq_u8(block, vld1q_u8(keys + i * 16));
+        /* AES mix columns */
+        block = vaesmcq_u8(block);
+    }
+
+    /* AES AddRoundKey for the previous round.
+     * SubBytes, ShiftRows for the final round.  */
+    block = vaeseq_u8(block, vld1q_u8(keys + (rounds -1) * 16));
+
+    /* Final round: no MixColumns */
+
+    /* Final AddRoundKey */
+    block = veorq_u8(block, vld1q_u8(keys + rounds  * 16));
+
+    return block;
+}
+
+static uint8x16_t aesce_decrypt_block(uint8x16_t block,
+                                      unsigned char *keys,
+                                      int rounds)
+{
+
+    for (int i = 0; i < rounds - 1; i++) {
+        /* AES AddRoundKey, SubBytes, ShiftRows */
+        block = vaesdq_u8(block, vld1q_u8(keys + i * 16));
+        /* AES inverse MixColumns for the next round.
+         *
+         * This means that we switch the order of the inverse AddRoundKey and
+         * inverse MixColumns operations. We have to do this as AddRoundKey is
+         * done in an atomic instruction together with the inverses of SubBytes
+         * and ShiftRows.
+         *
+         * It works because MixColumns is a linear operation over GF(2^8) and
+         * AddRoundKey is an exclusive or, which is equivalent to addition over
+         * GF(2^8). (The inverse of MixColumns needs to be applied to the
+         * affected round keys separately which has been done when the
+         * decryption round keys were calculated.) */
+        block = vaesimcq_u8(block);
+    }
+
+    /* The inverses of AES AddRoundKey, SubBytes, ShiftRows finishing up the
+     * last full round. */
+    block = vaesdq_u8(block, vld1q_u8(keys + (rounds - 1) * 16));
+
+    /* Inverse AddRoundKey for inverting the initial round key addition. */
+    block = veorq_u8(block, vld1q_u8(keys + rounds * 16));
+
+    return block;
+}
+
+/*
+ * AES-ECB block en(de)cryption
+ */
+int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx,
+                            int mode,
+                            const unsigned char input[16],
+                            unsigned char output[16])
+{
+    uint8x16_t block = vld1q_u8(&input[0]);
+    unsigned char *keys = (unsigned char *) (ctx->buf + ctx->rk_offset);
+
+    if (mode == MBEDTLS_AES_ENCRYPT) {
+        block = aesce_encrypt_block(block, keys, ctx->nr);
+    } else {
+        block = aesce_decrypt_block(block, keys, ctx->nr);
+    }
+    vst1q_u8(&output[0], block);
+
+    return 0;
+}
+
+/*
+ * Compute decryption round keys from encryption round keys
+ */
+void mbedtls_aesce_inverse_key(unsigned char *invkey,
+                               const unsigned char *fwdkey,
+                               int nr)
+{
+    int i, j;
+    j = nr;
+    vst1q_u8(invkey, vld1q_u8(fwdkey + j * 16));
+    for (i = 1, j--; j > 0; i++, j--) {
+        vst1q_u8(invkey + i * 16,
+                 vaesimcq_u8(vld1q_u8(fwdkey + j * 16)));
+    }
+    vst1q_u8(invkey + i * 16, vld1q_u8(fwdkey + j * 16));
+
+}
+
+static inline uint32_t aes_rot_word(uint32_t word)
+{
+    return (word << (32 - 8)) | (word >> 8);
+}
+
+static inline uint32_t aes_sub_word(uint32_t in)
+{
+    uint8x16_t v = vreinterpretq_u8_u32(vdupq_n_u32(in));
+    uint8x16_t zero = vdupq_n_u8(0);
+
+    /* vaeseq_u8 does both SubBytes and ShiftRows. Taking the first row yields
+     * the correct result as ShiftRows doesn't change the first row. */
+    v = vaeseq_u8(zero, v);
+    return vgetq_lane_u32(vreinterpretq_u32_u8(v), 0);
+}
+
+/*
+ * Key expansion function
+ */
+static void aesce_setkey_enc(unsigned char *rk,
+                             const unsigned char *key,
+                             const size_t key_bit_length)
+{
+    static uint8_t const rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10,
+                                    0x20, 0x40, 0x80, 0x1b, 0x36 };
+    /* See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf
+     *   - Section 5, Nr = Nk + 6
+     *   - Section 5.2, the length of round keys is Nb*(Nr+1)
+     */
+    const uint32_t key_len_in_words = key_bit_length / 32;  /* Nk */
+    const size_t round_key_len_in_words = 4;                /* Nb */
+    const size_t rounds_needed = key_len_in_words + 6;      /* Nr */
+    const size_t round_keys_len_in_words =
+        round_key_len_in_words * (rounds_needed + 1);       /* Nb*(Nr+1) */
+    const uint32_t *rko_end = (uint32_t *) rk + round_keys_len_in_words;
+
+    memcpy(rk, key, key_len_in_words * 4);
+
+    for (uint32_t *rki = (uint32_t *) rk;
+         rki + key_len_in_words < rko_end;
+         rki += key_len_in_words) {
+
+        size_t iteration = (rki - (uint32_t *) rk) / key_len_in_words;
+        uint32_t *rko;
+        rko = rki + key_len_in_words;
+        rko[0] = aes_rot_word(aes_sub_word(rki[key_len_in_words - 1]));
+        rko[0] ^= rcon[iteration] ^ rki[0];
+        rko[1] = rko[0] ^ rki[1];
+        rko[2] = rko[1] ^ rki[2];
+        rko[3] = rko[2] ^ rki[3];
+        if (rko + key_len_in_words > rko_end) {
+            /* Do not write overflow words.*/
+            continue;
+        }
+        switch (key_bit_length) {
+            case 128:
+                break;
+            case 192:
+                rko[4] = rko[3] ^ rki[4];
+                rko[5] = rko[4] ^ rki[5];
+                break;
+            case 256:
+                rko[4] = aes_sub_word(rko[3]) ^ rki[4];
+                rko[5] = rko[4] ^ rki[5];
+                rko[6] = rko[5] ^ rki[6];
+                rko[7] = rko[6] ^ rki[7];
+                break;
+        }
+    }
+}
+
+/*
+ * Key expansion, wrapper
+ */
+int mbedtls_aesce_setkey_enc(unsigned char *rk,
+                             const unsigned char *key,
+                             size_t bits)
+{
+    switch (bits) {
+        case 128:
+        case 192:
+        case 256:
+            aesce_setkey_enc(rk, key, bits);
+            break;
+        default:
+            return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
+    }
+
+    return 0;
+}
+
+#if defined(MBEDTLS_GCM_C)
+
+#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ == 5
+/* Some intrinsics are not available for GCC 5.X. */
+#define vreinterpretq_p64_u8(a) ((poly64x2_t) a)
+#define vreinterpretq_u8_p128(a) ((uint8x16_t) a)
+static inline poly64_t vget_low_p64(poly64x2_t __a)
+{
+    uint64x2_t tmp = (uint64x2_t) (__a);
+    uint64x1_t lo = vcreate_u64(vgetq_lane_u64(tmp, 0));
+    return (poly64_t) (lo);
+}
+#endif /* !__clang__ && __GNUC__ && __GNUC__ == 5*/
+
+/* vmull_p64/vmull_high_p64 wrappers.
+ *
+ * Older compilers miss some intrinsic functions for `poly*_t`. We use
+ * uint8x16_t and uint8x16x3_t as input/output parameters.
+ */
+static inline uint8x16_t pmull_low(uint8x16_t a, uint8x16_t b)
+{
+    return vreinterpretq_u8_p128(
+        vmull_p64(
+            (poly64_t) vget_low_p64(vreinterpretq_p64_u8(a)),
+            (poly64_t) vget_low_p64(vreinterpretq_p64_u8(b))));
+}
+
+static inline uint8x16_t pmull_high(uint8x16_t a, uint8x16_t b)
+{
+    return vreinterpretq_u8_p128(
+        vmull_high_p64(vreinterpretq_p64_u8(a),
+                       vreinterpretq_p64_u8(b)));
+}
+
+/* GHASH does 128b polynomial multiplication on block in GF(2^128) defined by
+ * `x^128 + x^7 + x^2 + x + 1`.
+ *
+ * Arm64 only has 64b->128b polynomial multipliers, we need to do 4 64b
+ * multiplies to generate a 128b.
+ *
+ * `poly_mult_128` executes polynomial multiplication and outputs 256b that
+ * represented by 3 128b due to code size optimization.
+ *
+ * Output layout:
+ * |            |             |             |
+ * |------------|-------------|-------------|
+ * | ret.val[0] | h3:h2:00:00 | high   128b |
+ * | ret.val[1] |   :m2:m1:00 | middle 128b |
+ * | ret.val[2] |   :  :l1:l0 | low    128b |
+ */
+static inline uint8x16x3_t poly_mult_128(uint8x16_t a, uint8x16_t b)
+{
+    uint8x16x3_t ret;
+    uint8x16_t h, m, l; /* retval high/middle/low */
+    uint8x16_t c, d, e;
+
+    h = pmull_high(a, b);                       /* h3:h2:00:00 = a1*b1 */
+    l = pmull_low(a, b);                        /*   :  :l1:l0 = a0*b0 */
+    c = vextq_u8(b, b, 8);                      /*      :c1:c0 = b0:b1 */
+    d = pmull_high(a, c);                       /*   :d2:d1:00 = a1*b0 */
+    e = pmull_low(a, c);                        /*   :e2:e1:00 = a0*b1 */
+    m = veorq_u8(d, e);                         /*   :m2:m1:00 = d + e */
+
+    ret.val[0] = h;
+    ret.val[1] = m;
+    ret.val[2] = l;
+    return ret;
+}
+
+/*
+ * Modulo reduction.
+ *
+ * See: https://www.researchgate.net/publication/285612706_Implementing_GCM_on_ARMv8
+ *
+ * Section 4.3
+ *
+ * Modular reduction is slightly more complex. Write the GCM modulus as f(z) =
+ * z^128 +r(z), where r(z) = z^7+z^2+z+ 1. The well known approach is to
+ * consider that z^128 ≡r(z) (mod z^128 +r(z)), allowing us to write the 256-bit
+ * operand to be reduced as a(z) = h(z)z^128 +l(z)≡h(z)r(z) + l(z). That is, we
+ * simply multiply the higher part of the operand by r(z) and add it to l(z). If
+ * the result is still larger than 128 bits, we reduce again.
+ */
+static inline uint8x16_t poly_mult_reduce(uint8x16x3_t input)
+{
+    uint8x16_t const ZERO = vdupq_n_u8(0);
+    /* use 'asm' as an optimisation barrier to prevent loading MODULO from memory */
+    uint64x2_t r = vreinterpretq_u64_u8(vdupq_n_u8(0x87));
+    asm ("" : "+w" (r));
+    uint8x16_t const MODULO = vreinterpretq_u8_u64(vshrq_n_u64(r, 64 - 8));
+    uint8x16_t h, m, l; /* input high/middle/low 128b */
+    uint8x16_t c, d, e, f, g, n, o;
+    h = input.val[0];            /* h3:h2:00:00                          */
+    m = input.val[1];            /*   :m2:m1:00                          */
+    l = input.val[2];            /*   :  :l1:l0                          */
+    c = pmull_high(h, MODULO);   /*   :c2:c1:00 = reduction of h3        */
+    d = pmull_low(h, MODULO);    /*   :  :d1:d0 = reduction of h2        */
+    e = veorq_u8(c, m);          /*   :e2:e1:00 = m2:m1:00 + c2:c1:00    */
+    f = pmull_high(e, MODULO);   /*   :  :f1:f0 = reduction of e2        */
+    g = vextq_u8(ZERO, e, 8);    /*   :  :g1:00 = e1:00                  */
+    n = veorq_u8(d, l);          /*   :  :n1:n0 = d1:d0 + l1:l0          */
+    o = veorq_u8(n, f);          /*       o1:o0 = f1:f0 + n1:n0          */
+    return veorq_u8(o, g);       /*             = o1:o0 + g1:00          */
+}
+
+/*
+ * GCM multiplication: c = a times b in GF(2^128)
+ */
+void mbedtls_aesce_gcm_mult(unsigned char c[16],
+                            const unsigned char a[16],
+                            const unsigned char b[16])
+{
+    uint8x16_t va, vb, vc;
+    va = vrbitq_u8(vld1q_u8(&a[0]));
+    vb = vrbitq_u8(vld1q_u8(&b[0]));
+    vc = vrbitq_u8(poly_mult_reduce(poly_mult_128(va, vb)));
+    vst1q_u8(&c[0], vc);
+}
+
+#endif /* MBEDTLS_GCM_C */
+
+#if defined(MBEDTLS_POP_TARGET_PRAGMA)
+#if defined(__clang__)
+#pragma clang attribute pop
+#elif defined(__GNUC__)
+#pragma GCC pop_options
+#endif
+#undef MBEDTLS_POP_TARGET_PRAGMA
+#endif
+
+#endif /* MBEDTLS_HAVE_ARM64 */
+
+#endif /* MBEDTLS_AESCE_C */
diff --git a/lib/libmbedtls/mbedtls/library/aesce.h b/lib/libmbedtls/mbedtls/library/aesce.h
new file mode 100644
index 0000000..12ddc74
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/aesce.h
@@ -0,0 +1,116 @@
+/**
+ * \file aesce.h
+ *
+ * \brief Support hardware AES acceleration on Armv8-A processors with
+ *        the Armv8-A Cryptographic Extension in AArch64 execution state.
+ *
+ * \warning These functions are only for internal use by other library
+ *          functions; you must not call them directly.
+ */
+/*
+ *  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_AESCE_H
+#define MBEDTLS_AESCE_H
+
+#include "mbedtls/build_info.h"
+
+#include "mbedtls/aes.h"
+
+
+#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \
+    defined(__aarch64__) && !defined(MBEDTLS_HAVE_ARM64)
+#define MBEDTLS_HAVE_ARM64
+#endif
+
+#if defined(MBEDTLS_HAVE_ARM64)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Internal function to detect the crypto extension in CPUs.
+ *
+ * \return         1 if CPU has support for the feature, 0 otherwise
+ */
+int mbedtls_aesce_has_support(void);
+
+/**
+ * \brief          Internal AES-ECB block encryption and decryption
+ *
+ * \param ctx      AES context
+ * \param mode     MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
+ * \param input    16-byte input block
+ * \param output   16-byte output block
+ *
+ * \return         0 on success (cannot fail)
+ */
+int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx,
+                            int mode,
+                            const unsigned char input[16],
+                            unsigned char output[16]);
+
+/**
+ * \brief          Internal GCM multiplication: c = a * b in GF(2^128)
+ *
+ * \note           This function is only for internal use by other library
+ *                 functions; you must not call it directly.
+ *
+ * \param c        Result
+ * \param a        First operand
+ * \param b        Second operand
+ *
+ * \note           Both operands and result are bit strings interpreted as
+ *                 elements of GF(2^128) as per the GCM spec.
+ */
+void mbedtls_aesce_gcm_mult(unsigned char c[16],
+                            const unsigned char a[16],
+                            const unsigned char b[16]);
+
+
+/**
+ * \brief           Internal round key inversion. This function computes
+ *                  decryption round keys from the encryption round keys.
+ *
+ * \param invkey    Round keys for the equivalent inverse cipher
+ * \param fwdkey    Original round keys (for encryption)
+ * \param nr        Number of rounds (that is, number of round keys minus one)
+ */
+void mbedtls_aesce_inverse_key(unsigned char *invkey,
+                               const unsigned char *fwdkey,
+                               int nr);
+
+/**
+ * \brief           Internal key expansion for encryption
+ *
+ * \param rk        Destination buffer where the round keys are written
+ * \param key       Encryption key
+ * \param bits      Key size in bits (must be 128, 192 or 256)
+ *
+ * \return          0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
+ */
+int mbedtls_aesce_setkey_enc(unsigned char *rk,
+                             const unsigned char *key,
+                             size_t bits);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_HAVE_ARM64 */
+
+#endif /* MBEDTLS_AESCE_H */
diff --git a/lib/libmbedtls/mbedtls/library/aesni.c b/lib/libmbedtls/mbedtls/library/aesni.c
index 996292f..a23c5b5 100644
--- a/lib/libmbedtls/mbedtls/library/aesni.c
+++ b/lib/libmbedtls/mbedtls/library/aesni.c
@@ -18,51 +18,385 @@
  */
 
 /*
- * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set
- * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/
+ * [AES-WP] https://www.intel.com/content/www/us/en/developer/articles/tool/intel-advanced-encryption-standard-aes-instructions-set.html
+ * [CLMUL-WP] https://www.intel.com/content/www/us/en/develop/download/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode.html
  */
 
 #include "common.h"
 
 #if defined(MBEDTLS_AESNI_C)
 
-#if defined(__has_feature)
-#if __has_feature(memory_sanitizer)
-#warning "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code."
-#endif
-#endif
-
-#include "mbedtls/aesni.h"
+#include "aesni.h"
 
 #include <string.h>
 
-#ifndef asm
-#define asm __asm
-#endif
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
 
-#if defined(MBEDTLS_HAVE_X86_64)
+#if MBEDTLS_AESNI_HAVE_CODE == 2
+#if !defined(_WIN32)
+#include <cpuid.h>
+#endif
+#include <immintrin.h>
+#endif
 
 /*
  * AES-NI support detection routine
  */
-int mbedtls_aesni_has_support( unsigned int what )
+int mbedtls_aesni_has_support(unsigned int what)
 {
     static int done = 0;
     static unsigned int c = 0;
 
-    if( ! done )
-    {
-        asm( "movl  $1, %%eax   \n\t"
+    if (!done) {
+#if MBEDTLS_AESNI_HAVE_CODE == 2
+        static unsigned info[4] = { 0, 0, 0, 0 };
+#if defined(_MSC_VER)
+        __cpuid(info, 1);
+#else
+        __cpuid(1, info[0], info[1], info[2], info[3]);
+#endif
+        c = info[2];
+#else /* AESNI using asm */
+        asm ("movl  $1, %%eax   \n\t"
              "cpuid             \n\t"
              : "=c" (c)
              :
-             : "eax", "ebx", "edx" );
+             : "eax", "ebx", "edx");
+#endif /* MBEDTLS_AESNI_HAVE_CODE */
         done = 1;
     }
 
-    return( ( c & what ) != 0 );
+    return (c & what) != 0;
 }
 
+#if MBEDTLS_AESNI_HAVE_CODE == 2
+
+/*
+ * AES-NI AES-ECB block en(de)cryption
+ */
+int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx,
+                            int mode,
+                            const unsigned char input[16],
+                            unsigned char output[16])
+{
+    const __m128i *rk = (const __m128i *) (ctx->buf + ctx->rk_offset);
+    unsigned nr = ctx->nr; // Number of remaining rounds
+
+    // Load round key 0
+    __m128i state;
+    memcpy(&state, input, 16);
+    state = _mm_xor_si128(state, rk[0]);  // state ^= *rk;
+    ++rk;
+    --nr;
+
+    if (mode == 0) {
+        while (nr != 0) {
+            state = _mm_aesdec_si128(state, *rk);
+            ++rk;
+            --nr;
+        }
+        state = _mm_aesdeclast_si128(state, *rk);
+    } else {
+        while (nr != 0) {
+            state = _mm_aesenc_si128(state, *rk);
+            ++rk;
+            --nr;
+        }
+        state = _mm_aesenclast_si128(state, *rk);
+    }
+
+    memcpy(output, &state, 16);
+    return 0;
+}
+
+/*
+ * GCM multiplication: c = a times b in GF(2^128)
+ * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5.
+ */
+
+static void gcm_clmul(const __m128i aa, const __m128i bb,
+                      __m128i *cc, __m128i *dd)
+{
+    /*
+     * Caryless multiplication dd:cc = aa * bb
+     * using [CLMUL-WP] algorithm 1 (p. 12).
+     */
+    *cc = _mm_clmulepi64_si128(aa, bb, 0x00); // a0*b0 = c1:c0
+    *dd = _mm_clmulepi64_si128(aa, bb, 0x11); // a1*b1 = d1:d0
+    __m128i ee = _mm_clmulepi64_si128(aa, bb, 0x10); // a0*b1 = e1:e0
+    __m128i ff = _mm_clmulepi64_si128(aa, bb, 0x01); // a1*b0 = f1:f0
+    ff = _mm_xor_si128(ff, ee);                      // e1+f1:e0+f0
+    ee = ff;                                         // e1+f1:e0+f0
+    ff = _mm_srli_si128(ff, 8);                      // 0:e1+f1
+    ee = _mm_slli_si128(ee, 8);                      // e0+f0:0
+    *dd = _mm_xor_si128(*dd, ff);                    // d1:d0+e1+f1
+    *cc = _mm_xor_si128(*cc, ee);                    // c1+e0+f0:c0
+}
+
+static void gcm_shift(__m128i *cc, __m128i *dd)
+{
+    /* [CMUCL-WP] Algorithm 5 Step 1: shift cc:dd one bit to the left,
+     * taking advantage of [CLMUL-WP] eq 27 (p. 18). */
+    //                                        // *cc = r1:r0
+    //                                        // *dd = r3:r2
+    __m128i cc_lo = _mm_slli_epi64(*cc, 1);   // r1<<1:r0<<1
+    __m128i dd_lo = _mm_slli_epi64(*dd, 1);   // r3<<1:r2<<1
+    __m128i cc_hi = _mm_srli_epi64(*cc, 63);  // r1>>63:r0>>63
+    __m128i dd_hi = _mm_srli_epi64(*dd, 63);  // r3>>63:r2>>63
+    __m128i xmm5 = _mm_srli_si128(cc_hi, 8);  // 0:r1>>63
+    cc_hi = _mm_slli_si128(cc_hi, 8);         // r0>>63:0
+    dd_hi = _mm_slli_si128(dd_hi, 8);         // 0:r1>>63
+
+    *cc = _mm_or_si128(cc_lo, cc_hi);         // r1<<1|r0>>63:r0<<1
+    *dd = _mm_or_si128(_mm_or_si128(dd_lo, dd_hi), xmm5); // r3<<1|r2>>62:r2<<1|r1>>63
+}
+
+static __m128i gcm_reduce(__m128i xx)
+{
+    //                                            // xx = x1:x0
+    /* [CLMUL-WP] Algorithm 5 Step 2 */
+    __m128i aa = _mm_slli_epi64(xx, 63);          // x1<<63:x0<<63 = stuff:a
+    __m128i bb = _mm_slli_epi64(xx, 62);          // x1<<62:x0<<62 = stuff:b
+    __m128i cc = _mm_slli_epi64(xx, 57);          // x1<<57:x0<<57 = stuff:c
+    __m128i dd = _mm_slli_si128(_mm_xor_si128(_mm_xor_si128(aa, bb), cc), 8); // a+b+c:0
+    return _mm_xor_si128(dd, xx);                 // x1+a+b+c:x0 = d:x0
+}
+
+static __m128i gcm_mix(__m128i dx)
+{
+    /* [CLMUL-WP] Algorithm 5 Steps 3 and 4 */
+    __m128i ee = _mm_srli_epi64(dx, 1);           // e1:x0>>1 = e1:e0'
+    __m128i ff = _mm_srli_epi64(dx, 2);           // f1:x0>>2 = f1:f0'
+    __m128i gg = _mm_srli_epi64(dx, 7);           // g1:x0>>7 = g1:g0'
+
+    // e0'+f0'+g0' is almost e0+f0+g0, except for some missing
+    // bits carried from d. Now get those bits back in.
+    __m128i eh = _mm_slli_epi64(dx, 63);          // d<<63:stuff
+    __m128i fh = _mm_slli_epi64(dx, 62);          // d<<62:stuff
+    __m128i gh = _mm_slli_epi64(dx, 57);          // d<<57:stuff
+    __m128i hh = _mm_srli_si128(_mm_xor_si128(_mm_xor_si128(eh, fh), gh), 8); // 0:missing bits of d
+
+    return _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(_mm_xor_si128(ee, ff), gg), hh), dx);
+}
+
+void mbedtls_aesni_gcm_mult(unsigned char c[16],
+                            const unsigned char a[16],
+                            const unsigned char b[16])
+{
+    __m128i aa, bb, cc, dd;
+
+    /* The inputs are in big-endian order, so byte-reverse them */
+    for (size_t i = 0; i < 16; i++) {
+        ((uint8_t *) &aa)[i] = a[15 - i];
+        ((uint8_t *) &bb)[i] = b[15 - i];
+    }
+
+    gcm_clmul(aa, bb, &cc, &dd);
+    gcm_shift(&cc, &dd);
+    /*
+     * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1
+     * using [CLMUL-WP] algorithm 5 (p. 18).
+     * Currently dd:cc holds x3:x2:x1:x0 (already shifted).
+     */
+    __m128i dx = gcm_reduce(cc);
+    __m128i xh = gcm_mix(dx);
+    cc = _mm_xor_si128(xh, dd); // x3+h1:x2+h0
+
+    /* Now byte-reverse the outputs */
+    for (size_t i = 0; i < 16; i++) {
+        c[i] = ((uint8_t *) &cc)[15 - i];
+    }
+
+    return;
+}
+
+/*
+ * Compute decryption round keys from encryption round keys
+ */
+void mbedtls_aesni_inverse_key(unsigned char *invkey,
+                               const unsigned char *fwdkey, int nr)
+{
+    __m128i *ik = (__m128i *) invkey;
+    const __m128i *fk = (const __m128i *) fwdkey + nr;
+
+    *ik = *fk;
+    for (--fk, ++ik; fk > (const __m128i *) fwdkey; --fk, ++ik) {
+        *ik = _mm_aesimc_si128(*fk);
+    }
+    *ik = *fk;
+}
+
+/*
+ * Key expansion, 128-bit case
+ */
+static __m128i aesni_set_rk_128(__m128i state, __m128i xword)
+{
+    /*
+     * Finish generating the next round key.
+     *
+     * On entry state is r3:r2:r1:r0 and xword is X:stuff:stuff:stuff
+     * with X = rot( sub( r3 ) ) ^ RCON (obtained with AESKEYGENASSIST).
+     *
+     * On exit, xword is r7:r6:r5:r4
+     * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3
+     * and this is returned, to be written to the round key buffer.
+     */
+    xword = _mm_shuffle_epi32(xword, 0xff);   // X:X:X:X
+    xword = _mm_xor_si128(xword, state);      // X+r3:X+r2:X+r1:r4
+    state = _mm_slli_si128(state, 4);         // r2:r1:r0:0
+    xword = _mm_xor_si128(xword, state);      // X+r3+r2:X+r2+r1:r5:r4
+    state = _mm_slli_si128(state, 4);         // r1:r0:0:0
+    xword = _mm_xor_si128(xword, state);      // X+r3+r2+r1:r6:r5:r4
+    state = _mm_slli_si128(state, 4);         // r0:0:0:0
+    state = _mm_xor_si128(xword, state);      // r7:r6:r5:r4
+    return state;
+}
+
+static void aesni_setkey_enc_128(unsigned char *rk_bytes,
+                                 const unsigned char *key)
+{
+    __m128i *rk = (__m128i *) rk_bytes;
+
+    memcpy(&rk[0], key, 16);
+    rk[1] = aesni_set_rk_128(rk[0], _mm_aeskeygenassist_si128(rk[0], 0x01));
+    rk[2] = aesni_set_rk_128(rk[1], _mm_aeskeygenassist_si128(rk[1], 0x02));
+    rk[3] = aesni_set_rk_128(rk[2], _mm_aeskeygenassist_si128(rk[2], 0x04));
+    rk[4] = aesni_set_rk_128(rk[3], _mm_aeskeygenassist_si128(rk[3], 0x08));
+    rk[5] = aesni_set_rk_128(rk[4], _mm_aeskeygenassist_si128(rk[4], 0x10));
+    rk[6] = aesni_set_rk_128(rk[5], _mm_aeskeygenassist_si128(rk[5], 0x20));
+    rk[7] = aesni_set_rk_128(rk[6], _mm_aeskeygenassist_si128(rk[6], 0x40));
+    rk[8] = aesni_set_rk_128(rk[7], _mm_aeskeygenassist_si128(rk[7], 0x80));
+    rk[9] = aesni_set_rk_128(rk[8], _mm_aeskeygenassist_si128(rk[8], 0x1B));
+    rk[10] = aesni_set_rk_128(rk[9], _mm_aeskeygenassist_si128(rk[9], 0x36));
+}
+
+/*
+ * Key expansion, 192-bit case
+ */
+static void aesni_set_rk_192(__m128i *state0, __m128i *state1, __m128i xword,
+                             unsigned char *rk)
+{
+    /*
+     * Finish generating the next 6 quarter-keys.
+     *
+     * On entry state0 is r3:r2:r1:r0, state1 is stuff:stuff:r5:r4
+     * and xword is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON
+     * (obtained with AESKEYGENASSIST).
+     *
+     * On exit, state0 is r9:r8:r7:r6 and state1 is stuff:stuff:r11:r10
+     * and those are written to the round key buffer.
+     */
+    xword = _mm_shuffle_epi32(xword, 0x55);   // X:X:X:X
+    xword = _mm_xor_si128(xword, *state0);    // X+r3:X+r2:X+r1:X+r0
+    *state0 = _mm_slli_si128(*state0, 4);     // r2:r1:r0:0
+    xword = _mm_xor_si128(xword, *state0);    // X+r3+r2:X+r2+r1:X+r1+r0:X+r0
+    *state0 = _mm_slli_si128(*state0, 4);     // r1:r0:0:0
+    xword = _mm_xor_si128(xword, *state0);    // X+r3+r2+r1:X+r2+r1+r0:X+r1+r0:X+r0
+    *state0 = _mm_slli_si128(*state0, 4);     // r0:0:0:0
+    xword = _mm_xor_si128(xword, *state0);    // X+r3+r2+r1+r0:X+r2+r1+r0:X+r1+r0:X+r0
+    *state0 = xword;                          // = r9:r8:r7:r6
+
+    xword = _mm_shuffle_epi32(xword, 0xff);   // r9:r9:r9:r9
+    xword = _mm_xor_si128(xword, *state1);    // stuff:stuff:r9+r5:r9+r4
+    *state1 = _mm_slli_si128(*state1, 4);     // stuff:stuff:r4:0
+    xword = _mm_xor_si128(xword, *state1);    // stuff:stuff:r9+r5+r4:r9+r4
+    *state1 = xword;                          // = stuff:stuff:r11:r10
+
+    /* Store state0 and the low half of state1 into rk, which is conceptually
+     * an array of 24-byte elements. Since 24 is not a multiple of 16,
+     * rk is not necessarily aligned so just `*rk = *state0` doesn't work. */
+    memcpy(rk, state0, 16);
+    memcpy(rk + 16, state1, 8);
+}
+
+static void aesni_setkey_enc_192(unsigned char *rk,
+                                 const unsigned char *key)
+{
+    /* First round: use original key */
+    memcpy(rk, key, 24);
+    /* aes.c guarantees that rk is aligned on a 16-byte boundary. */
+    __m128i state0 = ((__m128i *) rk)[0];
+    __m128i state1 = _mm_loadl_epi64(((__m128i *) rk) + 1);
+
+    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x01), rk + 24 * 1);
+    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x02), rk + 24 * 2);
+    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x04), rk + 24 * 3);
+    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x08), rk + 24 * 4);
+    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x10), rk + 24 * 5);
+    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x20), rk + 24 * 6);
+    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x40), rk + 24 * 7);
+    aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x80), rk + 24 * 8);
+}
+
+/*
+ * Key expansion, 256-bit case
+ */
+static void aesni_set_rk_256(__m128i state0, __m128i state1, __m128i xword,
+                             __m128i *rk0, __m128i *rk1)
+{
+    /*
+     * Finish generating the next two round keys.
+     *
+     * On entry state0 is r3:r2:r1:r0, state1 is r7:r6:r5:r4 and
+     * xword is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON
+     * (obtained with AESKEYGENASSIST).
+     *
+     * On exit, *rk0 is r11:r10:r9:r8 and *rk1 is r15:r14:r13:r12
+     */
+    xword = _mm_shuffle_epi32(xword, 0xff);
+    xword = _mm_xor_si128(xword, state0);
+    state0 = _mm_slli_si128(state0, 4);
+    xword = _mm_xor_si128(xword, state0);
+    state0 = _mm_slli_si128(state0, 4);
+    xword = _mm_xor_si128(xword, state0);
+    state0 = _mm_slli_si128(state0, 4);
+    state0 = _mm_xor_si128(state0, xword);
+    *rk0 = state0;
+
+    /* Set xword to stuff:Y:stuff:stuff with Y = subword( r11 )
+     * and proceed to generate next round key from there */
+    xword = _mm_aeskeygenassist_si128(state0, 0x00);
+    xword = _mm_shuffle_epi32(xword, 0xaa);
+    xword = _mm_xor_si128(xword, state1);
+    state1 = _mm_slli_si128(state1, 4);
+    xword = _mm_xor_si128(xword, state1);
+    state1 = _mm_slli_si128(state1, 4);
+    xword = _mm_xor_si128(xword, state1);
+    state1 = _mm_slli_si128(state1, 4);
+    state1 = _mm_xor_si128(state1, xword);
+    *rk1 = state1;
+}
+
+static void aesni_setkey_enc_256(unsigned char *rk_bytes,
+                                 const unsigned char *key)
+{
+    __m128i *rk = (__m128i *) rk_bytes;
+
+    memcpy(&rk[0], key, 16);
+    memcpy(&rk[1], key + 16, 16);
+
+    /*
+     * Main "loop" - Generating one more key than necessary,
+     * see definition of mbedtls_aes_context.buf
+     */
+    aesni_set_rk_256(rk[0], rk[1], _mm_aeskeygenassist_si128(rk[1], 0x01), &rk[2], &rk[3]);
+    aesni_set_rk_256(rk[2], rk[3], _mm_aeskeygenassist_si128(rk[3], 0x02), &rk[4], &rk[5]);
+    aesni_set_rk_256(rk[4], rk[5], _mm_aeskeygenassist_si128(rk[5], 0x04), &rk[6], &rk[7]);
+    aesni_set_rk_256(rk[6], rk[7], _mm_aeskeygenassist_si128(rk[7], 0x08), &rk[8], &rk[9]);
+    aesni_set_rk_256(rk[8], rk[9], _mm_aeskeygenassist_si128(rk[9], 0x10), &rk[10], &rk[11]);
+    aesni_set_rk_256(rk[10], rk[11], _mm_aeskeygenassist_si128(rk[11], 0x20), &rk[12], &rk[13]);
+    aesni_set_rk_256(rk[12], rk[13], _mm_aeskeygenassist_si128(rk[13], 0x40), &rk[14], &rk[15]);
+}
+
+#else /* MBEDTLS_AESNI_HAVE_CODE == 1 */
+
+#if defined(__has_feature)
+#if __has_feature(memory_sanitizer)
+#warning \
+    "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code."
+#endif
+#endif
+
 /*
  * Binutils needs to be at least 2.19 to support AES-NI instructions.
  * Unfortunately, a lot of users have a lower version now (2014-04).
@@ -73,13 +407,13 @@
  * Operand macros are in gas order (src, dst) as opposed to Intel order
  * (dst, src) in order to blend better into the surrounding assembly code.
  */
-#define AESDEC      ".byte 0x66,0x0F,0x38,0xDE,"
-#define AESDECLAST  ".byte 0x66,0x0F,0x38,0xDF,"
-#define AESENC      ".byte 0x66,0x0F,0x38,0xDC,"
-#define AESENCLAST  ".byte 0x66,0x0F,0x38,0xDD,"
-#define AESIMC      ".byte 0x66,0x0F,0x38,0xDB,"
-#define AESKEYGENA  ".byte 0x66,0x0F,0x3A,0xDF,"
-#define PCLMULQDQ   ".byte 0x66,0x0F,0x3A,0x44,"
+#define AESDEC(regs)      ".byte 0x66,0x0F,0x38,0xDE," regs "\n\t"
+#define AESDECLAST(regs)  ".byte 0x66,0x0F,0x38,0xDF," regs "\n\t"
+#define AESENC(regs)      ".byte 0x66,0x0F,0x38,0xDC," regs "\n\t"
+#define AESENCLAST(regs)  ".byte 0x66,0x0F,0x38,0xDD," regs "\n\t"
+#define AESIMC(regs)      ".byte 0x66,0x0F,0x38,0xDB," regs "\n\t"
+#define AESKEYGENA(regs, imm)  ".byte 0x66,0x0F,0x3A,0xDF," regs "," imm "\n\t"
+#define PCLMULQDQ(regs, imm)   ".byte 0x66,0x0F,0x3A,0x44," regs "," imm "\n\t"
 
 #define xmm0_xmm0   "0xC0"
 #define xmm0_xmm1   "0xC8"
@@ -92,12 +426,12 @@
 /*
  * AES-NI AES-ECB block en(de)cryption
  */
-int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx,
-                     int mode,
-                     const unsigned char input[16],
-                     unsigned char output[16] )
+int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx,
+                            int mode,
+                            const unsigned char input[16],
+                            unsigned char output[16])
 {
-    asm( "movdqu    (%3), %%xmm0    \n\t" // load input
+    asm ("movdqu    (%3), %%xmm0    \n\t" // load input
          "movdqu    (%1), %%xmm1    \n\t" // load round key 0
          "pxor      %%xmm1, %%xmm0  \n\t" // round 0
          "add       $16, %1         \n\t" // point to next round key
@@ -107,65 +441,64 @@
 
          "1:                        \n\t" // encryption loop
          "movdqu    (%1), %%xmm1    \n\t" // load round key
-         AESENC     xmm1_xmm0      "\n\t" // do round
+         AESENC(xmm1_xmm0)                // do round
          "add       $16, %1         \n\t" // point to next round key
          "subl      $1, %0          \n\t" // loop
          "jnz       1b              \n\t"
          "movdqu    (%1), %%xmm1    \n\t" // load round key
-         AESENCLAST xmm1_xmm0      "\n\t" // last round
+         AESENCLAST(xmm1_xmm0)            // last round
          "jmp       3f              \n\t"
 
          "2:                        \n\t" // decryption loop
          "movdqu    (%1), %%xmm1    \n\t"
-         AESDEC     xmm1_xmm0      "\n\t" // do round
+         AESDEC(xmm1_xmm0)                // do round
          "add       $16, %1         \n\t"
          "subl      $1, %0          \n\t"
          "jnz       2b              \n\t"
          "movdqu    (%1), %%xmm1    \n\t" // load round key
-         AESDECLAST xmm1_xmm0      "\n\t" // last round
+         AESDECLAST(xmm1_xmm0)            // last round
 
          "3:                        \n\t"
          "movdqu    %%xmm0, (%4)    \n\t" // export output
          :
-         : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output)
-         : "memory", "cc", "xmm0", "xmm1" );
+         : "r" (ctx->nr), "r" (ctx->buf + ctx->rk_offset), "r" (mode), "r" (input), "r" (output)
+         : "memory", "cc", "xmm0", "xmm1");
 
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * GCM multiplication: c = a times b in GF(2^128)
  * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5.
  */
-void mbedtls_aesni_gcm_mult( unsigned char c[16],
-                     const unsigned char a[16],
-                     const unsigned char b[16] )
+void mbedtls_aesni_gcm_mult(unsigned char c[16],
+                            const unsigned char a[16],
+                            const unsigned char b[16])
 {
     unsigned char aa[16], bb[16], cc[16];
     size_t i;
 
     /* The inputs are in big-endian order, so byte-reverse them */
-    for( i = 0; i < 16; i++ )
-    {
+    for (i = 0; i < 16; i++) {
         aa[i] = a[15 - i];
         bb[i] = b[15 - i];
     }
 
-    asm( "movdqu (%0), %%xmm0               \n\t" // a1:a0
+    asm ("movdqu (%0), %%xmm0               \n\t" // a1:a0
          "movdqu (%1), %%xmm1               \n\t" // b1:b0
 
          /*
           * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1
-          * using [CLMUL-WP] algorithm 1 (p. 13).
+          * using [CLMUL-WP] algorithm 1 (p. 12).
           */
          "movdqa %%xmm1, %%xmm2             \n\t" // copy of b1:b0
          "movdqa %%xmm1, %%xmm3             \n\t" // same
          "movdqa %%xmm1, %%xmm4             \n\t" // same
-         PCLMULQDQ xmm0_xmm1 ",0x00         \n\t" // a0*b0 = c1:c0
-         PCLMULQDQ xmm0_xmm2 ",0x11         \n\t" // a1*b1 = d1:d0
-         PCLMULQDQ xmm0_xmm3 ",0x10         \n\t" // a0*b1 = e1:e0
-         PCLMULQDQ xmm0_xmm4 ",0x01         \n\t" // a1*b0 = f1:f0
+         PCLMULQDQ(xmm0_xmm1, "0x00")             // a0*b0 = c1:c0
+         PCLMULQDQ(xmm0_xmm2, "0x11")             // a1*b1 = d1:d0
+         PCLMULQDQ(xmm0_xmm3, "0x10")             // a0*b1 = e1:e0
+         PCLMULQDQ(xmm0_xmm4, "0x01")             // a1*b0 = f1:f0
          "pxor %%xmm3, %%xmm4               \n\t" // e1+f1:e0+f0
          "movdqa %%xmm4, %%xmm3             \n\t" // same
          "psrldq $8, %%xmm4                 \n\t" // 0:e1+f1
@@ -175,7 +508,7 @@
 
          /*
           * Now shift the result one bit to the left,
-          * taking advantage of [CLMUL-WP] eq 27 (p. 20)
+          * taking advantage of [CLMUL-WP] eq 27 (p. 18)
           */
          "movdqa %%xmm1, %%xmm3             \n\t" // r1:r0
          "movdqa %%xmm2, %%xmm4             \n\t" // r3:r2
@@ -193,7 +526,7 @@
 
          /*
           * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1
-          * using [CLMUL-WP] algorithm 5 (p. 20).
+          * using [CLMUL-WP] algorithm 5 (p. 18).
           * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted).
           */
          /* Step 2 (1) */
@@ -237,11 +570,12 @@
          "movdqu %%xmm0, (%2)               \n\t" // done
          :
          : "r" (aa), "r" (bb), "r" (cc)
-         : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" );
+         : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
 
     /* Now byte-reverse the outputs */
-    for( i = 0; i < 16; i++ )
+    for (i = 0; i < 16; i++) {
         c[i] = cc[15 - i];
+    }
 
     return;
 }
@@ -249,32 +583,33 @@
 /*
  * Compute decryption round keys from encryption round keys
  */
-void mbedtls_aesni_inverse_key( unsigned char *invkey,
-                        const unsigned char *fwdkey, int nr )
+void mbedtls_aesni_inverse_key(unsigned char *invkey,
+                               const unsigned char *fwdkey, int nr)
 {
     unsigned char *ik = invkey;
     const unsigned char *fk = fwdkey + 16 * nr;
 
-    memcpy( ik, fk, 16 );
+    memcpy(ik, fk, 16);
 
-    for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 )
-        asm( "movdqu (%0), %%xmm0       \n\t"
-             AESIMC  xmm0_xmm0         "\n\t"
+    for (fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16) {
+        asm ("movdqu (%0), %%xmm0       \n\t"
+             AESIMC(xmm0_xmm0)
              "movdqu %%xmm0, (%1)       \n\t"
              :
              : "r" (fk), "r" (ik)
-             : "memory", "xmm0" );
+             : "memory", "xmm0");
+    }
 
-    memcpy( ik, fk, 16 );
+    memcpy(ik, fk, 16);
 }
 
 /*
  * Key expansion, 128-bit case
  */
-static void aesni_setkey_enc_128( unsigned char *rk,
-                                  const unsigned char *key )
+static void aesni_setkey_enc_128(unsigned char *rk,
+                                 const unsigned char *key)
 {
-    asm( "movdqu (%1), %%xmm0               \n\t" // copy the original key
+    asm ("movdqu (%1), %%xmm0               \n\t" // copy the original key
          "movdqu %%xmm0, (%0)               \n\t" // as round key 0
          "jmp 2f                            \n\t" // skip auxiliary routine
 
@@ -303,28 +638,28 @@
 
          /* Main "loop" */
          "2:                                \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x01        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x02        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x04        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x08        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x10        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x20        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x40        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x80        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x1B        \n\tcall 1b \n\t"
-         AESKEYGENA xmm0_xmm1 ",0x36        \n\tcall 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x01")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x02")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x04")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x08")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x10")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x20")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x40")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x80")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x1B")      "call 1b \n\t"
+         AESKEYGENA(xmm0_xmm1, "0x36")      "call 1b \n\t"
          :
          : "r" (rk), "r" (key)
-         : "memory", "cc", "0" );
+         : "memory", "cc", "0");
 }
 
 /*
  * Key expansion, 192-bit case
  */
-static void aesni_setkey_enc_192( unsigned char *rk,
-                                  const unsigned char *key )
+static void aesni_setkey_enc_192(unsigned char *rk,
+                                 const unsigned char *key)
 {
-    asm( "movdqu (%1), %%xmm0   \n\t" // copy original round key
+    asm ("movdqu (%1), %%xmm0   \n\t" // copy original round key
          "movdqu %%xmm0, (%0)   \n\t"
          "add $16, %0           \n\t"
          "movq 16(%1), %%xmm1   \n\t"
@@ -361,27 +696,27 @@
          "ret                           \n\t"
 
          "2:                            \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x01    \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x02    \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x04    \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x08    \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x10    \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x20    \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x40    \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x80    \n\tcall 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x01")  "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x02")  "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x04")  "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x08")  "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x10")  "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x20")  "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x40")  "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x80")  "call 1b \n\t"
 
          :
          : "r" (rk), "r" (key)
-         : "memory", "cc", "0" );
+         : "memory", "cc", "0");
 }
 
 /*
  * Key expansion, 256-bit case
  */
-static void aesni_setkey_enc_256( unsigned char *rk,
-                                  const unsigned char *key )
+static void aesni_setkey_enc_256(unsigned char *rk,
+                                 const unsigned char *key)
 {
-    asm( "movdqu (%1), %%xmm0           \n\t"
+    asm ("movdqu (%1), %%xmm0           \n\t"
          "movdqu %%xmm0, (%0)           \n\t"
          "add $16, %0                   \n\t"
          "movdqu 16(%1), %%xmm1         \n\t"
@@ -411,7 +746,7 @@
 
          /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 )
           * and proceed to generate next round key from there */
-         AESKEYGENA xmm0_xmm2 ",0x00        \n\t"
+         AESKEYGENA(xmm0_xmm2, "0x00")
          "pshufd $0xaa, %%xmm2, %%xmm2      \n\t"
          "pxor %%xmm1, %%xmm2               \n\t"
          "pslldq $4, %%xmm1                 \n\t"
@@ -429,36 +764,37 @@
           * see definition of mbedtls_aes_context.buf
           */
          "2:                                \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x01        \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x02        \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x04        \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x08        \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x10        \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x20        \n\tcall 1b \n\t"
-         AESKEYGENA xmm1_xmm2 ",0x40        \n\tcall 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x01")      "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x02")      "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x04")      "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x08")      "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x10")      "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x20")      "call 1b \n\t"
+         AESKEYGENA(xmm1_xmm2, "0x40")      "call 1b \n\t"
          :
          : "r" (rk), "r" (key)
-         : "memory", "cc", "0" );
+         : "memory", "cc", "0");
 }
 
+#endif  /* MBEDTLS_AESNI_HAVE_CODE */
+
 /*
  * Key expansion, wrapper
  */
-int mbedtls_aesni_setkey_enc( unsigned char *rk,
-                      const unsigned char *key,
-                      size_t bits )
+int mbedtls_aesni_setkey_enc(unsigned char *rk,
+                             const unsigned char *key,
+                             size_t bits)
 {
-    switch( bits )
-    {
-        case 128: aesni_setkey_enc_128( rk, key ); break;
-        case 192: aesni_setkey_enc_192( rk, key ); break;
-        case 256: aesni_setkey_enc_256( rk, key ); break;
-        default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
+    switch (bits) {
+        case 128: aesni_setkey_enc_128(rk, key); break;
+        case 192: aesni_setkey_enc_192(rk, key); break;
+        case 256: aesni_setkey_enc_256(rk, key); break;
+        default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
     }
 
-    return( 0 );
+    return 0;
 }
 
-#endif /* MBEDTLS_HAVE_X86_64 */
+#endif /* MBEDTLS_AESNI_HAVE_CODE */
 
 #endif /* MBEDTLS_AESNI_C */
diff --git a/lib/libmbedtls/mbedtls/library/aesni.h b/lib/libmbedtls/mbedtls/library/aesni.h
new file mode 100644
index 0000000..51b770f
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/aesni.h
@@ -0,0 +1,166 @@
+/**
+ * \file aesni.h
+ *
+ * \brief AES-NI for hardware AES acceleration on some Intel processors
+ *
+ * \warning These functions are only for internal use by other library
+ *          functions; you must not call them directly.
+ */
+/*
+ *  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_AESNI_H
+#define MBEDTLS_AESNI_H
+
+#include "mbedtls/build_info.h"
+
+#include "mbedtls/aes.h"
+
+#define MBEDTLS_AESNI_AES      0x02000000u
+#define MBEDTLS_AESNI_CLMUL    0x00000002u
+
+/* Can we do AESNI with inline assembly?
+ * (Only implemented with gas syntax, only for 64-bit.)
+ */
+#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \
+    (defined(__amd64__) || defined(__x86_64__))   &&  \
+    !defined(MBEDTLS_HAVE_X86_64)
+#define MBEDTLS_HAVE_X86_64
+#endif
+
+#if defined(MBEDTLS_AESNI_C)
+
+/* Can we do AESNI with intrinsics?
+ * (Only implemented with certain compilers, only for certain targets.)
+ */
+#undef MBEDTLS_AESNI_HAVE_INTRINSICS
+#if defined(_MSC_VER)
+/* Visual Studio supports AESNI intrinsics since VS 2008 SP1. We only support
+ * VS 2013 and up for other reasons anyway, so no need to check the version. */
+#define MBEDTLS_AESNI_HAVE_INTRINSICS
+#endif
+/* GCC-like compilers: currently, we only support intrinsics if the requisite
+ * target flag is enabled when building the library (e.g. `gcc -mpclmul -msse2`
+ * or `clang -maes -mpclmul`). */
+#if defined(__GNUC__) && defined(__AES__) && defined(__PCLMUL__)
+#define MBEDTLS_AESNI_HAVE_INTRINSICS
+#endif
+
+/* Choose the implementation of AESNI, if one is available. */
+#undef MBEDTLS_AESNI_HAVE_CODE
+/* To minimize disruption when releasing the intrinsics-based implementation,
+ * favor the assembly-based implementation if it's available. We intend to
+ * revise this in a later release of Mbed TLS 3.x. In the long run, we will
+ * likely remove the assembly implementation. */
+#if defined(MBEDTLS_HAVE_X86_64)
+#define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly
+#elif defined(MBEDTLS_AESNI_HAVE_INTRINSICS)
+#define MBEDTLS_AESNI_HAVE_CODE 2 // via intrinsics
+#endif
+
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Internal function to detect the AES-NI feature in CPUs.
+ *
+ * \note           This function is only for internal use by other library
+ *                 functions; you must not call it directly.
+ *
+ * \param what     The feature to detect
+ *                 (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL)
+ *
+ * \return         1 if CPU has support for the feature, 0 otherwise
+ */
+int mbedtls_aesni_has_support(unsigned int what);
+
+/**
+ * \brief          Internal AES-NI AES-ECB block encryption and decryption
+ *
+ * \note           This function is only for internal use by other library
+ *                 functions; you must not call it directly.
+ *
+ * \param ctx      AES context
+ * \param mode     MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
+ * \param input    16-byte input block
+ * \param output   16-byte output block
+ *
+ * \return         0 on success (cannot fail)
+ */
+int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx,
+                            int mode,
+                            const unsigned char input[16],
+                            unsigned char output[16]);
+
+/**
+ * \brief          Internal GCM multiplication: c = a * b in GF(2^128)
+ *
+ * \note           This function is only for internal use by other library
+ *                 functions; you must not call it directly.
+ *
+ * \param c        Result
+ * \param a        First operand
+ * \param b        Second operand
+ *
+ * \note           Both operands and result are bit strings interpreted as
+ *                 elements of GF(2^128) as per the GCM spec.
+ */
+void mbedtls_aesni_gcm_mult(unsigned char c[16],
+                            const unsigned char a[16],
+                            const unsigned char b[16]);
+
+/**
+ * \brief           Internal round key inversion. This function computes
+ *                  decryption round keys from the encryption round keys.
+ *
+ * \note            This function is only for internal use by other library
+ *                  functions; you must not call it directly.
+ *
+ * \param invkey    Round keys for the equivalent inverse cipher
+ * \param fwdkey    Original round keys (for encryption)
+ * \param nr        Number of rounds (that is, number of round keys minus one)
+ */
+void mbedtls_aesni_inverse_key(unsigned char *invkey,
+                               const unsigned char *fwdkey,
+                               int nr);
+
+/**
+ * \brief           Internal key expansion for encryption
+ *
+ * \note            This function is only for internal use by other library
+ *                  functions; you must not call it directly.
+ *
+ * \param rk        Destination buffer where the round keys are written
+ * \param key       Encryption key
+ * \param bits      Key size in bits (must be 128, 192 or 256)
+ *
+ * \return          0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
+ */
+int mbedtls_aesni_setkey_enc(unsigned char *rk,
+                             const unsigned char *key,
+                             size_t bits);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_AESNI_HAVE_CODE */
+#endif  /* MBEDTLS_AESNI_C */
+
+#endif /* MBEDTLS_AESNI_H */
diff --git a/lib/libmbedtls/mbedtls/library/alignment.h b/lib/libmbedtls/mbedtls/library/alignment.h
new file mode 100644
index 0000000..a518a8a
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/alignment.h
@@ -0,0 +1,520 @@
+/**
+ * \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"
+
+/*
+ * Define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS for architectures where unaligned memory
+ * accesses are known to be efficient.
+ *
+ * All functions defined here will behave correctly regardless, but might be less
+ * efficient when this is not defined.
+ */
+#if defined(__ARM_FEATURE_UNALIGNED) \
+    || defined(__i386__) || defined(__amd64__) || defined(__x86_64__)
+/*
+ * __ARM_FEATURE_UNALIGNED is defined where appropriate by armcc, gcc 7, clang 9
+ * (and later versions) for Arm v7 and later; all x86 platforms should have
+ * efficient unaligned access.
+ */
+#define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS
+#endif
+
+/**
+ * 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) && !defined(MBEDTLS_BSWAP16)
+#define MBEDTLS_BSWAP16 __builtin_bswap16
+#endif /* __has_builtin(__builtin_bswap16) */
+#if __has_builtin(__builtin_bswap32) && !defined(MBEDTLS_BSWAP32)
+#define MBEDTLS_BSWAP32 __builtin_bswap32
+#endif /* __has_builtin(__builtin_bswap32) */
+#if __has_builtin(__builtin_bswap64) && !defined(MBEDTLS_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)
+#if !defined(MBEDTLS_BSWAP16)
+#define MBEDTLS_BSWAP16 _byteswap_ushort
+#endif
+#if !defined(MBEDTLS_BSWAP32)
+#define MBEDTLS_BSWAP32 _byteswap_ulong
+#endif
+#if !defined(MBEDTLS_BSWAP64)
+#define MBEDTLS_BSWAP64 _byteswap_uint64
+#endif
+#endif /* defined(_MSC_VER) */
+
+/* Detect armcc built-in byteswap routine */
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 410000) && !defined(MBEDTLS_BSWAP32)
+#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 & 0x00000000000000ffULL) << 56 |
+        (x & 0x000000000000ff00ULL) << 40 |
+        (x & 0x0000000000ff0000ULL) << 24 |
+        (x & 0x00000000ff000000ULL) <<  8 |
+        (x & 0x000000ff00000000ULL) >>  8 |
+        (x & 0x0000ff0000000000ULL) >> 24 |
+        (x & 0x00ff000000000000ULL) >> 40 |
+        (x & 0xff00000000000000ULL) >> 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/lib/libmbedtls/mbedtls/library/arc4.c b/lib/libmbedtls/mbedtls/library/arc4.c
deleted file mode 100644
index b34dc5e..0000000
--- a/lib/libmbedtls/mbedtls/library/arc4.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- *  An implementation of the ARCFOUR algorithm
- *
- *  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.
- */
-/*
- *  The ARCFOUR algorithm was publicly disclosed on 94/09.
- *
- *  http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0
- */
-
-#include "common.h"
-
-#if defined(MBEDTLS_ARC4_C)
-
-#include "mbedtls/arc4.h"
-#include "mbedtls/platform_util.h"
-
-#include <string.h>
-
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
-
-#if !defined(MBEDTLS_ARC4_ALT)
-
-void mbedtls_arc4_init( mbedtls_arc4_context *ctx )
-{
-    memset( ctx, 0, sizeof( mbedtls_arc4_context ) );
-}
-
-void mbedtls_arc4_free( mbedtls_arc4_context *ctx )
-{
-    if( ctx == NULL )
-        return;
-
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_arc4_context ) );
-}
-
-/*
- * ARC4 key schedule
- */
-void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key,
-                 unsigned int keylen )
-{
-    int i, j, a;
-    unsigned int k;
-    unsigned char *m;
-
-    ctx->x = 0;
-    ctx->y = 0;
-    m = ctx->m;
-
-    for( i = 0; i < 256; i++ )
-        m[i] = (unsigned char) i;
-
-    j = k = 0;
-
-    for( i = 0; i < 256; i++, k++ )
-    {
-        if( k >= keylen ) k = 0;
-
-        a = m[i];
-        j = ( j + a + key[k] ) & 0xFF;
-        m[i] = m[j];
-        m[j] = (unsigned char) a;
-    }
-}
-
-/*
- * ARC4 cipher function
- */
-int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input,
-                unsigned char *output )
-{
-    int x, y, a, b;
-    size_t i;
-    unsigned char *m;
-
-    x = ctx->x;
-    y = ctx->y;
-    m = ctx->m;
-
-    for( i = 0; i < length; i++ )
-    {
-        x = ( x + 1 ) & 0xFF; a = m[x];
-        y = ( y + a ) & 0xFF; b = m[y];
-
-        m[x] = (unsigned char) b;
-        m[y] = (unsigned char) a;
-
-        output[i] = (unsigned char)
-            ( input[i] ^ m[(unsigned char)( a + b )] );
-    }
-
-    ctx->x = x;
-    ctx->y = y;
-
-    return( 0 );
-}
-
-#endif /* !MBEDTLS_ARC4_ALT */
-
-#if defined(MBEDTLS_SELF_TEST)
-/*
- * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994:
- *
- * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0
- */
-static const unsigned char arc4_test_key[3][8] =
-{
-    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
-    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
-};
-
-static const unsigned char arc4_test_pt[3][8] =
-{
-    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
-};
-
-static const unsigned char arc4_test_ct[3][8] =
-{
-    { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 },
-    { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 },
-    { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A }
-};
-
-/*
- * Checkup routine
- */
-int mbedtls_arc4_self_test( int verbose )
-{
-    int i, ret = 0;
-    unsigned char ibuf[8];
-    unsigned char obuf[8];
-    mbedtls_arc4_context ctx;
-
-    mbedtls_arc4_init( &ctx );
-
-    for( i = 0; i < 3; i++ )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "  ARC4 test #%d: ", i + 1 );
-
-        memcpy( ibuf, arc4_test_pt[i], 8 );
-
-        mbedtls_arc4_setup( &ctx, arc4_test_key[i], 8 );
-        mbedtls_arc4_crypt( &ctx, 8, ibuf, obuf );
-
-        if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "failed\n" );
-
-            ret = 1;
-            goto exit;
-        }
-
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
-    }
-
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
-
-exit:
-    mbedtls_arc4_free( &ctx );
-
-    return( ret );
-}
-
-#endif /* MBEDTLS_SELF_TEST */
-
-#endif /* MBEDTLS_ARC4_C */
diff --git a/lib/libmbedtls/mbedtls/library/aria.c b/lib/libmbedtls/mbedtls/library/aria.c
index bc05c4a..0980362 100644
--- a/lib/libmbedtls/mbedtls/library/aria.c
+++ b/lib/libmbedtls/mbedtls/library/aria.c
@@ -31,29 +31,17 @@
 
 #include <string.h>
 
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
 
 #if !defined(MBEDTLS_ARIA_ALT)
 
 #include "mbedtls/platform_util.h"
 
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
-    !defined(inline) && !defined(__cplusplus)
-#define inline __inline
-#endif
-
 /* Parameter validation macros */
-#define ARIA_VALIDATE_RET( cond )                                       \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ARIA_BAD_INPUT_DATA )
-#define ARIA_VALIDATE( cond )                                           \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
+#define ARIA_VALIDATE_RET(cond)                                       \
+    MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ARIA_BAD_INPUT_DATA)
+#define ARIA_VALIDATE(cond)                                           \
+    MBEDTLS_INTERNAL_VALIDATE(cond)
 
 /*
  * modify byte order: ( A B C D ) -> ( B A D C ), i.e. swap pairs of bytes
@@ -67,30 +55,30 @@
 #if defined(__arm__) /* rev16 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 ) && \
+    (!defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000) && \
     __ARM_ARCH >= 6
-static inline uint32_t aria_p1( uint32_t x )
+static inline uint32_t aria_p1(uint32_t x)
 {
     uint32_t r;
-    __asm( "rev16 %0, %1" : "=l" (r) : "l" (x) );
-    return( r );
+    __asm("rev16 %0, %1" : "=l" (r) : "l" (x));
+    return r;
 }
 #define ARIA_P1 aria_p1
 #elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \
-    ( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 )
-static inline uint32_t aria_p1( uint32_t x )
+    (__TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3)
+static inline uint32_t aria_p1(uint32_t x)
 {
     uint32_t r;
-    __asm( "rev16 r, x" );
-    return( r );
+    __asm("rev16 r, x");
+    return r;
 }
 #define ARIA_P1 aria_p1
 #endif
 #endif /* arm */
 #if defined(__GNUC__) && \
-    defined(__i386__) || defined(__amd64__) || defined( __x86_64__)
+    defined(__i386__) || defined(__amd64__) || defined(__x86_64__)
 /* I couldn't find an Intel equivalent of rev16, so two instructions */
-#define ARIA_P1(x) ARIA_P2( ARIA_P3( x ) )
+#define ARIA_P1(x) ARIA_P2(ARIA_P3(x))
 #endif /* x86 gnuc */
 #endif /* MBEDTLS_HAVE_ASM && GNUC */
 #if !defined(ARIA_P1)
@@ -110,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
@@ -175,28 +124,28 @@
  * half of App. B.1 in [1] in terms of 4-byte operators P1, P2, P3 and P4.
  * The implementation below uses only P1 and P2 as they are sufficient.
  */
-static inline void aria_a( uint32_t *a, uint32_t *b,
-                           uint32_t *c, uint32_t *d )
+static inline void aria_a(uint32_t *a, uint32_t *b,
+                          uint32_t *c, uint32_t *d)
 {
     uint32_t ta, tb, tc;
     ta  =  *b;                      // 4567
     *b  =  *a;                      // 0123
-    *a  =  ARIA_P2( ta );           // 6745
-    tb  =  ARIA_P2( *d );           // efcd
-    *d  =  ARIA_P1( *c );           // 98ba
-    *c  =  ARIA_P1( tb );           // fedc
+    *a  =  ARIA_P2(ta);             // 6745
+    tb  =  ARIA_P2(*d);             // efcd
+    *d  =  ARIA_P1(*c);             // 98ba
+    *c  =  ARIA_P1(tb);             // fedc
     ta  ^= *d;                      // 4567+98ba
-    tc  =  ARIA_P2( *b );           // 2301
-    ta  =  ARIA_P1( ta ) ^ tc ^ *c; // 2301+5476+89ab+fedc
-    tb  ^= ARIA_P2( *d );           // ba98+efcd
-    tc  ^= ARIA_P1( *a );           // 2301+7654
+    tc  =  ARIA_P2(*b);             // 2301
+    ta  =  ARIA_P1(ta) ^ tc ^ *c;   // 2301+5476+89ab+fedc
+    tb  ^= ARIA_P2(*d);             // ba98+efcd
+    tc  ^= ARIA_P1(*a);             // 2301+7654
     *b  ^= ta ^ tb;                 // 0123+2301+5476+89ab+ba98+efcd+fedc OUT
-    tb  =  ARIA_P2( tb ) ^ ta;      // 2301+5476+89ab+98ba+cdef+fedc
-    *a  ^= ARIA_P1( tb );           // 3210+4567+6745+89ab+98ba+dcfe+efcd OUT
-    ta  =  ARIA_P2( ta );           // 0123+7654+ab89+dcfe
-    *d  ^= ARIA_P1( ta ) ^ tc;      // 1032+2301+6745+7654+98ba+ba98+cdef OUT
-    tc  =  ARIA_P2( tc );           // 0123+5476
-    *c  ^= ARIA_P1( tc ) ^ ta;      // 0123+1032+4567+7654+ab89+dcfe+fedc OUT
+    tb  =  ARIA_P2(tb) ^ ta;        // 2301+5476+89ab+98ba+cdef+fedc
+    *a  ^= ARIA_P1(tb);             // 3210+4567+6745+89ab+98ba+dcfe+efcd OUT
+    ta  =  ARIA_P2(ta);             // 0123+7654+ab89+dcfe
+    *d  ^= ARIA_P1(ta) ^ tc;        // 1032+2301+6745+7654+98ba+ba98+cdef OUT
+    tc  =  ARIA_P2(tc);             // 0123+5476
+    *c  ^= ARIA_P1(tc) ^ ta;        // 0123+1032+4567+7654+ab89+dcfe+fedc OUT
 }
 
 /*
@@ -207,27 +156,27 @@
  * By passing sb1, sb2, is1, is2 as S-Boxes you get SL1
  * By passing is1, is2, sb1, sb2 as S-Boxes you get SL2
  */
-static inline void aria_sl( uint32_t *a, uint32_t *b,
-                            uint32_t *c, uint32_t *d,
-                            const uint8_t sa[256], const uint8_t sb[256],
-                            const uint8_t sc[256], const uint8_t sd[256] )
+static inline void aria_sl(uint32_t *a, uint32_t *b,
+                           uint32_t *c, uint32_t *d,
+                           const uint8_t sa[256], const uint8_t sb[256],
+                           const uint8_t sc[256], const uint8_t sd[256])
 {
-    *a = ( (uint32_t) sa[ MBEDTLS_BYTE_0( *a ) ]       ) ^
-         (((uint32_t) sb[ MBEDTLS_BYTE_1( *a ) ]) <<  8) ^
-         (((uint32_t) sc[ MBEDTLS_BYTE_2( *a ) ]) << 16) ^
-         (((uint32_t) sd[ MBEDTLS_BYTE_3( *a ) ]) << 24);
-    *b = ( (uint32_t) sa[ MBEDTLS_BYTE_0( *b ) ]       ) ^
-         (((uint32_t) sb[ MBEDTLS_BYTE_1( *b ) ]) <<  8) ^
-         (((uint32_t) sc[ MBEDTLS_BYTE_2( *b ) ]) << 16) ^
-         (((uint32_t) sd[ MBEDTLS_BYTE_3( *b ) ]) << 24);
-    *c = ( (uint32_t) sa[ MBEDTLS_BYTE_0( *c ) ]       ) ^
-         (((uint32_t) sb[ MBEDTLS_BYTE_1( *c ) ]) <<  8) ^
-         (((uint32_t) sc[ MBEDTLS_BYTE_2( *c ) ]) << 16) ^
-         (((uint32_t) sd[ MBEDTLS_BYTE_3( *c ) ]) << 24);
-    *d = ( (uint32_t) sa[ MBEDTLS_BYTE_0( *d ) ]       ) ^
-         (((uint32_t) sb[ MBEDTLS_BYTE_1( *d ) ]) <<  8) ^
-         (((uint32_t) sc[ MBEDTLS_BYTE_2( *d ) ]) << 16) ^
-         (((uint32_t) sd[ MBEDTLS_BYTE_3( *d ) ]) << 24);
+    *a = ((uint32_t) sa[MBEDTLS_BYTE_0(*a)]) ^
+         (((uint32_t) sb[MBEDTLS_BYTE_1(*a)]) <<  8) ^
+         (((uint32_t) sc[MBEDTLS_BYTE_2(*a)]) << 16) ^
+         (((uint32_t) sd[MBEDTLS_BYTE_3(*a)]) << 24);
+    *b = ((uint32_t) sa[MBEDTLS_BYTE_0(*b)]) ^
+         (((uint32_t) sb[MBEDTLS_BYTE_1(*b)]) <<  8) ^
+         (((uint32_t) sc[MBEDTLS_BYTE_2(*b)]) << 16) ^
+         (((uint32_t) sd[MBEDTLS_BYTE_3(*b)]) << 24);
+    *c = ((uint32_t) sa[MBEDTLS_BYTE_0(*c)]) ^
+         (((uint32_t) sb[MBEDTLS_BYTE_1(*c)]) <<  8) ^
+         (((uint32_t) sc[MBEDTLS_BYTE_2(*c)]) << 16) ^
+         (((uint32_t) sd[MBEDTLS_BYTE_3(*c)]) << 24);
+    *d = ((uint32_t) sa[MBEDTLS_BYTE_0(*d)]) ^
+         (((uint32_t) sb[MBEDTLS_BYTE_1(*d)]) <<  8) ^
+         (((uint32_t) sc[MBEDTLS_BYTE_2(*d)]) << 16) ^
+         (((uint32_t) sd[MBEDTLS_BYTE_3(*d)]) << 24);
 }
 
 /*
@@ -340,8 +289,8 @@
 /*
  * Helper for key schedule: r = FO( p, k ) ^ x
  */
-static void aria_fo_xor( uint32_t r[4], const uint32_t p[4],
-                         const uint32_t k[4], const uint32_t x[4] )
+static void aria_fo_xor(uint32_t r[4], const uint32_t p[4],
+                        const uint32_t k[4], const uint32_t x[4])
 {
     uint32_t a, b, c, d;
 
@@ -350,8 +299,8 @@
     c = p[2] ^ k[2];
     d = p[3] ^ k[3];
 
-    aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 );
-    aria_a( &a, &b, &c, &d );
+    aria_sl(&a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2);
+    aria_a(&a, &b, &c, &d);
 
     r[0] = a ^ x[0];
     r[1] = b ^ x[1];
@@ -362,8 +311,8 @@
 /*
  * Helper for key schedule: r = FE( p, k ) ^ x
  */
-static void aria_fe_xor( uint32_t r[4], const uint32_t p[4],
-                         const uint32_t k[4], const uint32_t x[4] )
+static void aria_fe_xor(uint32_t r[4], const uint32_t p[4],
+                        const uint32_t k[4], const uint32_t x[4])
 {
     uint32_t a, b, c, d;
 
@@ -372,8 +321,8 @@
     c = p[2] ^ k[2];
     d = p[3] ^ k[3];
 
-    aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 );
-    aria_a( &a, &b, &c, &d );
+    aria_sl(&a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2);
+    aria_a(&a, &b, &c, &d);
 
     r[0] = a ^ x[0];
     r[1] = b ^ x[1];
@@ -388,8 +337,8 @@
  * MBEDTLS_GET_UINT32_LE / MBEDTLS_PUT_UINT32_LE ) so we need to reverse
  * bytes here.
  */
-static void aria_rot128( uint32_t r[4], const uint32_t a[4],
-                         const uint32_t b[4], uint8_t n )
+static void aria_rot128(uint32_t r[4], const uint32_t a[4],
+                        const uint32_t b[4], uint8_t n)
 {
     uint8_t i, j;
     uint32_t t, u;
@@ -397,15 +346,14 @@
     const uint8_t n1 = n % 32;              // bit offset
     const uint8_t n2 = n1 ? 32 - n1 : 0;    // reverse bit offset
 
-    j = ( n / 32 ) % 4;                     // initial word offset
-    t = ARIA_P3( b[j] );                    // big endian
-    for( i = 0; i < 4; i++ )
-    {
-        j = ( j + 1 ) % 4;                  // get next word, big endian
-        u = ARIA_P3( b[j] );
+    j = (n / 32) % 4;                       // initial word offset
+    t = ARIA_P3(b[j]);                      // big endian
+    for (i = 0; i < 4; i++) {
+        j = (j + 1) % 4;                    // get next word, big endian
+        u = ARIA_P3(b[j]);
         t <<= n1;                           // rotate
         t |= u >> n2;
-        t = ARIA_P3( t );                   // back to little endian
+        t = ARIA_P3(t);                     // back to little endian
         r[i] = a[i] ^ t;                    // store
         t = u;                              // move to next word
     }
@@ -414,8 +362,8 @@
 /*
  * Set encryption key
  */
-int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx,
-                             const unsigned char *key, unsigned int keybits )
+int mbedtls_aria_setkey_enc(mbedtls_aria_context *ctx,
+                            const unsigned char *key, unsigned int keybits)
 {
     /* round constant masks */
     const uint32_t rc[3][4] =
@@ -427,74 +375,71 @@
 
     int i;
     uint32_t w[4][4], *w2;
-    ARIA_VALIDATE_RET( ctx != NULL );
-    ARIA_VALIDATE_RET( key != NULL );
+    ARIA_VALIDATE_RET(ctx != NULL);
+    ARIA_VALIDATE_RET(key != NULL);
 
-    if( keybits != 128 && keybits != 192 && keybits != 256 )
-        return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA );
+    if (keybits != 128 && keybits != 192 && keybits != 256) {
+        return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;
+    }
 
     /* Copy key to W0 (and potential remainder to W1) */
-    w[0][0] = MBEDTLS_GET_UINT32_LE( key,  0 );
-    w[0][1] = MBEDTLS_GET_UINT32_LE( key,  4 );
-    w[0][2] = MBEDTLS_GET_UINT32_LE( key,  8 );
-    w[0][3] = MBEDTLS_GET_UINT32_LE( key, 12 );
+    w[0][0] = MBEDTLS_GET_UINT32_LE(key,  0);
+    w[0][1] = MBEDTLS_GET_UINT32_LE(key,  4);
+    w[0][2] = MBEDTLS_GET_UINT32_LE(key,  8);
+    w[0][3] = MBEDTLS_GET_UINT32_LE(key, 12);
 
-    memset( w[1], 0, 16 );
-    if( keybits >= 192 )
-    {
-        w[1][0] = MBEDTLS_GET_UINT32_LE( key, 16 );  // 192 bit key
-        w[1][1] = MBEDTLS_GET_UINT32_LE( key, 20 );
+    memset(w[1], 0, 16);
+    if (keybits >= 192) {
+        w[1][0] = MBEDTLS_GET_UINT32_LE(key, 16);    // 192 bit key
+        w[1][1] = MBEDTLS_GET_UINT32_LE(key, 20);
     }
-    if( keybits == 256 )
-    {
-        w[1][2] = MBEDTLS_GET_UINT32_LE( key, 24 );  // 256 bit key
-        w[1][3] = MBEDTLS_GET_UINT32_LE( key, 28 );
+    if (keybits == 256) {
+        w[1][2] = MBEDTLS_GET_UINT32_LE(key, 24);    // 256 bit key
+        w[1][3] = MBEDTLS_GET_UINT32_LE(key, 28);
     }
 
-    i = ( keybits - 128 ) >> 6;             // index: 0, 1, 2
+    i = (keybits - 128) >> 6;               // index: 0, 1, 2
     ctx->nr = 12 + 2 * i;                   // no. rounds: 12, 14, 16
 
-    aria_fo_xor( w[1], w[0], rc[i], w[1] ); // W1 = FO(W0, CK1) ^ KR
+    aria_fo_xor(w[1], w[0], rc[i], w[1]);   // W1 = FO(W0, CK1) ^ KR
     i = i < 2 ? i + 1 : 0;
-    aria_fe_xor( w[2], w[1], rc[i], w[0] ); // W2 = FE(W1, CK2) ^ W0
+    aria_fe_xor(w[2], w[1], rc[i], w[0]);   // W2 = FE(W1, CK2) ^ W0
     i = i < 2 ? i + 1 : 0;
-    aria_fo_xor( w[3], w[2], rc[i], w[1] ); // W3 = FO(W2, CK3) ^ W1
+    aria_fo_xor(w[3], w[2], rc[i], w[1]);   // W3 = FO(W2, CK3) ^ W1
 
-    for( i = 0; i < 4; i++ )                // create round keys
-    {
+    for (i = 0; i < 4; i++) {               // create round keys
         w2 = w[(i + 1) & 3];
-        aria_rot128( ctx->rk[i     ], w[i], w2, 128 - 19 );
-        aria_rot128( ctx->rk[i +  4], w[i], w2, 128 - 31 );
-        aria_rot128( ctx->rk[i +  8], w[i], w2,       61 );
-        aria_rot128( ctx->rk[i + 12], w[i], w2,       31 );
+        aria_rot128(ctx->rk[i], w[i], w2, 128 - 19);
+        aria_rot128(ctx->rk[i +  4], w[i], w2, 128 - 31);
+        aria_rot128(ctx->rk[i +  8], w[i], w2,       61);
+        aria_rot128(ctx->rk[i + 12], w[i], w2,       31);
     }
-    aria_rot128( ctx->rk[16], w[0], w[1], 19 );
+    aria_rot128(ctx->rk[16], w[0], w[1], 19);
 
     /* w holds enough info to reconstruct the round keys */
-    mbedtls_platform_zeroize( w, sizeof( w ) );
+    mbedtls_platform_zeroize(w, sizeof(w));
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Set decryption key
  */
-int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx,
-                             const unsigned char *key, unsigned int keybits )
+int mbedtls_aria_setkey_dec(mbedtls_aria_context *ctx,
+                            const unsigned char *key, unsigned int keybits)
 {
     int i, j, k, ret;
-    ARIA_VALIDATE_RET( ctx != NULL );
-    ARIA_VALIDATE_RET( key != NULL );
+    ARIA_VALIDATE_RET(ctx != NULL);
+    ARIA_VALIDATE_RET(key != NULL);
 
-    ret = mbedtls_aria_setkey_enc( ctx, key, keybits );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_aria_setkey_enc(ctx, key, keybits);
+    if (ret != 0) {
+        return ret;
+    }
 
     /* flip the order of round keys */
-    for( i = 0, j = ctx->nr; i < j; i++, j-- )
-    {
-        for( k = 0; k < 4; k++ )
-        {
+    for (i = 0, j = ctx->nr; i < j; i++, j--) {
+        for (k = 0; k < 4; k++) {
             uint32_t t = ctx->rk[i][k];
             ctx->rk[i][k] = ctx->rk[j][k];
             ctx->rk[j][k] = t;
@@ -502,45 +447,43 @@
     }
 
     /* apply affine transform to middle keys */
-    for( i = 1; i < ctx->nr; i++ )
-    {
-        aria_a( &ctx->rk[i][0], &ctx->rk[i][1],
-                &ctx->rk[i][2], &ctx->rk[i][3] );
+    for (i = 1; i < ctx->nr; i++) {
+        aria_a(&ctx->rk[i][0], &ctx->rk[i][1],
+               &ctx->rk[i][2], &ctx->rk[i][3]);
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Encrypt a block
  */
-int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx,
-                            const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE],
-                            unsigned char output[MBEDTLS_ARIA_BLOCKSIZE] )
+int mbedtls_aria_crypt_ecb(mbedtls_aria_context *ctx,
+                           const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE],
+                           unsigned char output[MBEDTLS_ARIA_BLOCKSIZE])
 {
     int i;
 
     uint32_t a, b, c, d;
-    ARIA_VALIDATE_RET( ctx != NULL );
-    ARIA_VALIDATE_RET( input != NULL );
-    ARIA_VALIDATE_RET( output != NULL );
+    ARIA_VALIDATE_RET(ctx != NULL);
+    ARIA_VALIDATE_RET(input != NULL);
+    ARIA_VALIDATE_RET(output != NULL);
 
-    a = MBEDTLS_GET_UINT32_LE( input,  0 );
-    b = MBEDTLS_GET_UINT32_LE( input,  4 );
-    c = MBEDTLS_GET_UINT32_LE( input,  8 );
-    d = MBEDTLS_GET_UINT32_LE( input, 12 );
+    a = MBEDTLS_GET_UINT32_LE(input,  0);
+    b = MBEDTLS_GET_UINT32_LE(input,  4);
+    c = MBEDTLS_GET_UINT32_LE(input,  8);
+    d = MBEDTLS_GET_UINT32_LE(input, 12);
 
     i = 0;
-    while( 1 )
-    {
+    while (1) {
         a ^= ctx->rk[i][0];
         b ^= ctx->rk[i][1];
         c ^= ctx->rk[i][2];
         d ^= ctx->rk[i][3];
         i++;
 
-        aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 );
-        aria_a( &a, &b, &c, &d );
+        aria_sl(&a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2);
+        aria_a(&a, &b, &c, &d);
 
         a ^= ctx->rk[i][0];
         b ^= ctx->rk[i][1];
@@ -548,10 +491,11 @@
         d ^= ctx->rk[i][3];
         i++;
 
-        aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 );
-        if( i >= ctx->nr )
+        aria_sl(&a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2);
+        if (i >= ctx->nr) {
             break;
-        aria_a( &a, &b, &c, &d );
+        }
+        aria_a(&a, &b, &c, &d);
     }
 
     /* final key mixing */
@@ -560,80 +504,74 @@
     c ^= ctx->rk[i][2];
     d ^= ctx->rk[i][3];
 
-    MBEDTLS_PUT_UINT32_LE( a, output,  0 );
-    MBEDTLS_PUT_UINT32_LE( b, output,  4 );
-    MBEDTLS_PUT_UINT32_LE( c, output,  8 );
-    MBEDTLS_PUT_UINT32_LE( d, output, 12 );
+    MBEDTLS_PUT_UINT32_LE(a, output,  0);
+    MBEDTLS_PUT_UINT32_LE(b, output,  4);
+    MBEDTLS_PUT_UINT32_LE(c, output,  8);
+    MBEDTLS_PUT_UINT32_LE(d, output, 12);
 
-    return( 0 );
+    return 0;
 }
 
 /* Initialize context */
-void mbedtls_aria_init( mbedtls_aria_context *ctx )
+void mbedtls_aria_init(mbedtls_aria_context *ctx)
 {
-    ARIA_VALIDATE( ctx != NULL );
-    memset( ctx, 0, sizeof( mbedtls_aria_context ) );
+    ARIA_VALIDATE(ctx != NULL);
+    memset(ctx, 0, sizeof(mbedtls_aria_context));
 }
 
 /* Clear context */
-void mbedtls_aria_free( mbedtls_aria_context *ctx )
+void mbedtls_aria_free(mbedtls_aria_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aria_context ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_aria_context));
 }
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
 /*
  * ARIA-CBC buffer encryption/decryption
  */
-int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx,
-                            int mode,
-                            size_t length,
-                            unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE],
-                            const unsigned char *input,
-                            unsigned char *output )
+int mbedtls_aria_crypt_cbc(mbedtls_aria_context *ctx,
+                           int mode,
+                           size_t length,
+                           unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE],
+                           const unsigned char *input,
+                           unsigned char *output)
 {
-    int i;
     unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE];
 
-    ARIA_VALIDATE_RET( ctx != NULL );
-    ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT ||
-                       mode == MBEDTLS_ARIA_DECRYPT );
-    ARIA_VALIDATE_RET( length == 0 || input  != NULL );
-    ARIA_VALIDATE_RET( length == 0 || output != NULL );
-    ARIA_VALIDATE_RET( iv != NULL );
+    ARIA_VALIDATE_RET(ctx != NULL);
+    ARIA_VALIDATE_RET(mode == MBEDTLS_ARIA_ENCRYPT ||
+                      mode == MBEDTLS_ARIA_DECRYPT);
+    ARIA_VALIDATE_RET(length == 0 || input  != NULL);
+    ARIA_VALIDATE_RET(length == 0 || output != NULL);
+    ARIA_VALIDATE_RET(iv != NULL);
 
-    if( length % MBEDTLS_ARIA_BLOCKSIZE )
-        return( MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH );
+    if (length % MBEDTLS_ARIA_BLOCKSIZE) {
+        return MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH;
+    }
 
-    if( mode == MBEDTLS_ARIA_DECRYPT )
-    {
-        while( length > 0 )
-        {
-            memcpy( temp, input, MBEDTLS_ARIA_BLOCKSIZE );
-            mbedtls_aria_crypt_ecb( ctx, input, output );
+    if (mode == MBEDTLS_ARIA_DECRYPT) {
+        while (length > 0) {
+            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 );
+            memcpy(iv, temp, MBEDTLS_ARIA_BLOCKSIZE);
 
             input  += MBEDTLS_ARIA_BLOCKSIZE;
             output += MBEDTLS_ARIA_BLOCKSIZE;
             length -= MBEDTLS_ARIA_BLOCKSIZE;
         }
-    }
-    else
-    {
-        while( length > 0 )
-        {
-            for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ )
-                output[i] = (unsigned char)( input[i] ^ iv[i] );
+    } else {
+        while (length > 0) {
+            mbedtls_xor(output, input, iv, MBEDTLS_ARIA_BLOCKSIZE);
 
-            mbedtls_aria_crypt_ecb( ctx, output, output );
-            memcpy( iv, output, MBEDTLS_ARIA_BLOCKSIZE );
+            mbedtls_aria_crypt_ecb(ctx, output, output);
+            memcpy(iv, output, MBEDTLS_ARIA_BLOCKSIZE);
 
             input  += MBEDTLS_ARIA_BLOCKSIZE;
             output += MBEDTLS_ARIA_BLOCKSIZE;
@@ -641,7 +579,7 @@
         }
     }
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
@@ -649,63 +587,61 @@
 /*
  * ARIA-CFB128 buffer encryption/decryption
  */
-int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx,
-                               int mode,
-                               size_t length,
-                               size_t *iv_off,
-                               unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE],
-                               const unsigned char *input,
-                               unsigned char *output )
+int mbedtls_aria_crypt_cfb128(mbedtls_aria_context *ctx,
+                              int mode,
+                              size_t length,
+                              size_t *iv_off,
+                              unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE],
+                              const unsigned char *input,
+                              unsigned char *output)
 {
     unsigned char c;
     size_t n;
 
-    ARIA_VALIDATE_RET( ctx != NULL );
-    ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT ||
-                       mode == MBEDTLS_ARIA_DECRYPT );
-    ARIA_VALIDATE_RET( length == 0 || input  != NULL );
-    ARIA_VALIDATE_RET( length == 0 || output != NULL );
-    ARIA_VALIDATE_RET( iv != NULL );
-    ARIA_VALIDATE_RET( iv_off != NULL );
+    ARIA_VALIDATE_RET(ctx != NULL);
+    ARIA_VALIDATE_RET(mode == MBEDTLS_ARIA_ENCRYPT ||
+                      mode == MBEDTLS_ARIA_DECRYPT);
+    ARIA_VALIDATE_RET(length == 0 || input  != NULL);
+    ARIA_VALIDATE_RET(length == 0 || output != NULL);
+    ARIA_VALIDATE_RET(iv != NULL);
+    ARIA_VALIDATE_RET(iv_off != NULL);
 
     n = *iv_off;
 
     /* An overly large value of n can lead to an unlimited
      * buffer overflow. Therefore, guard against this
      * outside of parameter validation. */
-    if( n >= MBEDTLS_ARIA_BLOCKSIZE )
-        return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA );
+    if (n >= MBEDTLS_ARIA_BLOCKSIZE) {
+        return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;
+    }
 
-    if( mode == MBEDTLS_ARIA_DECRYPT )
-    {
-        while( length-- )
-        {
-            if( n == 0 )
-                mbedtls_aria_crypt_ecb( ctx, iv, iv );
+    if (mode == MBEDTLS_ARIA_DECRYPT) {
+        while (length--) {
+            if (n == 0) {
+                mbedtls_aria_crypt_ecb(ctx, iv, iv);
+            }
 
             c = *input++;
             *output++ = c ^ iv[n];
             iv[n] = c;
 
-            n = ( n + 1 ) & 0x0F;
+            n = (n + 1) & 0x0F;
         }
-    }
-    else
-    {
-        while( length-- )
-        {
-            if( n == 0 )
-                mbedtls_aria_crypt_ecb( ctx, iv, iv );
+    } else {
+        while (length--) {
+            if (n == 0) {
+                mbedtls_aria_crypt_ecb(ctx, iv, iv);
+            }
 
-            iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+            iv[n] = *output++ = (unsigned char) (iv[n] ^ *input++);
 
-            n = ( n + 1 ) & 0x0F;
+            n = (n + 1) & 0x0F;
         }
     }
 
     *iv_off = n;
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
@@ -713,50 +649,52 @@
 /*
  * ARIA-CTR buffer encryption/decryption
  */
-int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx,
-                            size_t length,
-                            size_t *nc_off,
-                            unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE],
-                            unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE],
-                            const unsigned char *input,
-                            unsigned char *output )
+int mbedtls_aria_crypt_ctr(mbedtls_aria_context *ctx,
+                           size_t length,
+                           size_t *nc_off,
+                           unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE],
+                           unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE],
+                           const unsigned char *input,
+                           unsigned char *output)
 {
     int c, i;
     size_t n;
 
-    ARIA_VALIDATE_RET( ctx != NULL );
-    ARIA_VALIDATE_RET( length == 0 || input  != NULL );
-    ARIA_VALIDATE_RET( length == 0 || output != NULL );
-    ARIA_VALIDATE_RET( nonce_counter != NULL );
-    ARIA_VALIDATE_RET( stream_block  != NULL );
-    ARIA_VALIDATE_RET( nc_off != NULL );
+    ARIA_VALIDATE_RET(ctx != NULL);
+    ARIA_VALIDATE_RET(length == 0 || input  != NULL);
+    ARIA_VALIDATE_RET(length == 0 || output != NULL);
+    ARIA_VALIDATE_RET(nonce_counter != NULL);
+    ARIA_VALIDATE_RET(stream_block  != NULL);
+    ARIA_VALIDATE_RET(nc_off != NULL);
 
     n = *nc_off;
     /* An overly large value of n can lead to an unlimited
      * buffer overflow. Therefore, guard against this
      * outside of parameter validation. */
-    if( n >= MBEDTLS_ARIA_BLOCKSIZE )
-        return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA );
+    if (n >= MBEDTLS_ARIA_BLOCKSIZE) {
+        return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;
+    }
 
-    while( length-- )
-    {
-        if( n == 0 ) {
-            mbedtls_aria_crypt_ecb( ctx, nonce_counter,
-                                stream_block );
+    while (length--) {
+        if (n == 0) {
+            mbedtls_aria_crypt_ecb(ctx, nonce_counter,
+                                   stream_block);
 
-            for( i = MBEDTLS_ARIA_BLOCKSIZE; i > 0; i-- )
-                if( ++nonce_counter[i - 1] != 0 )
+            for (i = MBEDTLS_ARIA_BLOCKSIZE; i > 0; i--) {
+                if (++nonce_counter[i - 1] != 0) {
                     break;
+                }
+            }
         }
         c = *input++;
-        *output++ = (unsigned char)( c ^ stream_block[n] );
+        *output++ = (unsigned char) (c ^ stream_block[n]);
 
-        n = ( n + 1 ) & 0x0F;
+        n = (n + 1) & 0x0F;
     }
 
     *nc_off = n;
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 #endif /* !MBEDTLS_ARIA_ALT */
@@ -895,20 +833,22 @@
 };
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
-#define ARIA_SELF_TEST_IF_FAIL              \
-        {                                   \
-            if( verbose )                   \
-                mbedtls_printf( "failed\n" );       \
+#define ARIA_SELF_TEST_ASSERT(cond)                   \
+    do {                                            \
+        if (cond) {                                \
+            if (verbose)                           \
+            mbedtls_printf("failed\n");       \
             goto exit;                              \
-        } else {                            \
-            if( verbose )                   \
-                mbedtls_printf( "passed\n" );       \
-        }
+        } else {                                    \
+            if (verbose)                           \
+            mbedtls_printf("passed\n");       \
+        }                                           \
+    } while (0)
 
 /*
  * Checkup routine
  */
-int mbedtls_aria_self_test( int verbose )
+int mbedtls_aria_self_test(int verbose)
 {
     int i;
     uint8_t blk[MBEDTLS_ARIA_BLOCKSIZE];
@@ -920,137 +860,142 @@
 #endif
 
 #if (defined(MBEDTLS_CIPHER_MODE_CBC) || \
-     defined(MBEDTLS_CIPHER_MODE_CFB) || \
-     defined(MBEDTLS_CIPHER_MODE_CTR))
+    defined(MBEDTLS_CIPHER_MODE_CFB) || \
+    defined(MBEDTLS_CIPHER_MODE_CTR))
     uint8_t buf[48], iv[MBEDTLS_ARIA_BLOCKSIZE];
 #endif
 
-    mbedtls_aria_init( &ctx );
+    mbedtls_aria_init(&ctx);
 
     /*
      * Test set 1
      */
-    for( i = 0; i < 3; i++ )
-    {
+    for (i = 0; i < 3; i++) {
         /* test ECB encryption */
-        if( verbose )
-            mbedtls_printf( "  ARIA-ECB-%d (enc): ", 128 + 64 * i );
-        mbedtls_aria_setkey_enc( &ctx, aria_test1_ecb_key, 128 + 64 * i );
-        mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_pt, blk );
-        if( memcmp( blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE ) != 0 )
-            ARIA_SELF_TEST_IF_FAIL;
+        if (verbose) {
+            mbedtls_printf("  ARIA-ECB-%d (enc): ", 128 + 64 * i);
+        }
+        mbedtls_aria_setkey_enc(&ctx, aria_test1_ecb_key, 128 + 64 * i);
+        mbedtls_aria_crypt_ecb(&ctx, aria_test1_ecb_pt, blk);
+        ARIA_SELF_TEST_ASSERT(
+            memcmp(blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE)
+            != 0);
 
         /* test ECB decryption */
-        if( verbose )
-            mbedtls_printf( "  ARIA-ECB-%d (dec): ", 128 + 64 * i );
-        mbedtls_aria_setkey_dec( &ctx, aria_test1_ecb_key, 128 + 64 * i );
-        mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_ct[i], blk );
-        if( memcmp( blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE ) != 0 )
-            ARIA_SELF_TEST_IF_FAIL;
+        if (verbose) {
+            mbedtls_printf("  ARIA-ECB-%d (dec): ", 128 + 64 * i);
+        }
+        mbedtls_aria_setkey_dec(&ctx, aria_test1_ecb_key, 128 + 64 * i);
+        mbedtls_aria_crypt_ecb(&ctx, aria_test1_ecb_ct[i], blk);
+        ARIA_SELF_TEST_ASSERT(
+            memcmp(blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE)
+            != 0);
     }
-    if( verbose )
-        mbedtls_printf( "\n" );
+    if (verbose) {
+        mbedtls_printf("\n");
+    }
 
     /*
      * Test set 2
      */
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-    for( i = 0; i < 3; i++ )
-    {
+    for (i = 0; i < 3; i++) {
         /* Test CBC encryption */
-        if( verbose )
-            mbedtls_printf( "  ARIA-CBC-%d (enc): ", 128 + 64 * i );
-        mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i );
-        memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE );
-        memset( buf, 0x55, sizeof( buf ) );
-        mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, iv,
-            aria_test2_pt, buf );
-        if( memcmp( buf, aria_test2_cbc_ct[i], 48 ) != 0 )
-            ARIA_SELF_TEST_IF_FAIL;
+        if (verbose) {
+            mbedtls_printf("  ARIA-CBC-%d (enc): ", 128 + 64 * i);
+        }
+        mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i);
+        memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE);
+        memset(buf, 0x55, sizeof(buf));
+        mbedtls_aria_crypt_cbc(&ctx, MBEDTLS_ARIA_ENCRYPT, 48, iv,
+                               aria_test2_pt, buf);
+        ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_cbc_ct[i], 48)
+                              != 0);
 
         /* Test CBC decryption */
-        if( verbose )
-            mbedtls_printf( "  ARIA-CBC-%d (dec): ", 128 + 64 * i );
-        mbedtls_aria_setkey_dec( &ctx, aria_test2_key, 128 + 64 * i );
-        memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE );
-        memset( buf, 0xAA, sizeof( buf ) );
-        mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_DECRYPT, 48, iv,
-            aria_test2_cbc_ct[i], buf );
-        if( memcmp( buf, aria_test2_pt, 48 ) != 0 )
-            ARIA_SELF_TEST_IF_FAIL;
+        if (verbose) {
+            mbedtls_printf("  ARIA-CBC-%d (dec): ", 128 + 64 * i);
+        }
+        mbedtls_aria_setkey_dec(&ctx, aria_test2_key, 128 + 64 * i);
+        memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE);
+        memset(buf, 0xAA, sizeof(buf));
+        mbedtls_aria_crypt_cbc(&ctx, MBEDTLS_ARIA_DECRYPT, 48, iv,
+                               aria_test2_cbc_ct[i], buf);
+        ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0);
     }
-    if( verbose )
-        mbedtls_printf( "\n" );
+    if (verbose) {
+        mbedtls_printf("\n");
+    }
 
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
-    for( i = 0; i < 3; i++ )
-    {
+    for (i = 0; i < 3; i++) {
         /* Test CFB encryption */
-        if( verbose )
-            mbedtls_printf( "  ARIA-CFB-%d (enc): ", 128 + 64 * i );
-        mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i );
-        memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE );
-        memset( buf, 0x55, sizeof( buf ) );
+        if (verbose) {
+            mbedtls_printf("  ARIA-CFB-%d (enc): ", 128 + 64 * i);
+        }
+        mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i);
+        memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE);
+        memset(buf, 0x55, sizeof(buf));
         j = 0;
-        mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, &j, iv,
-            aria_test2_pt, buf );
-        if( memcmp( buf, aria_test2_cfb_ct[i], 48 ) != 0 )
-            ARIA_SELF_TEST_IF_FAIL;
+        mbedtls_aria_crypt_cfb128(&ctx, MBEDTLS_ARIA_ENCRYPT, 48, &j, iv,
+                                  aria_test2_pt, buf);
+        ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_cfb_ct[i], 48) != 0);
 
         /* Test CFB decryption */
-        if( verbose )
-            mbedtls_printf( "  ARIA-CFB-%d (dec): ", 128 + 64 * i );
-        mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i );
-        memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE );
-        memset( buf, 0xAA, sizeof( buf ) );
+        if (verbose) {
+            mbedtls_printf("  ARIA-CFB-%d (dec): ", 128 + 64 * i);
+        }
+        mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i);
+        memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE);
+        memset(buf, 0xAA, sizeof(buf));
         j = 0;
-        mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_DECRYPT, 48, &j,
-            iv, aria_test2_cfb_ct[i], buf );
-        if( memcmp( buf, aria_test2_pt, 48 ) != 0 )
-            ARIA_SELF_TEST_IF_FAIL;
+        mbedtls_aria_crypt_cfb128(&ctx, MBEDTLS_ARIA_DECRYPT, 48, &j,
+                                  iv, aria_test2_cfb_ct[i], buf);
+        ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0);
     }
-    if( verbose )
-        mbedtls_printf( "\n" );
+    if (verbose) {
+        mbedtls_printf("\n");
+    }
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
-    for( i = 0; i < 3; i++ )
-    {
+    for (i = 0; i < 3; i++) {
         /* Test CTR encryption */
-        if( verbose )
-            mbedtls_printf( "  ARIA-CTR-%d (enc): ", 128 + 64 * i );
-        mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i );
-        memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE );                    // IV = 0
-        memset( buf, 0x55, sizeof( buf ) );
+        if (verbose) {
+            mbedtls_printf("  ARIA-CTR-%d (enc): ", 128 + 64 * i);
+        }
+        mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i);
+        memset(iv, 0, MBEDTLS_ARIA_BLOCKSIZE);                      // IV = 0
+        memset(buf, 0x55, sizeof(buf));
         j = 0;
-        mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk,
-            aria_test2_pt, buf );
-        if( memcmp( buf, aria_test2_ctr_ct[i], 48 ) != 0 )
-            ARIA_SELF_TEST_IF_FAIL;
+        mbedtls_aria_crypt_ctr(&ctx, 48, &j, iv, blk,
+                               aria_test2_pt, buf);
+        ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_ctr_ct[i], 48) != 0);
 
         /* Test CTR decryption */
-        if( verbose )
-            mbedtls_printf( "  ARIA-CTR-%d (dec): ", 128 + 64 * i );
-        mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i );
-        memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE );                    // IV = 0
-        memset( buf, 0xAA, sizeof( buf ) );
+        if (verbose) {
+            mbedtls_printf("  ARIA-CTR-%d (dec): ", 128 + 64 * i);
+        }
+        mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i);
+        memset(iv, 0, MBEDTLS_ARIA_BLOCKSIZE);                      // IV = 0
+        memset(buf, 0xAA, sizeof(buf));
         j = 0;
-        mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk,
-            aria_test2_ctr_ct[i], buf );
-        if( memcmp( buf, aria_test2_pt, 48 ) != 0 )
-            ARIA_SELF_TEST_IF_FAIL;
+        mbedtls_aria_crypt_ctr(&ctx, 48, &j, iv, blk,
+                               aria_test2_ctr_ct[i], buf);
+        ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0);
     }
-    if( verbose )
-        mbedtls_printf( "\n" );
+    if (verbose) {
+        mbedtls_printf("\n");
+    }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
     ret = 0;
 
 exit:
-    mbedtls_aria_free( &ctx );
-    return( ret );
+    mbedtls_aria_free(&ctx);
+    return ret;
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/lib/libmbedtls/mbedtls/library/asn1parse.c b/lib/libmbedtls/mbedtls/library/asn1parse.c
index 22747d3..d257ef4 100644
--- a/lib/libmbedtls/mbedtls/library/asn1parse.c
+++ b/lib/libmbedtls/mbedtls/library/asn1parse.c
@@ -31,214 +31,224 @@
 #include "mbedtls/bignum.h"
 #endif
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free       free
-#endif
 
 /*
  * ASN.1 DER decoding routines
  */
-int mbedtls_asn1_get_len( unsigned char **p,
-                  const unsigned char *end,
-                  size_t *len )
+int mbedtls_asn1_get_len(unsigned char **p,
+                         const unsigned char *end,
+                         size_t *len)
 {
-    if( ( end - *p ) < 1 )
-        return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+    if ((end - *p) < 1) {
+        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+    }
 
-    if( ( **p & 0x80 ) == 0 )
+    if ((**p & 0x80) == 0) {
         *len = *(*p)++;
-    else
-    {
-        switch( **p & 0x7F )
-        {
-        case 1:
-            if( ( end - *p ) < 2 )
-                return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+    } else {
+        switch (**p & 0x7F) {
+            case 1:
+                if ((end - *p) < 2) {
+                    return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+                }
 
-            *len = (*p)[1];
-            (*p) += 2;
-            break;
+                *len = (*p)[1];
+                (*p) += 2;
+                break;
 
-        case 2:
-            if( ( end - *p ) < 3 )
-                return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+            case 2:
+                if ((end - *p) < 3) {
+                    return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+                }
 
-            *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2];
-            (*p) += 3;
-            break;
+                *len = ((size_t) (*p)[1] << 8) | (*p)[2];
+                (*p) += 3;
+                break;
 
-        case 3:
-            if( ( end - *p ) < 4 )
-                return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+            case 3:
+                if ((end - *p) < 4) {
+                    return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+                }
 
-            *len = ( (size_t)(*p)[1] << 16 ) |
-                   ( (size_t)(*p)[2] << 8  ) | (*p)[3];
-            (*p) += 4;
-            break;
+                *len = ((size_t) (*p)[1] << 16) |
+                       ((size_t) (*p)[2] << 8) | (*p)[3];
+                (*p) += 4;
+                break;
 
-        case 4:
-            if( ( end - *p ) < 5 )
-                return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+            case 4:
+                if ((end - *p) < 5) {
+                    return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+                }
 
-            *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) |
-                   ( (size_t)(*p)[3] << 8  ) |           (*p)[4];
-            (*p) += 5;
-            break;
+                *len = ((size_t) (*p)[1] << 24) | ((size_t) (*p)[2] << 16) |
+                       ((size_t) (*p)[3] << 8) |           (*p)[4];
+                (*p) += 5;
+                break;
 
-        default:
-            return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+            default:
+                return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
         }
     }
 
-    if( *len > (size_t) ( end - *p ) )
-        return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+    if (*len > (size_t) (end - *p)) {
+        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+    }
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_asn1_get_tag( unsigned char **p,
-                  const unsigned char *end,
-                  size_t *len, int tag )
+int mbedtls_asn1_get_tag(unsigned char **p,
+                         const unsigned char *end,
+                         size_t *len, int tag)
 {
-    if( ( end - *p ) < 1 )
-        return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+    if ((end - *p) < 1) {
+        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+    }
 
-    if( **p != tag )
-        return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+    if (**p != tag) {
+        return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
+    }
 
     (*p)++;
 
-    return( mbedtls_asn1_get_len( p, end, len ) );
+    return mbedtls_asn1_get_len(p, end, len);
 }
 
-int mbedtls_asn1_get_bool( unsigned char **p,
-                   const unsigned char *end,
-                   int *val )
+int mbedtls_asn1_get_bool(unsigned char **p,
+                          const unsigned char *end,
+                          int *val)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BOOLEAN)) != 0) {
+        return ret;
+    }
 
-    if( len != 1 )
-        return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+    if (len != 1) {
+        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+    }
 
-    *val = ( **p != 0 ) ? 1 : 0;
+    *val = (**p != 0) ? 1 : 0;
     (*p)++;
 
-    return( 0 );
+    return 0;
 }
 
-static int asn1_get_tagged_int( unsigned char **p,
-                                const unsigned char *end,
-                                int tag, int *val )
+static int asn1_get_tagged_int(unsigned char **p,
+                               const unsigned char *end,
+                               int tag, int *val)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len, tag ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len, tag)) != 0) {
+        return ret;
+    }
 
     /*
      * len==0 is malformed (0 must be represented as 020100 for INTEGER,
      * or 0A0100 for ENUMERATED tags
      */
-    if( len == 0 )
-        return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+    if (len == 0) {
+        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+    }
     /* This is a cryptography library. Reject negative integers. */
-    if( ( **p & 0x80 ) != 0 )
-        return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+    if ((**p & 0x80) != 0) {
+        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+    }
 
     /* Skip leading zeros. */
-    while( len > 0 && **p == 0 )
-    {
-        ++( *p );
+    while (len > 0 && **p == 0) {
+        ++(*p);
         --len;
     }
 
     /* Reject integers that don't fit in an int. This code assumes that
      * the int type has no padding bit. */
-    if( len > sizeof( int ) )
-        return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
-    if( len == sizeof( int ) && ( **p & 0x80 ) != 0 )
-        return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+    if (len > sizeof(int)) {
+        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+    }
+    if (len == sizeof(int) && (**p & 0x80) != 0) {
+        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+    }
 
     *val = 0;
-    while( len-- > 0 )
-    {
-        *val = ( *val << 8 ) | **p;
+    while (len-- > 0) {
+        *val = (*val << 8) | **p;
         (*p)++;
     }
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_asn1_get_int( unsigned char **p,
+int mbedtls_asn1_get_int(unsigned char **p,
+                         const unsigned char *end,
+                         int *val)
+{
+    return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_INTEGER, val);
+}
+
+int mbedtls_asn1_get_enum(unsigned char **p,
                           const unsigned char *end,
-                          int *val )
+                          int *val)
 {
-    return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_INTEGER, val) );
-}
-
-int mbedtls_asn1_get_enum( unsigned char **p,
-                           const unsigned char *end,
-                           int *val )
-{
-    return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_ENUMERATED, val) );
+    return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_ENUMERATED, val);
 }
 
 #if defined(MBEDTLS_BIGNUM_C)
-int mbedtls_asn1_get_mpi( unsigned char **p,
-                  const unsigned char *end,
-                  mbedtls_mpi *X )
+int mbedtls_asn1_get_mpi(unsigned char **p,
+                         const unsigned char *end,
+                         mbedtls_mpi *X)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
+        return ret;
+    }
 
-    ret = mbedtls_mpi_read_binary( X, *p, len );
+    ret = mbedtls_mpi_read_binary(X, *p, len);
 
     *p += len;
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_BIGNUM_C */
 
-int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end,
-                        mbedtls_asn1_bitstring *bs)
+int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end,
+                               mbedtls_asn1_bitstring *bs)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     /* Certificate type is a single byte bitstring */
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
+        return ret;
+    }
 
     /* Check length, subtract one for actual bit string length */
-    if( bs->len < 1 )
-        return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+    if (bs->len < 1) {
+        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+    }
     bs->len -= 1;
 
     /* Get number of unused bits, ensure unused bits <= 7 */
     bs->unused_bits = **p;
-    if( bs->unused_bits > 7 )
-        return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+    if (bs->unused_bits > 7) {
+        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+    }
     (*p)++;
 
     /* Get actual bitstring */
     bs->p = *p;
     *p += bs->len;
 
-    if( *p != end )
-        return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+    if (*p != end) {
+        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -250,105 +260,105 @@
     const unsigned char *end,
     unsigned char tag_must_mask, unsigned char tag_must_val,
     unsigned char tag_may_mask, unsigned char tag_may_val,
-    int (*cb)( void *ctx, int tag,
-               unsigned char *start, size_t len ),
-    void *ctx )
+    int (*cb)(void *ctx, int tag,
+              unsigned char *start, size_t len),
+    void *ctx)
 {
     int ret;
     size_t len;
 
     /* Get main sequence tag */
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return ret;
     }
 
-    if( *p + len != end )
-        return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+    if (*p + len != end) {
+        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+    }
 
-    while( *p < end )
-    {
+    while (*p < end) {
         unsigned char const tag = *(*p)++;
 
-        if( ( tag & tag_must_mask ) != tag_must_val )
-            return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+        if ((tag & tag_must_mask) != tag_must_val) {
+            return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
+        }
 
-        if( ( ret = mbedtls_asn1_get_len( p, end, &len ) ) != 0 )
-            return( ret );
+        if ((ret = mbedtls_asn1_get_len(p, end, &len)) != 0) {
+            return ret;
+        }
 
-        if( ( tag & tag_may_mask ) == tag_may_val )
-        {
-            if( cb != NULL )
-            {
-                ret = cb( ctx, tag, *p, len );
-                if( ret != 0 )
-                    return( ret );
+        if ((tag & tag_may_mask) == tag_may_val) {
+            if (cb != NULL) {
+                ret = cb(ctx, tag, *p, len);
+                if (ret != 0) {
+                    return ret;
+                }
             }
         }
 
         *p += len;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Get a bit string without unused bits
  */
-int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
-                             size_t *len )
+int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end,
+                                    size_t *len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
+        return ret;
+    }
 
-    if( *len == 0 )
-        return( MBEDTLS_ERR_ASN1_INVALID_DATA );
-    --( *len );
+    if (*len == 0) {
+        return MBEDTLS_ERR_ASN1_INVALID_DATA;
+    }
+    --(*len);
 
-    if( **p != 0 )
-        return( MBEDTLS_ERR_ASN1_INVALID_DATA );
-    ++( *p );
+    if (**p != 0) {
+        return MBEDTLS_ERR_ASN1_INVALID_DATA;
+    }
+    ++(*p);
 
-    return( 0 );
+    return 0;
 }
 
-void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq )
+void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq)
 {
-    while( seq != NULL )
-    {
+    while (seq != NULL) {
         mbedtls_asn1_sequence *next = seq->next;
-        mbedtls_platform_zeroize( seq, sizeof( *seq ) );
-        mbedtls_free( seq );
+        mbedtls_free(seq);
         seq = next;
     }
 }
 
-typedef struct
-{
+typedef struct {
     int tag;
     mbedtls_asn1_sequence *cur;
 } asn1_get_sequence_of_cb_ctx_t;
 
-static int asn1_get_sequence_of_cb( void *ctx,
-                                    int tag,
-                                    unsigned char *start,
-                                    size_t len )
+static int asn1_get_sequence_of_cb(void *ctx,
+                                   int tag,
+                                   unsigned char *start,
+                                   size_t len)
 {
     asn1_get_sequence_of_cb_ctx_t *cb_ctx =
         (asn1_get_sequence_of_cb_ctx_t *) ctx;
     mbedtls_asn1_sequence *cur =
         cb_ctx->cur;
 
-    if( cur->buf.p != NULL )
-    {
+    if (cur->buf.p != NULL) {
         cur->next =
-            mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
+            mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
 
-        if( cur->next == NULL )
-            return( MBEDTLS_ERR_ASN1_ALLOC_FAILED );
+        if (cur->next == NULL) {
+            return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
+        }
 
         cur = cur->next;
     }
@@ -358,124 +368,139 @@
     cur->buf.tag = tag;
 
     cb_ctx->cur = cur;
-    return( 0 );
+    return 0;
 }
 
 /*
  *  Parses and splits an ASN.1 "SEQUENCE OF <tag>"
  */
-int mbedtls_asn1_get_sequence_of( unsigned char **p,
-                          const unsigned char *end,
-                          mbedtls_asn1_sequence *cur,
-                          int tag)
+int mbedtls_asn1_get_sequence_of(unsigned char **p,
+                                 const unsigned char *end,
+                                 mbedtls_asn1_sequence *cur,
+                                 int tag)
 {
     asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };
-    memset( cur, 0, sizeof( mbedtls_asn1_sequence ) );
-    return( mbedtls_asn1_traverse_sequence_of(
-                p, end, 0xFF, tag, 0, 0,
-                asn1_get_sequence_of_cb, &cb_ctx ) );
+    memset(cur, 0, sizeof(mbedtls_asn1_sequence));
+    return mbedtls_asn1_traverse_sequence_of(
+        p, end, 0xFF, tag, 0, 0,
+        asn1_get_sequence_of_cb, &cb_ctx);
 }
 
-int mbedtls_asn1_get_alg( unsigned char **p,
-                  const unsigned char *end,
-                  mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params )
+int mbedtls_asn1_get_alg(unsigned char **p,
+                         const unsigned char *end,
+                         mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return ret;
+    }
 
-    if( ( end - *p ) < 1 )
-        return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
+    if ((end - *p) < 1) {
+        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+    }
 
     alg->tag = **p;
     end = *p + len;
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &alg->len, MBEDTLS_ASN1_OID ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &alg->len, MBEDTLS_ASN1_OID)) != 0) {
+        return ret;
+    }
 
     alg->p = *p;
     *p += alg->len;
 
-    if( *p == end )
-    {
-        mbedtls_platform_zeroize( params, sizeof(mbedtls_asn1_buf) );
-        return( 0 );
+    if (*p == end) {
+        mbedtls_platform_zeroize(params, sizeof(mbedtls_asn1_buf));
+        return 0;
     }
 
     params->tag = **p;
     (*p)++;
 
-    if( ( ret = mbedtls_asn1_get_len( p, end, &params->len ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_asn1_get_len(p, end, &params->len)) != 0) {
+        return ret;
+    }
 
     params->p = *p;
     *p += params->len;
 
-    if( *p != end )
-        return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+    if (*p != end) {
+        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+    }
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_asn1_get_alg_null( unsigned char **p,
-                       const unsigned char *end,
-                       mbedtls_asn1_buf *alg )
+int mbedtls_asn1_get_alg_null(unsigned char **p,
+                              const unsigned char *end,
+                              mbedtls_asn1_buf *alg)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_asn1_buf params;
 
-    memset( &params, 0, sizeof(mbedtls_asn1_buf) );
+    memset(&params, 0, sizeof(mbedtls_asn1_buf));
 
-    if( ( ret = mbedtls_asn1_get_alg( p, end, alg, &params ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_asn1_get_alg(p, end, alg, &params)) != 0) {
+        return ret;
+    }
 
-    if( ( params.tag != MBEDTLS_ASN1_NULL && params.tag != 0 ) || params.len != 0 )
-        return( MBEDTLS_ERR_ASN1_INVALID_DATA );
+    if ((params.tag != MBEDTLS_ASN1_NULL && params.tag != 0) || params.len != 0) {
+        return MBEDTLS_ERR_ASN1_INVALID_DATA;
+    }
 
-    return( 0 );
+    return 0;
 }
 
-void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur )
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *cur)
 {
-    if( cur == NULL )
+    if (cur == NULL) {
         return;
+    }
 
-    mbedtls_free( cur->oid.p );
-    mbedtls_free( cur->val.p );
+    mbedtls_free(cur->oid.p);
+    mbedtls_free(cur->val.p);
 
-    mbedtls_platform_zeroize( cur, sizeof( mbedtls_asn1_named_data ) );
+    mbedtls_platform_zeroize(cur, sizeof(mbedtls_asn1_named_data));
 }
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
 
-void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head )
+void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head)
 {
     mbedtls_asn1_named_data *cur;
 
-    while( ( cur = *head ) != NULL )
-    {
+    while ((cur = *head) != NULL) {
         *head = cur->next;
-        mbedtls_asn1_free_named_data( cur );
-        mbedtls_free( cur );
+        mbedtls_free(cur->oid.p);
+        mbedtls_free(cur->val.p);
+        mbedtls_free(cur);
     }
 }
 
-mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list,
-                                       const char *oid, size_t len )
+void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name)
 {
-    while( list != NULL )
-    {
-        if( list->oid.len == len &&
-            memcmp( list->oid.p, oid, len ) == 0 )
-        {
+    for (mbedtls_asn1_named_data *next; name != NULL; name = next) {
+        next = name->next;
+        mbedtls_free(name);
+    }
+}
+
+const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data *list,
+                                                            const char *oid, size_t len)
+{
+    while (list != NULL) {
+        if (list->oid.len == len &&
+            memcmp(list->oid.p, oid, len) == 0) {
             break;
         }
 
         list = list->next;
     }
 
-    return( list );
+    return list;
 }
 
 #endif /* MBEDTLS_ASN1_PARSE_C */
diff --git a/lib/libmbedtls/mbedtls/library/asn1write.c b/lib/libmbedtls/mbedtls/library/asn1write.c
index afa26a6..b9d586a 100644
--- a/lib/libmbedtls/mbedtls/library/asn1write.c
+++ b/lib/libmbedtls/mbedtls/library/asn1write.c
@@ -26,460 +26,456 @@
 
 #include <string.h>
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free       free
-#endif
 
-int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len )
+int mbedtls_asn1_write_len(unsigned char **p, const unsigned char *start, size_t len)
 {
-    if( len < 0x80 )
-    {
-        if( *p - start < 1 )
-            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    if (len < 0x80) {
+        if (*p - start < 1) {
+            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+        }
 
         *--(*p) = (unsigned char) len;
-        return( 1 );
+        return 1;
     }
 
-    if( len <= 0xFF )
-    {
-        if( *p - start < 2 )
-            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    if (len <= 0xFF) {
+        if (*p - start < 2) {
+            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+        }
 
         *--(*p) = (unsigned char) len;
         *--(*p) = 0x81;
-        return( 2 );
+        return 2;
     }
 
-    if( len <= 0xFFFF )
-    {
-        if( *p - start < 3 )
-            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    if (len <= 0xFFFF) {
+        if (*p - start < 3) {
+            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+        }
 
-        *--(*p) = MBEDTLS_BYTE_0( len );
-        *--(*p) = MBEDTLS_BYTE_1( len );
+        *--(*p) = MBEDTLS_BYTE_0(len);
+        *--(*p) = MBEDTLS_BYTE_1(len);
         *--(*p) = 0x82;
-        return( 3 );
+        return 3;
     }
 
-    if( len <= 0xFFFFFF )
-    {
-        if( *p - start < 4 )
-            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    if (len <= 0xFFFFFF) {
+        if (*p - start < 4) {
+            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+        }
 
-        *--(*p) = MBEDTLS_BYTE_0( len );
-        *--(*p) = MBEDTLS_BYTE_1( len );
-        *--(*p) = MBEDTLS_BYTE_2( len );
+        *--(*p) = MBEDTLS_BYTE_0(len);
+        *--(*p) = MBEDTLS_BYTE_1(len);
+        *--(*p) = MBEDTLS_BYTE_2(len);
         *--(*p) = 0x83;
-        return( 4 );
+        return 4;
     }
 
+    int len_is_valid = 1;
 #if SIZE_MAX > 0xFFFFFFFF
-    if( len <= 0xFFFFFFFF )
+    len_is_valid = (len <= 0xFFFFFFFF);
 #endif
-    {
-        if( *p - start < 5 )
-            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    if (len_is_valid) {
+        if (*p - start < 5) {
+            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+        }
 
-        *--(*p) = MBEDTLS_BYTE_0( len );
-        *--(*p) = MBEDTLS_BYTE_1( len );
-        *--(*p) = MBEDTLS_BYTE_2( len );
-        *--(*p) = MBEDTLS_BYTE_3( len );
+        *--(*p) = MBEDTLS_BYTE_0(len);
+        *--(*p) = MBEDTLS_BYTE_1(len);
+        *--(*p) = MBEDTLS_BYTE_2(len);
+        *--(*p) = MBEDTLS_BYTE_3(len);
         *--(*p) = 0x84;
-        return( 5 );
+        return 5;
     }
 
-#if SIZE_MAX > 0xFFFFFFFF
-    return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
-#endif
+    return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
 }
 
-int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )
+int mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start, unsigned char tag)
 {
-    if( *p - start < 1 )
-        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    if (*p - start < 1) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    }
 
     *--(*p) = tag;
 
-    return( 1 );
+    return 1;
 }
 
-int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
-                           const unsigned char *buf, size_t size )
+int mbedtls_asn1_write_raw_buffer(unsigned char **p, const unsigned char *start,
+                                  const unsigned char *buf, size_t size)
 {
     size_t len = 0;
 
-    if( *p < start || (size_t)( *p - start ) < size )
-        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    if (*p < start || (size_t) (*p - start) < size) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    }
 
     len = size;
     (*p) -= len;
-    memcpy( *p, buf, len );
+    memcpy(*p, buf, len);
 
-    return( (int) len );
+    return (int) len;
 }
 
 #if defined(MBEDTLS_BIGNUM_C)
-int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X )
+int mbedtls_asn1_write_mpi(unsigned char **p, const unsigned char *start, const mbedtls_mpi *X)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
     // Write the MPI
     //
-    len = mbedtls_mpi_size( X );
+    len = mbedtls_mpi_size(X);
 
     /* DER represents 0 with a sign bit (0=nonnegative) and 7 value bits, not
      * as 0 digits. We need to end up with 020100, not with 0200. */
-    if( len == 0 )
+    if (len == 0) {
         len = 1;
+    }
 
-    if( *p < start || (size_t)( *p - start ) < len )
-        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    if (*p < start || (size_t) (*p - start) < len) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    }
 
     (*p) -= len;
-    MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(X, *p, len));
 
     // DER format assumes 2s complement for numbers, so the leftmost bit
     // should be 0 for positive numbers and 1 for negative numbers.
     //
-    if( X->s ==1 && **p & 0x80 )
-    {
-        if( *p - start < 1 )
-            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    if (X->s == 1 && **p & 0x80) {
+        if (*p - start < 1) {
+            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+        }
 
         *--(*p) = 0x00;
         len += 1;
     }
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_INTEGER));
 
     ret = (int) len;
 
 cleanup:
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_BIGNUM_C */
 
-int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start )
+int mbedtls_asn1_write_null(unsigned char **p, const unsigned char *start)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
     // Write NULL
     //
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, 0));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_NULL));
 
-    return( (int) len );
+    return (int) len;
 }
 
-int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start,
-                    const char *oid, size_t oid_len )
+int mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start,
+                           const char *oid, size_t oid_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
-                                  (const unsigned char *) oid, oid_len ) );
-    MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
+                                                            (const unsigned char *) oid, oid_len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OID));
 
-    return( (int) len );
+    return (int) len;
 }
 
-int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
-                                     const char *oid, size_t oid_len,
-                                     size_t par_len )
+int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, const unsigned char *start,
+                                            const char *oid, size_t oid_len,
+                                            size_t par_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
-    if( par_len == 0 )
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) );
-    else
+    if (par_len == 0) {
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_null(p, start));
+    } else {
         len += par_len;
+    }
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
-                                       MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
+                                                     MBEDTLS_ASN1_CONSTRUCTED |
+                                                     MBEDTLS_ASN1_SEQUENCE));
 
-    return( (int) len );
+    return (int) len;
 }
 
-int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean )
+int mbedtls_asn1_write_bool(unsigned char **p, const unsigned char *start, int boolean)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
-    if( *p - start < 1 )
-        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    if (*p - start < 1) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    }
 
     *--(*p) = (boolean) ? 255 : 0;
     len++;
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BOOLEAN));
 
-    return( (int) len );
+    return (int) len;
 }
 
-static int asn1_write_tagged_int( unsigned char **p, unsigned char *start, int val, int tag )
+static int asn1_write_tagged_int(unsigned char **p, const unsigned char *start, int val, int tag)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
-    do
-    {
-        if( *p - start < 1 )
-            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    do {
+        if (*p - start < 1) {
+            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+        }
         len += 1;
         *--(*p) = val & 0xff;
         val >>= 8;
-    }
-    while( val > 0 );
+    } while (val > 0);
 
-    if( **p & 0x80 )
-    {
-        if( *p - start < 1 )
-            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    if (**p & 0x80) {
+        if (*p - start < 1) {
+            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+        }
         *--(*p) = 0x00;
         len += 1;
     }
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag));
 
-    return( (int) len );
+    return (int) len;
 }
 
-int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
+int mbedtls_asn1_write_int(unsigned char **p, const unsigned char *start, int val)
 {
-    return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_INTEGER ) );
+    return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_INTEGER);
 }
 
-int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val )
+int mbedtls_asn1_write_enum(unsigned char **p, const unsigned char *start, int val)
 {
-    return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_ENUMERATED ) );
+    return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_ENUMERATED);
 }
 
-int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag,
-    const char *text, size_t text_len )
+int mbedtls_asn1_write_tagged_string(unsigned char **p, const unsigned char *start, int tag,
+                                     const char *text, size_t text_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
-        (const unsigned char *) text, text_len ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
+                                                            (const unsigned char *) text,
+                                                            text_len));
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag));
 
-    return( (int) len );
+    return (int) len;
 }
 
-int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start,
-    const char *text, size_t text_len )
+int mbedtls_asn1_write_utf8_string(unsigned char **p, const unsigned char *start,
+                                   const char *text, size_t text_len)
 {
-    return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) );
+    return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len);
 }
 
-int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start,
-                                 const char *text, size_t text_len )
+int mbedtls_asn1_write_printable_string(unsigned char **p, const unsigned char *start,
+                                        const char *text, size_t text_len)
 {
-    return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) );
+    return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text,
+                                            text_len);
 }
 
-int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
-                           const char *text, size_t text_len )
+int mbedtls_asn1_write_ia5_string(unsigned char **p, const unsigned char *start,
+                                  const char *text, size_t text_len)
 {
-    return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) );
+    return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len);
 }
 
-int mbedtls_asn1_write_named_bitstring( unsigned char **p,
-                                        unsigned char *start,
-                                        const unsigned char *buf,
-                                        size_t bits )
+int mbedtls_asn1_write_named_bitstring(unsigned char **p,
+                                       const unsigned char *start,
+                                       const unsigned char *buf,
+                                       size_t bits)
 {
     size_t unused_bits, byte_len;
     const unsigned char *cur_byte;
     unsigned char cur_byte_shifted;
     unsigned char bit;
 
-    byte_len = ( bits + 7 ) / 8;
-    unused_bits = ( byte_len * 8 ) - bits;
+    byte_len = (bits + 7) / 8;
+    unused_bits = (byte_len * 8) - bits;
 
     /*
      * Named bitstrings require that trailing 0s are excluded in the encoding
      * of the bitstring. Trailing 0s are considered part of the 'unused' bits
      * when encoding this value in the first content octet
      */
-    if( bits != 0 )
-    {
+    if (bits != 0) {
         cur_byte = buf + byte_len - 1;
         cur_byte_shifted = *cur_byte >> unused_bits;
 
-        for( ; ; )
-        {
+        for (;;) {
             bit = cur_byte_shifted & 0x1;
             cur_byte_shifted >>= 1;
 
-            if( bit != 0 )
+            if (bit != 0) {
                 break;
+            }
 
             bits--;
-            if( bits == 0 )
+            if (bits == 0) {
                 break;
+            }
 
-            if( bits % 8 == 0 )
+            if (bits % 8 == 0) {
                 cur_byte_shifted = *--cur_byte;
+            }
         }
     }
 
-    return( mbedtls_asn1_write_bitstring( p, start, buf, bits ) );
+    return mbedtls_asn1_write_bitstring(p, start, buf, bits);
 }
 
-int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
-                          const unsigned char *buf, size_t bits )
+int mbedtls_asn1_write_bitstring(unsigned char **p, const unsigned char *start,
+                                 const unsigned char *buf, size_t bits)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
     size_t unused_bits, byte_len;
 
-    byte_len = ( bits + 7 ) / 8;
-    unused_bits = ( byte_len * 8 ) - bits;
+    byte_len = (bits + 7) / 8;
+    unused_bits = (byte_len * 8) - bits;
 
-    if( *p < start || (size_t)( *p - start ) < byte_len + 1 )
-        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    if (*p < start || (size_t) (*p - start) < byte_len + 1) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    }
 
     len = byte_len + 1;
 
     /* Write the bitstring. Ensure the unused bits are zeroed */
-    if( byte_len > 0 )
-    {
+    if (byte_len > 0) {
         byte_len--;
-        *--( *p ) = buf[byte_len] & ~( ( 0x1 << unused_bits ) - 1 );
-        ( *p ) -= byte_len;
-        memcpy( *p, buf, byte_len );
+        *--(*p) = buf[byte_len] & ~((0x1 << unused_bits) - 1);
+        (*p) -= byte_len;
+        memcpy(*p, buf, byte_len);
     }
 
     /* Write unused bits */
-    *--( *p ) = (unsigned char)unused_bits;
+    *--(*p) = (unsigned char) unused_bits;
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BIT_STRING));
 
-    return( (int) len );
+    return (int) len;
 }
 
-int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start,
-                             const unsigned char *buf, size_t size )
+int mbedtls_asn1_write_octet_string(unsigned char **p, const unsigned char *start,
+                                    const unsigned char *buf, size_t size)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, buf, size));
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OCTET_STRING));
 
-    return( (int) len );
+    return (int) len;
 }
 
 
 /* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(),
  * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */
 static mbedtls_asn1_named_data *asn1_find_named_data(
-                                               mbedtls_asn1_named_data *list,
-                                               const char *oid, size_t len )
+    mbedtls_asn1_named_data *list,
+    const char *oid, size_t len)
 {
-    while( list != NULL )
-    {
-        if( list->oid.len == len &&
-            memcmp( list->oid.p, oid, len ) == 0 )
-        {
+    while (list != NULL) {
+        if (list->oid.len == len &&
+            memcmp(list->oid.p, oid, len) == 0) {
             break;
         }
 
         list = list->next;
     }
 
-    return( list );
+    return list;
 }
 
 mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(
-                                        mbedtls_asn1_named_data **head,
-                                        const char *oid, size_t oid_len,
-                                        const unsigned char *val,
-                                        size_t val_len )
+    mbedtls_asn1_named_data **head,
+    const char *oid, size_t oid_len,
+    const unsigned char *val,
+    size_t val_len)
 {
     mbedtls_asn1_named_data *cur;
 
-    if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL )
-    {
+    if ((cur = asn1_find_named_data(*head, oid, oid_len)) == NULL) {
         // Add new entry if not present yet based on OID
         //
-        cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1,
-                                            sizeof(mbedtls_asn1_named_data) );
-        if( cur == NULL )
-            return( NULL );
-
-        cur->oid.len = oid_len;
-        cur->oid.p = mbedtls_calloc( 1, oid_len );
-        if( cur->oid.p == NULL )
-        {
-            mbedtls_free( cur );
-            return( NULL );
+        cur = (mbedtls_asn1_named_data *) mbedtls_calloc(1,
+                                                         sizeof(mbedtls_asn1_named_data));
+        if (cur == NULL) {
+            return NULL;
         }
 
-        memcpy( cur->oid.p, oid, oid_len );
+        cur->oid.len = oid_len;
+        cur->oid.p = mbedtls_calloc(1, oid_len);
+        if (cur->oid.p == NULL) {
+            mbedtls_free(cur);
+            return NULL;
+        }
+
+        memcpy(cur->oid.p, oid, oid_len);
 
         cur->val.len = val_len;
-        if( val_len != 0 )
-        {
-            cur->val.p = mbedtls_calloc( 1, val_len );
-            if( cur->val.p == NULL )
-            {
-                mbedtls_free( cur->oid.p );
-                mbedtls_free( cur );
-                return( NULL );
+        if (val_len != 0) {
+            cur->val.p = mbedtls_calloc(1, val_len);
+            if (cur->val.p == NULL) {
+                mbedtls_free(cur->oid.p);
+                mbedtls_free(cur);
+                return NULL;
             }
         }
 
         cur->next = *head;
         *head = cur;
-    }
-    else if( val_len == 0 )
-    {
-        mbedtls_free( cur->val.p );
+    } else if (val_len == 0) {
+        mbedtls_free(cur->val.p);
         cur->val.p = NULL;
-    }
-    else if( cur->val.len != val_len )
-    {
+    } else if (cur->val.len != val_len) {
         /*
          * Enlarge existing value buffer if needed
          * Preserve old data until the allocation succeeded, to leave list in
          * a consistent state in case allocation fails.
          */
-        void *p = mbedtls_calloc( 1, val_len );
-        if( p == NULL )
-            return( NULL );
+        void *p = mbedtls_calloc(1, val_len);
+        if (p == NULL) {
+            return NULL;
+        }
 
-        mbedtls_free( cur->val.p );
+        mbedtls_free(cur->val.p);
         cur->val.p = p;
         cur->val.len = val_len;
     }
 
-    if( val != NULL && val_len != 0 )
-        memcpy( cur->val.p, val, val_len );
+    if (val != NULL && val_len != 0) {
+        memcpy(cur->val.p, val, val_len);
+    }
 
-    return( cur );
+    return cur;
 }
 #endif /* MBEDTLS_ASN1_WRITE_C */
diff --git a/lib/libmbedtls/mbedtls/library/base64.c b/lib/libmbedtls/mbedtls/library/base64.c
index 83daa0b..4170610 100644
--- a/lib/libmbedtls/mbedtls/library/base64.c
+++ b/lib/libmbedtls/mbedtls/library/base64.c
@@ -28,76 +28,68 @@
 
 #if defined(MBEDTLS_SELF_TEST)
 #include <string.h>
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
 #endif /* MBEDTLS_SELF_TEST */
 
-#define BASE64_SIZE_T_MAX   ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
+#define BASE64_SIZE_T_MAX   ((size_t) -1)   /* SIZE_T_MAX is not standard */
 
 /*
  * Encode a buffer into base64 format
  */
-int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
-                   const unsigned char *src, size_t slen )
+int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen,
+                          const unsigned char *src, size_t slen)
 {
     size_t i, n;
     int C1, C2, C3;
     unsigned char *p;
 
-    if( slen == 0 )
-    {
+    if (slen == 0) {
         *olen = 0;
-        return( 0 );
+        return 0;
     }
 
-    n = slen / 3 + ( slen % 3 != 0 );
+    n = slen / 3 + (slen % 3 != 0);
 
-    if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 )
-    {
+    if (n > (BASE64_SIZE_T_MAX - 1) / 4) {
         *olen = BASE64_SIZE_T_MAX;
-        return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
+        return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
     }
 
     n *= 4;
 
-    if( ( dlen < n + 1 ) || ( NULL == dst ) )
-    {
+    if ((dlen < n + 1) || (NULL == dst)) {
         *olen = n + 1;
-        return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
+        return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
     }
 
-    n = ( slen / 3 ) * 3;
+    n = (slen / 3) * 3;
 
-    for( i = 0, p = dst; i < n; i += 3 )
-    {
+    for (i = 0, p = dst; i < n; i += 3) {
         C1 = *src++;
         C2 = *src++;
         C3 = *src++;
 
-        *p++ = mbedtls_ct_base64_enc_char( ( C1 >> 2 ) & 0x3F );
-        *p++ = mbedtls_ct_base64_enc_char( ( ( ( C1 &  3 ) << 4 ) + ( C2 >> 4 ) )
-                                        & 0x3F );
-        *p++ = mbedtls_ct_base64_enc_char( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) )
-                                        & 0x3F );
-        *p++ = mbedtls_ct_base64_enc_char( C3 & 0x3F );
+        *p++ = mbedtls_ct_base64_enc_char((C1 >> 2) & 0x3F);
+        *p++ = mbedtls_ct_base64_enc_char((((C1 &  3) << 4) + (C2 >> 4))
+                                          & 0x3F);
+        *p++ = mbedtls_ct_base64_enc_char((((C2 & 15) << 2) + (C3 >> 6))
+                                          & 0x3F);
+        *p++ = mbedtls_ct_base64_enc_char(C3 & 0x3F);
     }
 
-    if( i < slen )
-    {
+    if (i < slen) {
         C1 = *src++;
-        C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
+        C2 = ((i + 1) < slen) ? *src++ : 0;
 
-        *p++ = mbedtls_ct_base64_enc_char( ( C1 >> 2 ) & 0x3F );
-        *p++ = mbedtls_ct_base64_enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) )
-                                        & 0x3F );
+        *p++ = mbedtls_ct_base64_enc_char((C1 >> 2) & 0x3F);
+        *p++ = mbedtls_ct_base64_enc_char((((C1 & 3) << 4) + (C2 >> 4))
+                                          & 0x3F);
 
-        if( ( i + 1 ) < slen )
-             *p++ = mbedtls_ct_base64_enc_char( ( ( C2 & 15 ) << 2 ) & 0x3F );
-        else *p++ = '=';
+        if ((i + 1) < slen) {
+            *p++ = mbedtls_ct_base64_enc_char(((C2 & 15) << 2) & 0x3F);
+        } else {
+            *p++ = '=';
+        }
 
         *p++ = '=';
     }
@@ -105,14 +97,14 @@
     *olen = p - dst;
     *p = 0;
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Decode a base64-formatted buffer
  */
-int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
-                   const unsigned char *src, size_t slen )
+int mbedtls_base64_decode(unsigned char *dst, size_t dlen, size_t *olen,
+                          const unsigned char *src, size_t slen)
 {
     size_t i; /* index in source */
     size_t n; /* number of digits or trailing = in source */
@@ -123,92 +115,97 @@
     unsigned char *p;
 
     /* First pass: check for validity and get output length */
-    for( i = n = 0; i < slen; i++ )
-    {
+    for (i = n = 0; i < slen; i++) {
         /* Skip spaces before checking for EOL */
         spaces_present = 0;
-        while( i < slen && src[i] == ' ' )
-        {
+        while (i < slen && src[i] == ' ') {
             ++i;
             spaces_present = 1;
         }
 
         /* Spaces at end of buffer are OK */
-        if( i == slen )
+        if (i == slen) {
             break;
+        }
 
-        if( ( slen - i ) >= 2 &&
-            src[i] == '\r' && src[i + 1] == '\n' )
+        if ((slen - i) >= 2 &&
+            src[i] == '\r' && src[i + 1] == '\n') {
             continue;
+        }
 
-        if( src[i] == '\n' )
+        if (src[i] == '\n') {
             continue;
+        }
 
         /* Space inside a line is an error */
-        if( spaces_present )
-            return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
-
-        if( src[i] > 127 )
-            return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
-
-        if( src[i] == '=' )
-        {
-            if( ++equals > 2 )
-                return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+        if (spaces_present) {
+            return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
         }
-        else
-        {
-            if( equals != 0 )
-                return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
-            if( mbedtls_ct_base64_dec_value( src[i] ) < 0 )
-                return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+
+        if (src[i] > 127) {
+            return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
+        }
+
+        if (src[i] == '=') {
+            if (++equals > 2) {
+                return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
+            }
+        } else {
+            if (equals != 0) {
+                return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
+            }
+            if (mbedtls_ct_base64_dec_value(src[i]) < 0) {
+                return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
+            }
         }
         n++;
     }
 
-    if( n == 0 )
-    {
+    if (n == 0) {
         *olen = 0;
-        return( 0 );
+        return 0;
     }
 
     /* The following expression is to calculate the following formula without
      * risk of integer overflow in n:
      *     n = ( ( n * 6 ) + 7 ) >> 3;
      */
-    n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 );
+    n = (6 * (n >> 3)) + ((6 * (n & 0x7) + 7) >> 3);
     n -= equals;
 
-    if( dst == NULL || dlen < n )
-    {
+    if (dst == NULL || dlen < n) {
         *olen = n;
-        return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
+        return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
     }
 
     equals = 0;
-    for( x = 0, p = dst; i > 0; i--, src++ )
-    {
-        if( *src == '\r' || *src == '\n' || *src == ' ' )
+    for (x = 0, p = dst; i > 0; i--, src++) {
+        if (*src == '\r' || *src == '\n' || *src == ' ') {
             continue;
+        }
 
         x = x << 6;
-        if( *src == '=' )
+        if (*src == '=') {
             ++equals;
-        else
-            x |= mbedtls_ct_base64_dec_value( *src );
+        } else {
+            x |= mbedtls_ct_base64_dec_value(*src);
+        }
 
-        if( ++accumulated_digits == 4 )
-        {
+        if (++accumulated_digits == 4) {
             accumulated_digits = 0;
-            *p++ = MBEDTLS_BYTE_2( x );
-            if( equals <= 1 ) *p++ = MBEDTLS_BYTE_1( x );
-            if( equals <= 0 ) *p++ = MBEDTLS_BYTE_0( x );
+            *p++ = MBEDTLS_BYTE_2(x);
+            if (equals <= 1) {
+                *p++ = MBEDTLS_BYTE_1(x);
+            }
+            if (equals <= 0) {
+                *p++ = MBEDTLS_BYTE_0(x);
+            }
         }
     }
 
     *olen = p - dst;
 
-    return( 0 );
+    return 0;
 }
 
 #if defined(MBEDTLS_SELF_TEST)
@@ -232,44 +229,47 @@
 /*
  * Checkup routine
  */
-int mbedtls_base64_self_test( int verbose )
+int mbedtls_base64_self_test(int verbose)
 {
     size_t len;
     const unsigned char *src;
     unsigned char buffer[128];
 
-    if( verbose != 0 )
-        mbedtls_printf( "  Base64 encoding test: " );
+    if (verbose != 0) {
+        mbedtls_printf("  Base64 encoding test: ");
+    }
 
     src = base64_test_dec;
 
-    if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 ||
-         memcmp( base64_test_enc, buffer, 88 ) != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
+    if (mbedtls_base64_encode(buffer, sizeof(buffer), &len, src, 64) != 0 ||
+        memcmp(base64_test_enc, buffer, 88) != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("failed\n");
+        }
 
-        return( 1 );
+        return 1;
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n  Base64 decoding test: " );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n  Base64 decoding test: ");
+    }
 
     src = base64_test_enc;
 
-    if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 ||
-         memcmp( base64_test_dec, buffer, 64 ) != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
+    if (mbedtls_base64_decode(buffer, sizeof(buffer), &len, src, 88) != 0 ||
+        memcmp(base64_test_dec, buffer, 64) != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("failed\n");
+        }
 
-        return( 1 );
+        return 1;
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n\n");
+    }
 
-    return( 0 );
+    return 0;
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/lib/libmbedtls/mbedtls/library/bignum.c b/lib/libmbedtls/mbedtls/library/bignum.c
index 598a78c..b6733b7 100644
--- a/lib/libmbedtls/mbedtls/library/bignum.c
+++ b/lib/libmbedtls/mbedtls/library/bignum.c
@@ -38,7 +38,8 @@
 #if defined(MBEDTLS_BIGNUM_C)
 
 #include "mbedtls/bignum.h"
-#include "mbedtls/bn_mul.h"
+#include "bignum_core.h"
+#include "bn_mul.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 #include "constant_time_internal.h"
@@ -46,51 +47,32 @@
 #include <limits.h>
 #include <string.h>
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#define mbedtls_printf     printf
-#define mbedtls_calloc    calloc
-#define mbedtls_free       free
-#endif
 
 #include <mempool.h>
 #include <util.h>
 
-#define MPI_VALIDATE_RET( cond )                                       \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
-#define MPI_VALIDATE( cond )                                           \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
+#define MPI_VALIDATE_RET(cond)                                       \
+    MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA)
+#define MPI_VALIDATE(cond)                                           \
+    MBEDTLS_INTERNAL_VALIDATE(cond)
 
-#define ciL    (sizeof(mbedtls_mpi_uint))         /* chars in limb  */
-#define biL    (ciL << 3)               /* bits  in limb  */
-#define biH    (ciL << 2)               /* half limb size */
-
-#define MPI_SIZE_T_MAX  ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
-
-/*
- * Convert between bits/chars and number of limbs
- * Divide first in order to avoid potential overflows
- */
-#define BITS_TO_LIMBS(i)  ( (i) / biL + ( (i) % biL != 0 ) )
-#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
+#define MPI_SIZE_T_MAX  ((size_t) -1)   /* SIZE_T_MAX is not standard */
 
 void *mbedtls_mpi_mempool;
 
 /* Implementation that should never be optimized out by the compiler */
-static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
+static void mbedtls_mpi_zeroize(mbedtls_mpi_uint *v, size_t n)
 {
-    mbedtls_platform_zeroize( v, ciL * n );
+    mbedtls_platform_zeroize(v, ciL * n);
 }
 
 /*
  * Initialize one MPI
  */
-static void mpi_init( mbedtls_mpi *X, short use_mempool )
+static void mpi_init(mbedtls_mpi *X, short use_mempool)
 {
-    MPI_VALIDATE( X != NULL );
+    MPI_VALIDATE(X != NULL);
 
     X->s = 1;
     X->use_mempool = use_mempool;
@@ -98,31 +80,31 @@
     X->p = NULL;
 }
 
-void mbedtls_mpi_init( mbedtls_mpi *X )
+void mbedtls_mpi_init(mbedtls_mpi *X)
 {
-    mpi_init( X, 0 /*use_mempool*/ );
+    mpi_init(X, 0 /*use_mempool*/);
 }
 
-void mbedtls_mpi_init_mempool( mbedtls_mpi *X )
+void mbedtls_mpi_init_mempool(mbedtls_mpi *X)
 {
-    mpi_init( X, !!mbedtls_mpi_mempool /*use_mempool*/ );
+    mpi_init(X, !!mbedtls_mpi_mempool /*use_mempool*/);
 }
 
 /*
  * Unallocate one MPI
  */
-void mbedtls_mpi_free( mbedtls_mpi *X )
+void mbedtls_mpi_free(mbedtls_mpi *X)
 {
-    if( X == NULL )
+    if (X == NULL) {
         return;
+    }
 
-    if( X->p != NULL )
-    {
-        mbedtls_mpi_zeroize( X->p, X->n );
-        if( X->use_mempool )
-            mempool_free( mbedtls_mpi_mempool, X->p );
+    if (X->p != NULL) {
+        mbedtls_mpi_zeroize(X->p, X->n);
+        if(X->use_mempool)
+            mempool_free(mbedtls_mpi_mempool, X->p);
         else
-            mbedtls_free( X->p );
+        mbedtls_free(X->p);
     }
 
     X->s = 1;
@@ -133,121 +115,112 @@
 /*
  * Enlarge to the specified number of limbs
  */
-int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
+int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
 {
     mbedtls_mpi_uint *p;
-    MPI_VALIDATE_RET( X != NULL );
+    MPI_VALIDATE_RET(X != NULL);
 
-    if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
-        return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
+    if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
+        return MBEDTLS_ERR_MPI_ALLOC_FAILED;
+    }
 
-    if( X->n < nblimbs )
-    {
-        if( X->use_mempool )
-        {
-            p = mempool_alloc( mbedtls_mpi_mempool, nblimbs * ciL );
-            if( p == NULL )
-                return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
-            memset( p, 0, nblimbs * ciL );
-        }
-        else
-        {
-            p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL );
-            if( p == NULL )
-                return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
+    if (X->n < nblimbs) {
+        if(X->use_mempool) {
+            p = mempool_alloc(mbedtls_mpi_mempool, nblimbs * ciL);
+            if(p == NULL)
+                return MBEDTLS_ERR_MPI_ALLOC_FAILED;
+            memset(p, 0, nblimbs * ciL);
+        } else {
+                p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL);
+                if (p == NULL)
+                    return MBEDTLS_ERR_MPI_ALLOC_FAILED;
         }
 
-        if( X->p != NULL )
-        {
-            memcpy( p, X->p, X->n * ciL );
-            mbedtls_mpi_zeroize( X->p, X->n );
-            if( X->use_mempool )
-                mempool_free( mbedtls_mpi_mempool, X->p);
+        if (X->p != NULL) {
+            memcpy(p, X->p, X->n * ciL);
+            mbedtls_mpi_zeroize(X->p, X->n);
+            if (X->use_mempool)
+                mempool_free(mbedtls_mpi_mempool, X->p);
             else
-                mbedtls_free( X->p );
+                mbedtls_free(X->p);
         }
 
         X->n = nblimbs;
         X->p = p;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Resize down as much as possible,
  * while keeping at least the specified number of limbs
  */
-int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
+int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
 {
     mbedtls_mpi_uint *p;
     size_t i;
-    MPI_VALIDATE_RET( X != NULL );
+    MPI_VALIDATE_RET(X != NULL);
 
-    if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
-        return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
+    if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
+        return MBEDTLS_ERR_MPI_ALLOC_FAILED;
+    }
 
     /* Actually resize up if there are currently fewer than nblimbs limbs. */
-    if( X->n <= nblimbs )
-        return( mbedtls_mpi_grow( X, nblimbs ) );
+    if (X->n <= nblimbs) {
+        return mbedtls_mpi_grow(X, nblimbs);
+    }
     /* After this point, then X->n > nblimbs and in particular X->n > 0. */
 
-    for( i = X->n - 1; i > 0; i-- )
-        if( X->p[i] != 0 )
+    for (i = X->n - 1; i > 0; i--) {
+        if (X->p[i] != 0) {
             break;
+        }
+    }
     i++;
 
-    if( i < nblimbs )
+    if (i < nblimbs) {
         i = nblimbs;
-
-    if( X->use_mempool )
-    {
-        p = mempool_alloc( mbedtls_mpi_mempool, i * ciL );
-        if( p == NULL )
-            return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
-        memset( p, 0, i * ciL );
-    }
-    else
-    {
-        p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL );
-        if( p == NULL )
-            return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
     }
 
-    if( X->p != NULL )
-    {
-        memcpy( p, X->p, i * ciL );
-        mbedtls_mpi_zeroize( X->p, X->n );
-        if( X->use_mempool )
-            mempool_free( mbedtls_mpi_mempool, X->p );
+    if (X->use_mempool) {
+        p = mempool_alloc(mbedtls_mpi_mempool, i * ciL);
+        if (p == NULL)
+            return MBEDTLS_ERR_MPI_ALLOC_FAILED;
+        memset(p, 0, i * ciL);
+    } else {
+        if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL)
+            return MBEDTLS_ERR_MPI_ALLOC_FAILED;
+    }
+
+    if (X->p != NULL) {
+        memcpy(p, X->p, i * ciL);
+        mbedtls_mpi_zeroize(X->p, X->n);
+        if (X->use_mempool)
+            mempool_free(mbedtls_mpi_mempool, X->p);
         else
-            mbedtls_free( X->p );
+            mbedtls_free(X->p);
     }
 
     X->n = i;
     X->p = p;
 
-    return( 0 );
+    return 0;
 }
 
 /* Resize X to have exactly n limbs and set it to 0. */
-static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs )
+static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
 {
-    if( limbs == 0 )
-    {
-        mbedtls_mpi_free( X );
-        return( 0 );
-    }
-    else if( X->n == limbs )
-    {
-        memset( X->p, 0, limbs * ciL );
+    if (limbs == 0) {
+        mbedtls_mpi_free(X);
+        return 0;
+    } else if (X->n == limbs) {
+        memset(X->p, 0, limbs * ciL);
         X->s = 1;
-        return( 0 );
-    }
-    else
-    {
-        mbedtls_mpi_free( X );
-        return( mbedtls_mpi_grow( X, limbs ) );
+        return 0;
+    } else {
+        mbedtls_mpi_free(X);
+        return mbedtls_mpi_grow(X, limbs);
     }
 }
 
@@ -260,390 +233,374 @@
  * but some code in the bignum module relies on this property, for example
  * in mbedtls_mpi_exp_mod().
  */
-int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
+int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
 {
     int ret = 0;
     size_t i;
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( Y != NULL );
+    MPI_VALIDATE_RET(X != NULL);
+    MPI_VALIDATE_RET(Y != NULL);
 
-    if( X == Y )
-        return( 0 );
-
-    if( Y->n == 0 )
-    {
-        if( X->n != 0 )
-        {
-            X->s = 1;
-            memset( X->p, 0, X->n * ciL );
-        }
-        return( 0 );
+    if (X == Y) {
+        return 0;
     }
 
-    for( i = Y->n - 1; i > 0; i-- )
-        if( Y->p[i] != 0 )
+    if (Y->n == 0) {
+        if (X->n != 0) {
+            X->s = 1;
+            memset(X->p, 0, X->n * ciL);
+        }
+        return 0;
+    }
+
+    for (i = Y->n - 1; i > 0; i--) {
+        if (Y->p[i] != 0) {
             break;
+        }
+    }
     i++;
 
     X->s = Y->s;
 
-    if( X->n < i )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
-    }
-    else
-    {
-        memset( X->p + i, 0, ( X->n - i ) * ciL );
+    if (X->n < i) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i));
+    } else {
+        memset(X->p + i, 0, (X->n - i) * ciL);
     }
 
-    memcpy( X->p, Y->p, i * ciL );
+    memcpy(X->p, Y->p, i * ciL);
 
 cleanup:
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Swap the contents of X and Y
  */
-void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
+void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
 {
     mbedtls_mpi T;
-    MPI_VALIDATE( X != NULL );
-    MPI_VALIDATE( Y != NULL );
+    MPI_VALIDATE(X != NULL);
+    MPI_VALIDATE(Y != NULL);
 
-    memcpy( &T,  X, sizeof( mbedtls_mpi ) );
-    memcpy(  X,  Y, sizeof( mbedtls_mpi ) );
-    memcpy(  Y, &T, sizeof( mbedtls_mpi ) );
+    memcpy(&T,  X, sizeof(mbedtls_mpi));
+    memcpy(X,  Y, sizeof(mbedtls_mpi));
+    memcpy(Y, &T, sizeof(mbedtls_mpi));
+}
+
+static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
+{
+    if (z >= 0) {
+        return z;
+    }
+    /* Take care to handle the most negative value (-2^(biL-1)) correctly.
+     * A naive -z would have undefined behavior.
+     * Write this in a way that makes popular compilers happy (GCC, Clang,
+     * MSVC). */
+    return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
 }
 
 /*
  * Set value from integer
  */
-int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
+int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    MPI_VALIDATE_RET( X != NULL );
+    MPI_VALIDATE_RET(X != NULL);
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
-    memset( X->p, 0, X->n * ciL );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
+    memset(X->p, 0, X->n * ciL);
 
-    X->p[0] = ( z < 0 ) ? -z : z;
-    X->s    = ( z < 0 ) ? -1 : 1;
+    X->p[0] = mpi_sint_abs(z);
+    X->s    = (z < 0) ? -1 : 1;
 
 cleanup:
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Get a specific bit
  */
-int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
+int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
 {
-    MPI_VALIDATE_RET( X != NULL );
+    MPI_VALIDATE_RET(X != NULL);
 
-    if( X->n * biL <= pos )
-        return( 0 );
+    if (X->n * biL <= pos) {
+        return 0;
+    }
 
-    return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
+    return (X->p[pos / biL] >> (pos % biL)) & 0x01;
 }
 
-/* Get a specific byte, without range checks. */
-#define GET_BYTE( X, i )                                \
-    ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
-
 /*
  * Set a bit to a specific value of 0 or 1
  */
-int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
+int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
 {
     int ret = 0;
     size_t off = pos / biL;
     size_t idx = pos % biL;
-    MPI_VALIDATE_RET( X != NULL );
+    MPI_VALIDATE_RET(X != NULL);
 
-    if( val != 0 && val != 1 )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-
-    if( X->n * biL <= pos )
-    {
-        if( val == 0 )
-            return( 0 );
-
-        MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
+    if (val != 0 && val != 1) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
     }
 
-    X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
+    if (X->n * biL <= pos) {
+        if (val == 0) {
+            return 0;
+        }
+
+        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1));
+    }
+
+    X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx);
     X->p[off] |= (mbedtls_mpi_uint) val << idx;
 
 cleanup:
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Return the number of less significant zero-bits
  */
-size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
+size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
 {
     size_t i, j, count = 0;
-    MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
+    MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0);
 
-    for( i = 0; i < X->n; i++ )
-        for( j = 0; j < biL; j++, count++ )
-            if( ( ( X->p[i] >> j ) & 1 ) != 0 )
-                return( count );
-
-    return( 0 );
-}
-
-/*
- * Count leading zero bits in a given integer
- */
-static size_t mbedtls_clz( const mbedtls_mpi_uint x )
-{
-    size_t j;
-    mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
-
-    for( j = 0; j < biL; j++ )
-    {
-        if( x & mask ) break;
-
-        mask >>= 1;
+    for (i = 0; i < X->n; i++) {
+        for (j = 0; j < biL; j++, count++) {
+            if (((X->p[i] >> j) & 1) != 0) {
+                return count;
+            }
+        }
     }
 
-    return j;
+    return 0;
 }
 
 /*
  * Return the number of bits
  */
-size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
+size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X)
 {
-    size_t i, j;
-
-    if( X->n == 0 )
-        return( 0 );
-
-    for( i = X->n - 1; i > 0; i-- )
-        if( X->p[i] != 0 )
-            break;
-
-    j = biL - mbedtls_clz( X->p[i] );
-
-    return( ( i * biL ) + j );
+    return mbedtls_mpi_core_bitlen(X->p, X->n);
 }
 
 /*
  * Return the total size in bytes
  */
-size_t mbedtls_mpi_size( const mbedtls_mpi *X )
+size_t mbedtls_mpi_size(const mbedtls_mpi *X)
 {
-    return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
+    return (mbedtls_mpi_bitlen(X) + 7) >> 3;
 }
 
 /*
  * Convert an ASCII character to digit value
  */
-static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
+static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c)
 {
     *d = 255;
 
-    if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
-    if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
-    if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
+    if (c >= 0x30 && c <= 0x39) {
+        *d = c - 0x30;
+    }
+    if (c >= 0x41 && c <= 0x46) {
+        *d = c - 0x37;
+    }
+    if (c >= 0x61 && c <= 0x66) {
+        *d = c - 0x57;
+    }
 
-    if( *d >= (mbedtls_mpi_uint) radix )
-        return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
+    if (*d >= (mbedtls_mpi_uint) radix) {
+        return MBEDTLS_ERR_MPI_INVALID_CHARACTER;
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Import from an ASCII string
  */
-int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
+int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i, j, slen, n;
     int sign = 1;
     mbedtls_mpi_uint d;
     mbedtls_mpi T;
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( s != NULL );
+    MPI_VALIDATE_RET(X != NULL);
+    MPI_VALIDATE_RET(s != NULL);
 
-    if( radix < 2 || radix > 16 )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-
-    mbedtls_mpi_init_mempool( &T );
-
-    if( s[0] == 0 )
-    {
-        mbedtls_mpi_free( X );
-        return( 0 );
+    if (radix < 2 || radix > 16) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
     }
 
-    if( s[0] == '-' )
-    {
+    mbedtls_mpi_init_mempool(&T);
+
+    if (s[0] == 0) {
+        mbedtls_mpi_free(X);
+        return 0;
+    }
+
+    if (s[0] == '-') {
         ++s;
         sign = -1;
     }
 
-    slen = strlen( s );
+    slen = strlen(s);
 
-    if( radix == 16 )
-    {
-        if( slen > MPI_SIZE_T_MAX >> 2 )
-            return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-
-        n = BITS_TO_LIMBS( slen << 2 );
-
-        MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
-
-        for( i = slen, j = 0; i > 0; i--, j++ )
-        {
-            MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
-            X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
+    if (radix == 16) {
+        if (slen > MPI_SIZE_T_MAX >> 2) {
+            return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
         }
-    }
-    else
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
 
-        for( i = 0; i < slen; i++ )
-        {
-            MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
+        n = BITS_TO_LIMBS(slen << 2);
+
+        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
+
+        for (i = slen, j = 0; i > 0; i--, j++) {
+            MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1]));
+            X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2);
+        }
+    } else {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
+
+        for (i = 0; i < slen; i++) {
+            MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i]));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d));
         }
     }
 
-    if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
+    if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) {
         X->s = -1;
+    }
 
 cleanup:
 
-    mbedtls_mpi_free( &T );
+    mbedtls_mpi_free(&T);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Helper to write the digits high-order first.
  */
-static int mpi_write_hlp( mbedtls_mpi *X, int radix,
-                          char **p, const size_t buflen )
+static int mpi_write_hlp(mbedtls_mpi *X, int radix,
+                         char **p, const size_t buflen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_mpi_uint r;
     size_t length = 0;
     char *p_end = *p + buflen;
 
-    do
-    {
-        if( length >= buflen )
-        {
-            return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
+    do {
+        if (length >= buflen) {
+            return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
         }
 
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix));
         /*
          * Write the residue in the current position, as an ASCII character.
          */
-        if( r < 0xA )
-            *(--p_end) = (char)( '0' + r );
-        else
-            *(--p_end) = (char)( 'A' + ( r - 0xA ) );
+        if (r < 0xA) {
+            *(--p_end) = (char) ('0' + r);
+        } else {
+            *(--p_end) = (char) ('A' + (r - 0xA));
+        }
 
         length++;
-    } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
+    } while (mbedtls_mpi_cmp_int(X, 0) != 0);
 
-    memmove( *p, p_end, length );
+    memmove(*p, p_end, length);
     *p += length;
 
 cleanup:
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Export into an ASCII string
  */
-int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
-                              char *buf, size_t buflen, size_t *olen )
+int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
+                             char *buf, size_t buflen, size_t *olen)
 {
     int ret = 0;
     size_t n;
     char *p;
     mbedtls_mpi T;
-    MPI_VALIDATE_RET( X    != NULL );
-    MPI_VALIDATE_RET( olen != NULL );
-    MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
+    MPI_VALIDATE_RET(X    != NULL);
+    MPI_VALIDATE_RET(olen != NULL);
+    MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
 
-    if( radix < 2 || radix > 16 )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+    if (radix < 2 || radix > 16) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
 
-    n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
-    if( radix >=  4 ) n >>= 1;   /* Number of 4-adic digits necessary to present
+    n = mbedtls_mpi_bitlen(X);   /* Number of bits necessary to present `n`. */
+    if (radix >=  4) {
+        n >>= 1;                 /* Number of 4-adic digits necessary to present
                                   * `n`. If radix > 4, this might be a strict
                                   * overapproximation of the number of
                                   * radix-adic digits needed to present `n`. */
-    if( radix >= 16 ) n >>= 1;   /* Number of hexadecimal digits necessary to
+    }
+    if (radix >= 16) {
+        n >>= 1;                 /* Number of hexadecimal digits necessary to
                                   * present `n`. */
 
+    }
     n += 1; /* Terminating null byte */
     n += 1; /* Compensate for the divisions above, which round down `n`
              * in case it's not even. */
     n += 1; /* Potential '-'-sign. */
-    n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
+    n += (n & 1);   /* Make n even to have enough space for hexadecimal writing,
                      * which always uses an even number of hex-digits. */
 
-    if( buflen < n )
-    {
+    if (buflen < n) {
         *olen = n;
-        return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
+        return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
     }
 
     p = buf;
-    mbedtls_mpi_init_mempool( &T );
+    mbedtls_mpi_init_mempool(&T);
 
-    if( X->s == -1 )
-    {
+    if (X->s == -1) {
         *p++ = '-';
         buflen--;
     }
 
-    if( radix == 16 )
-    {
+    if (radix == 16) {
         int c;
         size_t i, j, k;
 
-        for( i = X->n, k = 0; i > 0; i-- )
-        {
-            for( j = ciL; j > 0; j-- )
-            {
-                c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
+        for (i = X->n, k = 0; i > 0; i--) {
+            for (j = ciL; j > 0; j--) {
+                c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF;
 
-                if( c == 0 && k == 0 && ( i + j ) != 2 )
+                if (c == 0 && k == 0 && (i + j) != 2) {
                     continue;
+                }
 
                 *(p++) = "0123456789ABCDEF" [c / 16];
                 *(p++) = "0123456789ABCDEF" [c % 16];
                 k = 1;
             }
         }
-    }
-    else
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
+    } else {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X));
 
-        if( T.s == -1 )
+        if (T.s == -1) {
             T.s = 1;
+        }
 
-        MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
+        MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen));
     }
 
     *p++ = '\0';
@@ -651,16 +608,16 @@
 
 cleanup:
 
-    mbedtls_mpi_free( &T );
+    mbedtls_mpi_free(&T);
 
-    return( ret );
+    return ret;
 }
 
 #if defined(MBEDTLS_FS_IO)
 /*
  * Read X from an opened file
  */
-int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
+int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
 {
     mbedtls_mpi_uint d;
     size_t slen;
@@ -669,37 +626,46 @@
      * Buffer should have space for (short) label and decimal formatted MPI,
      * newline characters and '\0'
      */
-    char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
+    char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
 
-    MPI_VALIDATE_RET( X   != NULL );
-    MPI_VALIDATE_RET( fin != NULL );
+    MPI_VALIDATE_RET(X   != NULL);
+    MPI_VALIDATE_RET(fin != NULL);
 
-    if( radix < 2 || radix > 16 )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+    if (radix < 2 || radix > 16) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
 
-    memset( s, 0, sizeof( s ) );
-    if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
-        return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
+    memset(s, 0, sizeof(s));
+    if (fgets(s, sizeof(s) - 1, fin) == NULL) {
+        return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
+    }
 
-    slen = strlen( s );
-    if( slen == sizeof( s ) - 2 )
-        return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
+    slen = strlen(s);
+    if (slen == sizeof(s) - 2) {
+        return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
+    }
 
-    if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
-    if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
+    if (slen > 0 && s[slen - 1] == '\n') {
+        slen--; s[slen] = '\0';
+    }
+    if (slen > 0 && s[slen - 1] == '\r') {
+        slen--; s[slen] = '\0';
+    }
 
     p = s + slen;
-    while( p-- > s )
-        if( mpi_get_digit( &d, radix, *p ) != 0 )
+    while (p-- > s) {
+        if (mpi_get_digit(&d, radix, *p) != 0) {
             break;
+        }
+    }
 
-    return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
+    return mbedtls_mpi_read_string(X, radix, p + 1);
 }
 
 /*
  * Write X into an opened file (or stdout if fout == NULL)
  */
-int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
+int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n, slen, plen;
@@ -707,144 +673,57 @@
      * Buffer should have space for (short) label and decimal formatted MPI,
      * newline characters and '\0'
      */
-    char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
-    MPI_VALIDATE_RET( X != NULL );
+    char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
+    MPI_VALIDATE_RET(X != NULL);
 
-    if( radix < 2 || radix > 16 )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+    if (radix < 2 || radix > 16) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
 
-    memset( s, 0, sizeof( s ) );
+    memset(s, 0, sizeof(s));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n));
 
-    if( p == NULL ) p = "";
+    if (p == NULL) {
+        p = "";
+    }
 
-    plen = strlen( p );
-    slen = strlen( s );
+    plen = strlen(p);
+    slen = strlen(s);
     s[slen++] = '\r';
     s[slen++] = '\n';
 
-    if( fout != NULL )
-    {
-        if( fwrite( p, 1, plen, fout ) != plen ||
-            fwrite( s, 1, slen, fout ) != slen )
-            return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
+    if (fout != NULL) {
+        if (fwrite(p, 1, plen, fout) != plen ||
+            fwrite(s, 1, slen, fout) != slen) {
+            return MBEDTLS_ERR_MPI_FILE_IO_ERROR;
+        }
+    } else {
+        mbedtls_printf("%s%s", p, s);
     }
-    else
-        mbedtls_printf( "%s%s", p, s );
 
 cleanup:
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_FS_IO */
 
-
-/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
- * into the storage form used by mbedtls_mpi. */
-
-static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
-{
-    uint8_t i;
-    unsigned char *x_ptr;
-    mbedtls_mpi_uint tmp = 0;
-
-    for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
-    {
-        tmp <<= CHAR_BIT;
-        tmp |= (mbedtls_mpi_uint) *x_ptr;
-    }
-
-    return( tmp );
-}
-
-static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
-{
-#if defined(__BYTE_ORDER__)
-
-/* Nothing to do on bigendian systems. */
-#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
-    return( x );
-#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) )
-    {
-        case 4:
-            return( __builtin_bswap32(x) );
-        case 8:
-            return( __builtin_bswap64(x) );
-    }
-#endif
-#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
-#endif /* __BYTE_ORDER__ */
-
-    /* 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_uint_bigendian_to_host_c( x ) );
-}
-
-static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
-{
-    mbedtls_mpi_uint *cur_limb_left;
-    mbedtls_mpi_uint *cur_limb_right;
-    if( limbs == 0 )
-        return;
-
-    /*
-     * Traverse limbs and
-     * - adapt byte-order in each limb
-     * - swap the limbs themselves.
-     * For that, simultaneously traverse the limbs from left to right
-     * and from right to left, as long as the left index is not bigger
-     * than the right index (it's not a problem if limbs is odd and the
-     * indices coincide in the last iteration).
-     */
-    for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
-         cur_limb_left <= cur_limb_right;
-         cur_limb_left++, cur_limb_right-- )
-    {
-        mbedtls_mpi_uint tmp;
-        /* Note that if cur_limb_left == cur_limb_right,
-         * this code effectively swaps the bytes only once. */
-        tmp             = mpi_uint_bigendian_to_host( *cur_limb_left  );
-        *cur_limb_left  = mpi_uint_bigendian_to_host( *cur_limb_right );
-        *cur_limb_right = tmp;
-    }
-}
-
 /*
  * Import X from unsigned binary data, little endian
+ *
+ * This function is guaranteed to return an MPI with exactly the necessary
+ * number of limbs (in particular, it does not skip 0s in the input).
  */
-int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
-                                const unsigned char *buf, size_t buflen )
+int mbedtls_mpi_read_binary_le(mbedtls_mpi *X,
+                               const unsigned char *buf, size_t buflen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t i;
-    size_t const limbs = CHARS_TO_LIMBS( buflen );
+    const size_t limbs = CHARS_TO_LIMBS(buflen);
 
     /* Ensure that target MPI has exactly the necessary number of limbs */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
 
-    for( i = 0; i < buflen; i++ )
-        X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
+    MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen));
 
 cleanup:
 
@@ -853,34 +732,27 @@
      * upon failure is not necessary because failure only can happen before any
      * input is copied.
      */
-    return( ret );
+    return ret;
 }
 
 /*
  * Import X from unsigned binary data, big endian
+ *
+ * This function is guaranteed to return an MPI with exactly the necessary
+ * number of limbs (in particular, it does not skip 0s in the input).
  */
-int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
+int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t const limbs    = CHARS_TO_LIMBS( buflen );
-    size_t const overhead = ( limbs * ciL ) - buflen;
-    unsigned char *Xp;
+    const size_t limbs = CHARS_TO_LIMBS(buflen);
 
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
+    MPI_VALIDATE_RET(X != NULL);
+    MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
 
     /* Ensure that target MPI has exactly the necessary number of limbs */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
 
-    /* Avoid calling `memcpy` with NULL source or destination argument,
-     * even if buflen is 0. */
-    if( buflen != 0 )
-    {
-        Xp = (unsigned char*) X->p;
-        memcpy( Xp + overhead, buf, buflen );
-
-        mpi_bigendian_to_host( X->p, limbs );
-    }
+    MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen));
 
 cleanup:
 
@@ -889,133 +761,66 @@
      * upon failure is not necessary because failure only can happen before any
      * input is copied.
      */
-    return( ret );
+    return ret;
 }
 
 /*
  * Export X into unsigned binary data, little endian
  */
-int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
-                                 unsigned char *buf, size_t buflen )
+int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
+                                unsigned char *buf, size_t buflen)
 {
-    size_t stored_bytes = X->n * ciL;
-    size_t bytes_to_copy;
-    size_t i;
-
-    if( stored_bytes < buflen )
-    {
-        bytes_to_copy = stored_bytes;
-    }
-    else
-    {
-        bytes_to_copy = buflen;
-
-        /* The output buffer is smaller than the allocated size of X.
-         * However X may fit if its leading bytes are zero. */
-        for( i = bytes_to_copy; i < stored_bytes; i++ )
-        {
-            if( GET_BYTE( X, i ) != 0 )
-                return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
-        }
-    }
-
-    for( i = 0; i < bytes_to_copy; i++ )
-        buf[i] = GET_BYTE( X, i );
-
-    if( stored_bytes < buflen )
-    {
-        /* Write trailing 0 bytes */
-        memset( buf + stored_bytes, 0, buflen - stored_bytes );
-    }
-
-    return( 0 );
+    return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen);
 }
 
 /*
  * Export X into unsigned binary data, big endian
  */
-int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
-                              unsigned char *buf, size_t buflen )
+int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
+                             unsigned char *buf, size_t buflen)
 {
-    size_t stored_bytes;
-    size_t bytes_to_copy;
-    unsigned char *p;
-    size_t i;
-
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
-
-    stored_bytes = X->n * ciL;
-
-    if( stored_bytes < buflen )
-    {
-        /* There is enough space in the output buffer. Write initial
-         * null bytes and record the position at which to start
-         * writing the significant bytes. In this case, the execution
-         * trace of this function does not depend on the value of the
-         * number. */
-        bytes_to_copy = stored_bytes;
-        p = buf + buflen - stored_bytes;
-        memset( buf, 0, buflen - stored_bytes );
-    }
-    else
-    {
-        /* The output buffer is smaller than the allocated size of X.
-         * However X may fit if its leading bytes are zero. */
-        bytes_to_copy = buflen;
-        p = buf;
-        for( i = bytes_to_copy; i < stored_bytes; i++ )
-        {
-            if( GET_BYTE( X, i ) != 0 )
-                return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
-        }
-    }
-
-    for( i = 0; i < bytes_to_copy; i++ )
-        p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
-
-    return( 0 );
+    return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen);
 }
 
 /*
  * Left-shift: X <<= count
  */
-int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
+int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i, v0, t1;
     mbedtls_mpi_uint r0 = 0, r1;
-    MPI_VALIDATE_RET( X != NULL );
+    MPI_VALIDATE_RET(X != NULL);
 
-    v0 = count / (biL    );
+    v0 = count / (biL);
     t1 = count & (biL - 1);
 
-    i = mbedtls_mpi_bitlen( X ) + count;
+    i = mbedtls_mpi_bitlen(X) + count;
 
-    if( X->n * biL < i )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
+    if (X->n * biL < i) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i)));
+    }
 
     ret = 0;
 
     /*
      * shift by count / limb_size
      */
-    if( v0 > 0 )
-    {
-        for( i = X->n; i > v0; i-- )
+    if (v0 > 0) {
+        for (i = X->n; i > v0; i--) {
             X->p[i - 1] = X->p[i - v0 - 1];
+        }
 
-        for( ; i > 0; i-- )
+        for (; i > 0; i--) {
             X->p[i - 1] = 0;
+        }
     }
 
     /*
      * shift by count % limb_size
      */
-    if( t1 > 0 )
-    {
-        for( i = v0; i < X->n; i++ )
-        {
+    if (t1 > 0) {
+        for (i = v0; i < X->n; i++) {
             r1 = X->p[i] >> (biL - t1);
             X->p[i] <<= t1;
             X->p[i] |= r0;
@@ -1025,552 +830,424 @@
 
 cleanup:
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Right-shift: X >>= count
  */
-int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
+int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
 {
-    size_t i, v0, v1;
-    mbedtls_mpi_uint r0 = 0, r1;
-    MPI_VALIDATE_RET( X != NULL );
-
-    v0 = count /  biL;
-    v1 = count & (biL - 1);
-
-    if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
-        return mbedtls_mpi_lset( X, 0 );
-
-    /*
-     * shift by count / limb_size
-     */
-    if( v0 > 0 )
-    {
-        for( i = 0; i < X->n - v0; i++ )
-            X->p[i] = X->p[i + v0];
-
-        for( ; i < X->n; i++ )
-            X->p[i] = 0;
+    MPI_VALIDATE_RET(X != NULL);
+    if (X->n != 0) {
+        mbedtls_mpi_core_shift_r(X->p, X->n, count);
     }
-
-    /*
-     * shift by count % limb_size
-     */
-    if( v1 > 0 )
-    {
-        for( i = X->n; i > 0; i-- )
-        {
-            r1 = X->p[i - 1] << (biL - v1);
-            X->p[i - 1] >>= v1;
-            X->p[i - 1] |= r0;
-            r0 = r1;
-        }
-    }
-
-    return( 0 );
+    return 0;
 }
 
 /*
  * Compare unsigned values
  */
-int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
+int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
 {
     size_t i, j;
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( Y != NULL );
+    MPI_VALIDATE_RET(X != NULL);
+    MPI_VALIDATE_RET(Y != NULL);
 
-    for( i = X->n; i > 0; i-- )
-        if( X->p[i - 1] != 0 )
+    for (i = X->n; i > 0; i--) {
+        if (X->p[i - 1] != 0) {
             break;
-
-    for( j = Y->n; j > 0; j-- )
-        if( Y->p[j - 1] != 0 )
-            break;
-
-    if( i == 0 && j == 0 )
-        return( 0 );
-
-    if( i > j ) return(  1 );
-    if( j > i ) return( -1 );
-
-    for( ; i > 0; i-- )
-    {
-        if( X->p[i - 1] > Y->p[i - 1] ) return(  1 );
-        if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
+        }
     }
 
-    return( 0 );
+    for (j = Y->n; j > 0; j--) {
+        if (Y->p[j - 1] != 0) {
+            break;
+        }
+    }
+
+    if (i == 0 && j == 0) {
+        return 0;
+    }
+
+    if (i > j) {
+        return 1;
+    }
+    if (j > i) {
+        return -1;
+    }
+
+    for (; i > 0; i--) {
+        if (X->p[i - 1] > Y->p[i - 1]) {
+            return 1;
+        }
+        if (X->p[i - 1] < Y->p[i - 1]) {
+            return -1;
+        }
+    }
+
+    return 0;
 }
 
 /*
  * Compare signed values
  */
-int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
+int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
 {
     size_t i, j;
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( Y != NULL );
+    MPI_VALIDATE_RET(X != NULL);
+    MPI_VALIDATE_RET(Y != NULL);
 
-    for( i = X->n; i > 0; i-- )
-        if( X->p[i - 1] != 0 )
+    for (i = X->n; i > 0; i--) {
+        if (X->p[i - 1] != 0) {
             break;
-
-    for( j = Y->n; j > 0; j-- )
-        if( Y->p[j - 1] != 0 )
-            break;
-
-    if( i == 0 && j == 0 )
-        return( 0 );
-
-    if( i > j ) return(  X->s );
-    if( j > i ) return( -Y->s );
-
-    if( X->s > 0 && Y->s < 0 ) return(  1 );
-    if( Y->s > 0 && X->s < 0 ) return( -1 );
-
-    for( ; i > 0; i-- )
-    {
-        if( X->p[i - 1] > Y->p[i - 1] ) return(  X->s );
-        if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
+        }
     }
 
-    return( 0 );
+    for (j = Y->n; j > 0; j--) {
+        if (Y->p[j - 1] != 0) {
+            break;
+        }
+    }
+
+    if (i == 0 && j == 0) {
+        return 0;
+    }
+
+    if (i > j) {
+        return X->s;
+    }
+    if (j > i) {
+        return -Y->s;
+    }
+
+    if (X->s > 0 && Y->s < 0) {
+        return 1;
+    }
+    if (Y->s > 0 && X->s < 0) {
+        return -1;
+    }
+
+    for (; i > 0; i--) {
+        if (X->p[i - 1] > Y->p[i - 1]) {
+            return X->s;
+        }
+        if (X->p[i - 1] < Y->p[i - 1]) {
+            return -X->s;
+        }
+    }
+
+    return 0;
 }
 
 /*
  * Compare signed values
  */
-int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
+int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
 {
     mbedtls_mpi Y;
     mbedtls_mpi_uint p[1];
-    MPI_VALIDATE_RET( X != NULL );
+    MPI_VALIDATE_RET(X != NULL);
 
-    *p  = ( z < 0 ) ? -z : z;
-    Y.s = ( z < 0 ) ? -1 : 1;
+    *p  = mpi_sint_abs(z);
+    Y.s = (z < 0) ? -1 : 1;
     Y.n = 1;
     Y.p = p;
 
-    return( mbedtls_mpi_cmp_mpi( X, &Y ) );
+    return mbedtls_mpi_cmp_mpi(X, &Y);
 }
 
 /*
  * Unsigned addition: X = |A| + |B|  (HAC 14.7)
  */
-int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
+int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t i, j;
-    mbedtls_mpi_uint *o, *p, c, tmp;
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( A != NULL );
-    MPI_VALIDATE_RET( B != NULL );
+    size_t j;
+    MPI_VALIDATE_RET(X != NULL);
+    MPI_VALIDATE_RET(A != NULL);
+    MPI_VALIDATE_RET(B != NULL);
 
-    if( X == B )
-    {
+    if (X == B) {
         const mbedtls_mpi *T = A; A = X; B = T;
     }
 
-    if( X != A )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
+    if (X != A) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
+    }
 
     /*
-     * X should always be positive as a result of unsigned additions.
+     * X must always be positive as a result of unsigned additions.
      */
     X->s = 1;
 
-    for( j = B->n; j > 0; j-- )
-        if( B->p[j - 1] != 0 )
+    for (j = B->n; j > 0; j--) {
+        if (B->p[j - 1] != 0) {
             break;
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
-
-    o = B->p; p = X->p; c = 0;
-
-    /*
-     * tmp is used because it might happen that p == o
-     */
-    for( i = 0; i < j; i++, o++, p++ )
-    {
-        tmp= *o;
-        *p +=  c; c  = ( *p <  c );
-        *p += tmp; c += ( *p < tmp );
+        }
     }
 
-    while( c != 0 )
-    {
-        if( i >= X->n )
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
-            p = X->p + i;
+    /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0
+     * and B is 0 (of any size). */
+    if (j == 0) {
+        return 0;
+    }
+
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j));
+
+    /* j is the number of non-zero limbs of B. Add those to X. */
+
+    mbedtls_mpi_uint *p = X->p;
+
+    mbedtls_mpi_uint c = mbedtls_mpi_core_add(p, p, B->p, j);
+
+    p += j;
+
+    /* Now propagate any carry */
+
+    while (c != 0) {
+        if (j >= X->n) {
+            MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1));
+            p = X->p + j;
         }
 
-        *p += c; c = ( *p < c ); i++; p++;
+        *p += c; c = (*p < c); j++; p++;
     }
 
 cleanup:
 
-    return( ret );
-}
-
-/**
- * Helper for mbedtls_mpi subtraction.
- *
- * Calculate l - r where l and r have the same size.
- * This function operates modulo (2^ciL)^n and returns the carry
- * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
- *
- * d may be aliased to l or r.
- *
- * \param n             Number of limbs of \p d, \p l and \p r.
- * \param[out] d        The result of the subtraction.
- * \param[in] l         The left operand.
- * \param[in] r         The right operand.
- *
- * \return              1 if `l < r`.
- *                      0 if `l >= r`.
- */
-static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
-                                     mbedtls_mpi_uint *d,
-                                     const mbedtls_mpi_uint *l,
-                                     const mbedtls_mpi_uint *r )
-{
-    size_t i;
-    mbedtls_mpi_uint c = 0, t, z;
-
-    for( i = 0; i < n; i++ )
-    {
-        z = ( l[i] <  c );    t = l[i] - c;
-        c = ( t < r[i] ) + z; d[i] = t - r[i];
-    }
-
-    return( c );
+    return ret;
 }
 
 /*
  * Unsigned subtraction: X = |A| - |B|  (HAC 14.9, 14.10)
  */
-int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
+int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
     mbedtls_mpi_uint carry;
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( A != NULL );
-    MPI_VALIDATE_RET( B != NULL );
+    MPI_VALIDATE_RET(X != NULL);
+    MPI_VALIDATE_RET(A != NULL);
+    MPI_VALIDATE_RET(B != NULL);
 
-    for( n = B->n; n > 0; n-- )
-        if( B->p[n - 1] != 0 )
+    for (n = B->n; n > 0; n--) {
+        if (B->p[n - 1] != 0) {
             break;
-    if( n > A->n )
-    {
+        }
+    }
+    if (n > A->n) {
         /* B >= (2^ciL)^n > A */
         ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
         goto cleanup;
     }
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n));
 
     /* Set the high limbs of X to match A. Don't touch the lower limbs
      * because X might be aliased to B, and we must not overwrite the
      * significant digits of B. */
-    if( A->n > n )
-        memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL );
-    if( X->n > A->n )
-        memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );
+    if (A->n > n && A != X) {
+        memcpy(X->p + n, A->p + n, (A->n - n) * ciL);
+    }
+    if (X->n > A->n) {
+        memset(X->p + A->n, 0, (X->n - A->n) * ciL);
+    }
 
-    carry = mpi_sub_hlp( n, X->p, A->p, B->p );
-    if( carry != 0 )
-    {
-        /* Propagate the carry to the first nonzero limb of X. */
-        for( ; n < X->n && X->p[n] == 0; n++ )
-            --X->p[n];
-        /* If we ran out of space for the carry, it means that the result
-         * is negative. */
-        if( n == X->n )
-        {
+    carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n);
+    if (carry != 0) {
+        /* Propagate the carry through the rest of X. */
+        carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n);
+
+        /* If we have further carry/borrow, the result is negative. */
+        if (carry != 0) {
             ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
             goto cleanup;
         }
-        --X->p[n];
     }
 
     /* X should always be positive as a result of unsigned subtractions. */
     X->s = 1;
 
 cleanup:
-    return( ret );
+    return ret;
+}
+
+/* Common function for signed addition and subtraction.
+ * Calculate A + B * flip_B where flip_B is 1 or -1.
+ */
+static int add_sub_mpi(mbedtls_mpi *X,
+                       const mbedtls_mpi *A, const mbedtls_mpi *B,
+                       int flip_B)
+{
+    int ret, s;
+    MPI_VALIDATE_RET(X != NULL);
+    MPI_VALIDATE_RET(A != NULL);
+    MPI_VALIDATE_RET(B != NULL);
+
+    s = A->s;
+    if (A->s * B->s * flip_B < 0) {
+        int cmp = mbedtls_mpi_cmp_abs(A, B);
+        if (cmp >= 0) {
+            MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B));
+            /* If |A| = |B|, the result is 0 and we must set the sign bit
+             * to +1 regardless of which of A or B was negative. Otherwise,
+             * since |A| > |B|, the sign is the sign of A. */
+            X->s = cmp == 0 ? 1 : s;
+        } else {
+            MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A));
+            /* Since |A| < |B|, the sign is the opposite of A. */
+            X->s = -s;
+        }
+    } else {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B));
+        X->s = s;
+    }
+
+cleanup:
+
+    return ret;
 }
 
 /*
  * Signed addition: X = A + B
  */
-int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
+int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
 {
-    int ret, s;
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( A != NULL );
-    MPI_VALIDATE_RET( B != NULL );
-
-    s = A->s;
-    if( A->s * B->s < 0 )
-    {
-        if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
-            X->s =  s;
-        }
-        else
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
-            X->s = -s;
-        }
-    }
-    else
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
-        X->s = s;
-    }
-
-cleanup:
-
-    return( ret );
+    return add_sub_mpi(X, A, B, 1);
 }
 
 /*
  * Signed subtraction: X = A - B
  */
-int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
+int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
 {
-    int ret, s;
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( A != NULL );
-    MPI_VALIDATE_RET( B != NULL );
-
-    s = A->s;
-    if( A->s * B->s > 0 )
-    {
-        if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
-            X->s =  s;
-        }
-        else
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
-            X->s = -s;
-        }
-    }
-    else
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
-        X->s = s;
-    }
-
-cleanup:
-
-    return( ret );
+    return add_sub_mpi(X, A, B, -1);
 }
 
 /*
  * Signed addition: X = A + b
  */
-int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
+int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
 {
     mbedtls_mpi B;
     mbedtls_mpi_uint p[1];
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( A != NULL );
+    MPI_VALIDATE_RET(X != NULL);
+    MPI_VALIDATE_RET(A != NULL);
 
-    p[0] = ( b < 0 ) ? -b : b;
-    B.s = ( b < 0 ) ? -1 : 1;
+    p[0] = mpi_sint_abs(b);
+    B.s = (b < 0) ? -1 : 1;
     B.n = 1;
     B.p = p;
 
-    return( mbedtls_mpi_add_mpi( X, A, &B ) );
+    return mbedtls_mpi_add_mpi(X, A, &B);
 }
 
 /*
  * Signed subtraction: X = A - b
  */
-int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
+int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b)
 {
     mbedtls_mpi B;
     mbedtls_mpi_uint p[1];
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( A != NULL );
+    MPI_VALIDATE_RET(X != NULL);
+    MPI_VALIDATE_RET(A != NULL);
 
-    p[0] = ( b < 0 ) ? -b : b;
-    B.s = ( b < 0 ) ? -1 : 1;
+    p[0] = mpi_sint_abs(b);
+    B.s = (b < 0) ? -1 : 1;
     B.n = 1;
     B.p = p;
 
-    return( mbedtls_mpi_sub_mpi( X, A, &B ) );
-}
-
-/** Helper for mbedtls_mpi multiplication.
- *
- * Add \p b * \p s to \p d.
- *
- * \param i             The number of limbs of \p s.
- * \param[in] s         A bignum to multiply, of size \p i.
- *                      It may overlap with \p d, but only if
- *                      \p d <= \p s.
- *                      Its leading limb must not be \c 0.
- * \param[in,out] d     The bignum to add to.
- *                      It must be sufficiently large to store the
- *                      result of the multiplication. This means
- *                      \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
- *                      is not known a priori.
- * \param b             A scalar to multiply.
- */
-static
-#if defined(__APPLE__) && defined(__arm__)
-/*
- * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
- * appears to need this to prevent bad ARM code generation at -O3.
- */
-__attribute__ ((noinline))
-#endif
-void mpi_mul_hlp( size_t i,
-                  const mbedtls_mpi_uint *s,
-                  mbedtls_mpi_uint *d,
-                  mbedtls_mpi_uint b )
-{
-    mbedtls_mpi_uint c = 0, t = 0;
-
-#if defined(MULADDC_HUIT)
-    for( ; i >= 8; i -= 8 )
-    {
-        MULADDC_INIT
-        MULADDC_HUIT
-        MULADDC_STOP
-    }
-
-    for( ; i > 0; i-- )
-    {
-        MULADDC_INIT
-        MULADDC_CORE
-        MULADDC_STOP
-    }
-#else /* MULADDC_HUIT */
-    for( ; i >= 16; i -= 16 )
-    {
-        MULADDC_INIT
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_CORE   MULADDC_CORE
-
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_STOP
-    }
-
-    for( ; i >= 8; i -= 8 )
-    {
-        MULADDC_INIT
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_CORE   MULADDC_CORE
-
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_CORE   MULADDC_CORE
-        MULADDC_STOP
-    }
-
-    for( ; i > 0; i-- )
-    {
-        MULADDC_INIT
-        MULADDC_CORE
-        MULADDC_STOP
-    }
-#endif /* MULADDC_HUIT */
-
-    t++;
-
-    while( c != 0 )
-    {
-        *d += c; c = ( *d < c ); d++;
-    }
+    return mbedtls_mpi_sub_mpi(X, A, &B);
 }
 
 /*
  * Baseline multiplication: X = A * B  (HAC 14.12)
  */
-int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
+int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i, j;
     mbedtls_mpi TA, TB;
     int result_is_zero = 0;
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( A != NULL );
-    MPI_VALIDATE_RET( B != NULL );
+    MPI_VALIDATE_RET(X != NULL);
+    MPI_VALIDATE_RET(A != NULL);
+    MPI_VALIDATE_RET(B != NULL);
 
-    mbedtls_mpi_init_mempool( &TA ); mbedtls_mpi_init_mempool( &TB );
+    mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TB);
 
-    if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
-    if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
+    if (X == A) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
+    }
+    if (X == B) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB;
+    }
 
-    for( i = A->n; i > 0; i-- )
-        if( A->p[i - 1] != 0 )
+    for (i = A->n; i > 0; i--) {
+        if (A->p[i - 1] != 0) {
             break;
-    if( i == 0 )
+        }
+    }
+    if (i == 0) {
         result_is_zero = 1;
+    }
 
-    for( j = B->n; j > 0; j-- )
-        if( B->p[j - 1] != 0 )
+    for (j = B->n; j > 0; j--) {
+        if (B->p[j - 1] != 0) {
             break;
-    if( j == 0 )
+        }
+    }
+    if (j == 0) {
         result_is_zero = 1;
+    }
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
 
-    for( ; j > 0; j-- )
-        mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
+    for (size_t k = 0; k < j; k++) {
+        /* We know that there cannot be any carry-out since we're
+         * iterating from bottom to top. */
+        (void) mbedtls_mpi_core_mla(X->p + k, i + 1,
+                                    A->p, i,
+                                    B->p[k]);
+    }
 
     /* If the result is 0, we don't shortcut the operation, which reduces
      * but does not eliminate side channels leaking the zero-ness. We do
      * need to take care to set the sign bit properly since the library does
      * not fully support an MPI object with a value of 0 and s == -1. */
-    if( result_is_zero )
+    if (result_is_zero) {
         X->s = 1;
-    else
+    } else {
         X->s = A->s * B->s;
+    }
 
 cleanup:
 
-    mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
+    mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Baseline multiplication: X = A * b
  */
-int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
+int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
 {
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( A != NULL );
+    MPI_VALIDATE_RET(X != NULL);
+    MPI_VALIDATE_RET(A != NULL);
 
-    /* mpi_mul_hlp can't deal with a leading 0. */
     size_t n = A->n;
-    while( n > 0 && A->p[n - 1] == 0 )
+    while (n > 0 && A->p[n - 1] == 0) {
         --n;
-
-    /* The general method below doesn't work if n==0 or b==0. By chance
-     * calculating the result is trivial in those cases. */
-    if( b == 0 || n == 0 )
-    {
-        return( mbedtls_mpi_lset( X, 0 ) );
     }
 
-    /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
+    /* The general method below doesn't work if b==0. */
+    if (b == 0 || n == 0) {
+        return mbedtls_mpi_lset(X, 0);
+    }
+
+    /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     /* In general, A * b requires 1 limb more than b. If
      * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
@@ -1579,27 +1256,32 @@
      * making the call to grow() unconditional causes slightly fewer
      * calls to calloc() in ECP code, presumably because it reuses the
      * same mpi for a while and this way the mpi is more likely to directly
-     * grow to its final size. */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
-    mpi_mul_hlp( n, A->p, X->p, b - 1 );
+     * grow to its final size.
+     *
+     * Note that calculating A*b as 0 + A*b doesn't work as-is because
+     * A,X can be the same. */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
+    mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1);
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
  * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
  * mbedtls_mpi_uint divisor, d
  */
-static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
-            mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
+static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1,
+                                            mbedtls_mpi_uint u0,
+                                            mbedtls_mpi_uint d,
+                                            mbedtls_mpi_uint *r)
 {
 #if defined(MBEDTLS_HAVE_UDBL)
     mbedtls_t_udbl dividend, quotient;
 #else
     const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
-    const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
+    const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1;
     mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
     mbedtls_mpi_uint u0_msw, u0_lsw;
     size_t s;
@@ -1608,22 +1290,25 @@
     /*
      * Check for overflow
      */
-    if( 0 == d || u1 >= d )
-    {
-        if (r != NULL) *r = ~0;
+    if (0 == d || u1 >= d) {
+        if (r != NULL) {
+            *r = ~(mbedtls_mpi_uint) 0u;
+        }
 
-        return ( ~0 );
+        return ~(mbedtls_mpi_uint) 0u;
     }
 
 #if defined(MBEDTLS_HAVE_UDBL)
     dividend  = (mbedtls_t_udbl) u1 << biL;
     dividend |= (mbedtls_t_udbl) u0;
     quotient = dividend / d;
-    if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
-        quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
+    if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) {
+        quotient = ((mbedtls_t_udbl) 1 << biL) - 1;
+    }
 
-    if( r != NULL )
-        *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
+    if (r != NULL) {
+        *r = (mbedtls_mpi_uint) (dividend - (quotient * d));
+    }
 
     return (mbedtls_mpi_uint) quotient;
 #else
@@ -1636,11 +1321,11 @@
     /*
      * Normalize the divisor, d, and dividend, u0, u1
      */
-    s = mbedtls_clz( d );
+    s = mbedtls_mpi_core_clz(d);
     d = d << s;
 
     u1 = u1 << s;
-    u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
+    u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1));
     u0 =  u0 << s;
 
     d1 = d >> biH;
@@ -1655,28 +1340,31 @@
     q1 = u1 / d1;
     r0 = u1 - d1 * q1;
 
-    while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
-    {
+    while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) {
         q1 -= 1;
         r0 += d1;
 
-        if ( r0 >= radix ) break;
+        if (r0 >= radix) {
+            break;
+        }
     }
 
-    rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
+    rAX = (u1 * radix) + (u0_msw - q1 * d);
     q0 = rAX / d1;
     r0 = rAX - q0 * d1;
 
-    while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
-    {
+    while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) {
         q0 -= 1;
         r0 += d1;
 
-        if ( r0 >= radix ) break;
+        if (r0 >= radix) {
+            break;
+        }
     }
 
-    if (r != NULL)
-        *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
+    if (r != NULL) {
+        *r = (rAX * radix + u0_lsw - q0 * d) >> s;
+    }
 
     quotient = q1 * radix + q0;
 
@@ -1687,21 +1375,22 @@
 /*
  * Division by mbedtls_mpi: A = Q * B + R  (HAC 14.20)
  */
-int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
-                         const mbedtls_mpi *B )
+int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
+                        const mbedtls_mpi *B)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i, n, t, k;
     mbedtls_mpi X, Y, Z, T1, T2;
     mbedtls_mpi_uint TP2[3];
-    MPI_VALIDATE_RET( A != NULL );
-    MPI_VALIDATE_RET( B != NULL );
+    MPI_VALIDATE_RET(A != NULL);
+    MPI_VALIDATE_RET(B != NULL);
 
-    if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
-        return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
+    if (mbedtls_mpi_cmp_int(B, 0) == 0) {
+        return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
+    }
 
-    mbedtls_mpi_init_mempool( &X ); mbedtls_mpi_init_mempool( &Y );
-    mbedtls_mpi_init_mempool( &Z ); mbedtls_mpi_init_mempool( &T1 );
+    mbedtls_mpi_init_mempool(&X); mbedtls_mpi_init_mempool(&Y);
+    mbedtls_mpi_init_mempool(&Z); mbedtls_mpi_init_mempool(&T1);
     /*
      * Avoid dynamic memory allocations for constant-size T2.
      *
@@ -1710,196 +1399,194 @@
      * buffer.
      */
     T2.s = 1;
-    T2.n = sizeof( TP2 ) / sizeof( *TP2 );
+    T2.n = sizeof(TP2) / sizeof(*TP2);
     T2.p = TP2;
 
-    if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
-    {
-        if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
-        if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
-        return( 0 );
+    if (mbedtls_mpi_cmp_abs(A, B) < 0) {
+        if (Q != NULL) {
+            MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0));
+        }
+        if (R != NULL) {
+            MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A));
+        }
+        return 0;
     }
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B));
     X.s = Y.s = 1;
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z,  0 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z,  0));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2));
 
-    k = mbedtls_mpi_bitlen( &Y ) % biL;
-    if( k < biL - 1 )
-    {
+    k = mbedtls_mpi_bitlen(&Y) % biL;
+    if (k < biL - 1) {
         k = biL - 1 - k;
-        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k));
+    } else {
+        k = 0;
     }
-    else k = 0;
 
     n = X.n - 1;
     t = Y.n - 1;
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t)));
 
-    while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
-    {
+    while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) {
         Z.p[n - t]++;
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y));
     }
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t)));
 
-    for( i = n; i > t ; i-- )
-    {
-        if( X.p[i] >= Y.p[t] )
-            Z.p[i - t - 1] = ~0;
-        else
-        {
-            Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
-                                                            Y.p[t], NULL);
+    for (i = n; i > t; i--) {
+        if (X.p[i] >= Y.p[t]) {
+            Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u;
+        } else {
+            Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1],
+                                                 Y.p[t], NULL);
         }
 
-        T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
-        T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
+        T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
+        T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
         T2.p[2] = X.p[i];
 
         Z.p[i - t - 1]++;
-        do
-        {
+        do {
             Z.p[i - t - 1]--;
 
-            MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
-            T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
+            MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0));
+            T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
             T1.p[1] = Y.p[t];
-            MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
-        }
-        while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
+            MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1]));
+        } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0);
 
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1,  biL * ( i - t - 1 ) ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1]));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1,  biL * (i - t - 1)));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1));
 
-        if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
+        if (mbedtls_mpi_cmp_int(&X, 0) < 0) {
+            MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1)));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1));
             Z.p[i - t - 1]--;
         }
     }
 
-    if( Q != NULL )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
+    if (Q != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z));
         Q->s = A->s * B->s;
     }
 
-    if( R != NULL )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
+    if (R != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k));
         X.s = A->s;
-        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X));
 
-        if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
+        if (mbedtls_mpi_cmp_int(R, 0) == 0) {
             R->s = 1;
+        }
     }
 
 cleanup:
 
-    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
-    mbedtls_mpi_free( &T1 );
-    mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
+    mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z);
+    mbedtls_mpi_free(&T1);
+    mbedtls_platform_zeroize(TP2, sizeof(TP2));
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Division by int: A = Q * b + R
  */
-int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
-                         const mbedtls_mpi *A,
-                         mbedtls_mpi_sint b )
+int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
+                        const mbedtls_mpi *A,
+                        mbedtls_mpi_sint b)
 {
     mbedtls_mpi B;
     mbedtls_mpi_uint p[1];
-    MPI_VALIDATE_RET( A != NULL );
+    MPI_VALIDATE_RET(A != NULL);
 
-    p[0] = ( b < 0 ) ? -b : b;
-    B.s = ( b < 0 ) ? -1 : 1;
+    p[0] = mpi_sint_abs(b);
+    B.s = (b < 0) ? -1 : 1;
     B.n = 1;
     B.p = p;
 
-    return( mbedtls_mpi_div_mpi( Q, R, A, &B ) );
+    return mbedtls_mpi_div_mpi(Q, R, A, &B);
 }
 
 /*
  * Modulo: R = A mod B
  */
-int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
+int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    MPI_VALIDATE_RET( R != NULL );
-    MPI_VALIDATE_RET( A != NULL );
-    MPI_VALIDATE_RET( B != NULL );
+    MPI_VALIDATE_RET(R != NULL);
+    MPI_VALIDATE_RET(A != NULL);
+    MPI_VALIDATE_RET(B != NULL);
 
-    if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
-        return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
+    if (mbedtls_mpi_cmp_int(B, 0) < 0) {
+        return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
+    }
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B));
 
-    while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
-      MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
+    while (mbedtls_mpi_cmp_int(R, 0) < 0) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B));
+    }
 
-    while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
-      MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
+    while (mbedtls_mpi_cmp_mpi(R, B) >= 0) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B));
+    }
 
 cleanup:
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Modulo: r = A mod b
  */
-int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
+int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b)
 {
     size_t i;
     mbedtls_mpi_uint x, y, z;
-    MPI_VALIDATE_RET( r != NULL );
-    MPI_VALIDATE_RET( A != NULL );
+    MPI_VALIDATE_RET(r != NULL);
+    MPI_VALIDATE_RET(A != NULL);
 
-    if( b == 0 )
-        return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
+    if (b == 0) {
+        return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
+    }
 
-    if( b < 0 )
-        return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
+    if (b < 0) {
+        return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
+    }
 
     /*
      * handle trivial cases
      */
-    if( b == 1 || A->n == 0 )
-    {
+    if (b == 1 || A->n == 0) {
         *r = 0;
-        return( 0 );
+        return 0;
     }
 
-    if( b == 2 )
-    {
+    if (b == 2) {
         *r = A->p[0] & 1;
-        return( 0 );
+        return 0;
     }
 
     /*
      * general case
      */
-    for( i = A->n, y = 0; i > 0; i-- )
-    {
+    for (i = A->n, y = 0; i > 0; i--) {
         x  = A->p[i - 1];
-        y  = ( y << biH ) | ( x >> biH );
+        y  = (y << biH) | (x >> biH);
         z  = y / b;
         y -= z * b;
 
         x <<= biH;
-        y  = ( y << biH ) | ( x >> biH );
+        y  = (y << biH) | (x >> biH);
         z  = y / b;
         y -= z * b;
     }
@@ -1908,29 +1595,18 @@
      * If A is negative, then the current y represents a negative value.
      * Flipping it to the positive side.
      */
-    if( A->s < 0 && y != 0 )
+    if (A->s < 0 && y != 0) {
         y = b - y;
+    }
 
     *r = y;
 
-    return( 0 );
+    return 0;
 }
 
-/*
- * Fast Montgomery initialization (thanks to Tom St Denis)
- */
-static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
+static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
 {
-    mbedtls_mpi_uint x, m0 = N->p[0];
-    unsigned int i;
-
-    x  = m0;
-    x += ( ( m0 + 2 ) & 4 ) << 1;
-
-    for( i = biL; i >= 8; i /= 2 )
-        x *= ( 2 - ( m0 * x ) );
-
-    *mm = ~x + 1;
+    *mm = mbedtls_mpi_core_montmul_init(N->p);
 }
 
 void mbedtls_mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
@@ -1949,66 +1625,26 @@
  * \param[in]       B   One of the numbers to multiply.
  *                      It must be nonzero and must not have more limbs than N
  *                      (B->n <= N->n).
- * \param[in]       N   The modulo. N must be odd.
+ * \param[in]       N   The modulus. \p N must be odd.
  * \param           mm  The value calculated by `mpi_montg_init(&mm, N)`.
  *                      This is -N^-1 mod 2^ciL.
  * \param[in,out]   T   A bignum for temporary storage.
- *                      It must be at least twice the limb size of N plus 2
- *                      (T->n >= 2 * (N->n + 1)).
+ *                      It must be at least twice the limb size of N plus 1
+ *                      (T->n >= 2 * N->n + 1).
  *                      Its initial content is unused and
  *                      its final content is indeterminate.
- *                      Note that unlike the usual convention in the library
- *                      for `const mbedtls_mpi*`, the content of T can change.
+ *                      It does not get reallocated.
  */
-static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
-                         const mbedtls_mpi *T )
+static void mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
+                        const mbedtls_mpi *N, mbedtls_mpi_uint mm,
+                        mbedtls_mpi *T)
 {
-    size_t i, n, m;
-    mbedtls_mpi_uint u0, u1, *d;
-
-    memset( T->p, 0, T->n * ciL );
-
-    d = T->p;
-    n = N->n;
-    m = ( B->n < n ) ? B->n : n;
-
-    for( i = 0; i < n; i++ )
-    {
-        /*
-         * T = (T + u0*B + u1*N) / 2^biL
-         */
-        u0 = A->p[i];
-        u1 = ( d[0] + u0 * B->p[0] ) * mm;
-
-        mpi_mul_hlp( m, B->p, d, u0 );
-        mpi_mul_hlp( n, N->p, d, u1 );
-
-        *d++ = u0; d[n + 1] = 0;
-    }
-
-    /* At this point, d is either the desired result or the desired result
-     * plus N. We now potentially subtract N, avoiding leaking whether the
-     * subtraction is performed through side channels. */
-
-    /* Copy the n least significant limbs of d to A, so that
-     * A = d if d < N (recall that N has n limbs). */
-    memcpy( A->p, d, n * ciL );
-    /* If d >= N then we want to set A to d - N. To prevent timing attacks,
-     * do the calculation without using conditional tests. */
-    /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
-    d[n] += 1;
-    d[n] -= mpi_sub_hlp( n, d, d, N->p );
-    /* If d0 < N then d < (2^biL)^n
-     * so d[n] == 0 and we want to keep A as it is.
-     * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
-     * so d[n] == 1 and we want to set A to the result of the subtraction
-     * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
-     * This exactly corresponds to a conditional assignment. */
-    mbedtls_ct_mpi_uint_cond_assign( n, A->p, d, (unsigned char) d[n] );
+    mbedtls_mpi_core_montmul(A->p, A->p, B->p, B->n, N->p, N->n, mm, T->p);
 }
 
-void mbedtls_mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
-                          const mbedtls_mpi *T )
+void mbedtls_mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
+                         const mbedtls_mpi *N, mbedtls_mpi_uint mm,
+                         mbedtls_mpi *T )
 {
     mpi_montmul( A, B, N, mm, T);
 }
@@ -2018,8 +1654,8 @@
  *
  * See mpi_montmul() regarding constraints and guarantees on the parameters.
  */
-static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
-                         mbedtls_mpi_uint mm, const mbedtls_mpi *T )
+static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
+                        mbedtls_mpi_uint mm, mbedtls_mpi *T)
 {
     mbedtls_mpi_uint z = 1;
     mbedtls_mpi U;
@@ -2027,13 +1663,13 @@
     U.n = U.s = (int) z;
     U.p = &z;
 
-    mpi_montmul( A, &U, N, mm, T );
+    mpi_montmul(A, &U, N, mm, T);
 }
 
-void mbedtls_mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
-                          mbedtls_mpi_uint mm, const mbedtls_mpi *T )
+void mbedtls_mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
+                         mbedtls_mpi_uint mm, mbedtls_mpi *T)
 {
-    mpi_montred( A, N, mm, T );
+    mpi_montred(A, N, mm, T);
 }
 
 /**
@@ -2051,87 +1687,136 @@
  *
  * \return \c 0 on success, or a negative error code.
  */
-static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
+static int mpi_select(mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    for( size_t i = 0; i < T_size; i++ )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
-                        (unsigned char) mbedtls_ct_size_bool_eq( i, idx ) ) );
+    for (size_t i = 0; i < T_size; i++) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
+                                                     (unsigned char) mbedtls_ct_size_bool_eq(i,
+                                                                                             idx)));
     }
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
  * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
  */
-int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
-                         const mbedtls_mpi *E, const mbedtls_mpi *N,
-                         mbedtls_mpi *prec_RR )
+int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
+                        const mbedtls_mpi *E, const mbedtls_mpi *N,
+                        mbedtls_mpi *prec_RR)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t wbits, wsize, one = 1;
+    size_t window_bitsize;
     size_t i, j, nblimbs;
     size_t bufsize, nbits;
+    size_t exponent_bits_in_window = 0;
     mbedtls_mpi_uint ei, mm, state;
     mbedtls_mpi RR, T, WW, Apos;
-    mbedtls_mpi *W = NULL;
+    mbedtls_mpi *W;
     const size_t array_size_W = 2 << MBEDTLS_MPI_WINDOW_SIZE;
     int neg;
 
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( A != NULL );
-    MPI_VALIDATE_RET( E != NULL );
-    MPI_VALIDATE_RET( N != NULL );
+    MPI_VALIDATE_RET(X != NULL);
+    MPI_VALIDATE_RET(A != NULL);
+    MPI_VALIDATE_RET(E != NULL);
+    MPI_VALIDATE_RET(N != NULL);
 
-    if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+    if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
 
-    if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+    if (mbedtls_mpi_cmp_int(E, 0) < 0) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
 
-    if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
-        mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
-        return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+    if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS ||
+        mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
 
     /*
      * Init temps and window size
      */
-    mpi_montg_init( &mm, N );
-    mbedtls_mpi_init_mempool( &RR ); mbedtls_mpi_init( &T );
-    mbedtls_mpi_init_mempool( &Apos );
-    mbedtls_mpi_init_mempool( &WW );
+    mpi_montg_init(&mm, N);
+    mbedtls_mpi_init_mempool(&RR); mbedtls_mpi_init(&T);
+    mbedtls_mpi_init_mempool(&Apos);
+    mbedtls_mpi_init_mempool(&WW);
 
-    i = mbedtls_mpi_bitlen( E );
+    i = mbedtls_mpi_bitlen(E);
 
-    wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
-            ( i >  79 ) ? 4 : ( i >  23 ) ? 3 : 1;
+    window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
+                     (i >  79) ? 4 : (i >  23) ? 3 : 1;
 
-#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
-    if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
-        wsize = MBEDTLS_MPI_WINDOW_SIZE;
+#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
+    if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
+        window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
+    }
 #endif
 
+    const size_t w_table_used_size = (size_t) 1 << window_bitsize;
+
+    W = mempool_alloc(mbedtls_mpi_mempool,
+                      sizeof( mbedtls_mpi ) * array_size_W);
+    if (W == NULL) {
+        ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
+        goto cleanup;
+    }
+    for (i = 0; i < array_size_W; i++)
+        mbedtls_mpi_init_mempool(W + i);
+    /*
+     * This function is not constant-trace: its memory accesses depend on the
+     * exponent value. To defend against timing attacks, callers (such as RSA
+     * and DHM) should use exponent blinding. However this is not enough if the
+     * adversary can find the exponent in a single trace, so this function
+     * takes extra precautions against adversaries who can observe memory
+     * access patterns.
+     *
+     * This function performs a series of multiplications by table elements and
+     * squarings, and we want the prevent the adversary from finding out which
+     * table element was used, and from distinguishing between multiplications
+     * and squarings. Firstly, when multiplying by an element of the window
+     * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
+     * squarings as having a different memory access patterns from other
+     * multiplications. So secondly, we put the accumulator X in the table as
+     * well, and also do a constant-trace table lookup to multiply by X.
+     *
+     * This way, all multiplications take the form of a lookup-and-multiply.
+     * The number of lookup-and-multiply operations inside each iteration of
+     * the main loop still depends on the bits of the exponent, but since the
+     * other operations in the loop don't have an easily recognizable memory
+     * trace, an adversary is unlikely to be able to observe the exact
+     * patterns.
+     *
+     * An adversary may still be able to recover the exponent if they can
+     * observe both memory accesses and branches. However, branch prediction
+     * exploitation typically requires many traces of execution over the same
+     * data, which is defeated by randomized blinding.
+     *
+     * To achieve this, we make a copy of X and we use the table entry in each
+     * calculation from this point on.
+     */
+    const size_t x_index = 0;
+    mbedtls_mpi_copy(&W[x_index], X);
+
     j = N->n + 1;
     /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
      * and mpi_montred() calls later. Here we ensure that W[1] and X are
      * large enough, and later we'll grow other W[i] to the same length.
      * They must not be shrunk midway through this function!
      */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
 
     /*
      * Compensate for negative A (and correct at the end)
      */
-    neg = ( A->s == -1 );
-    if( neg )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
+    neg = (A->s == -1);
+    if (neg) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
         Apos.s = 1;
         A = &Apos;
     }
@@ -2139,93 +1824,89 @@
     /*
      * If 1st call, pre-compute R^2 mod N
      */
-    if( prec_RR == NULL || prec_RR->p == NULL )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
+    if (prec_RR == NULL || prec_RR->p == NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N));
 
-        if( prec_RR != NULL )
-            memcpy( prec_RR, &RR, sizeof( mbedtls_mpi ) );
+        if (prec_RR != NULL) {
+            memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
+        }
+    } else {
+        memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
     }
-    else
-        memcpy( &RR, prec_RR, sizeof( mbedtls_mpi ) );
 
-    W = mempool_alloc( mbedtls_mpi_mempool,
-                       sizeof( mbedtls_mpi ) * array_size_W );
-    if( W == NULL ) {
-        ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
-        goto cleanup;
-    }
-    for( i = 0; i < array_size_W; i++ )
-        mbedtls_mpi_init_mempool( W + i );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1],  j ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1],  j));
 
     /*
      * W[1] = A * R^2 * R^-1 mod N = A * R mod N
      */
-    if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
+    if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
         /* This should be a no-op because W[1] is already that large before
          * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
          * in mpi_montmul() below, so let's make sure. */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n + 1 ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
+    } else {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
     }
-    else
-        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
 
     /* Note that this is safe because W[1] always has at least N->n limbs
      * (it grew above and was preserved by mbedtls_mpi_copy()). */
-    mpi_montmul( &W[1], &RR, N, mm, &T );
+    mpi_montmul(&W[1], &RR, N, mm, &T);
 
     /*
-     * X = R^2 * R^-1 mod N = R mod N
+     * W[x_index] = R^2 * R^-1 mod N = R mod N
      */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
-    mpi_montred( X, N, mm, &T );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
+    mpi_montred(&W[x_index], N, mm, &T);
 
-    if( wsize > 1 )
-    {
+
+    if (window_bitsize > 1) {
         /*
-         * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
+         * W[i] = W[1] ^ i
+         *
+         * The first bit of the sliding window is always 1 and therefore we
+         * only need to store the second half of the table.
+         *
+         * (There are two special elements in the table: W[0] for the
+         * accumulator/result and W[1] for A in Montgomery form. Both of these
+         * are already set at this point.)
          */
-        j =  one << ( wsize - 1 );
+        j = w_table_used_size / 2;
 
-        MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1]    ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
 
-        for( i = 0; i < wsize - 1; i++ )
-            mpi_montmul( &W[j], &W[j], N, mm, &T );
+        for (i = 0; i < window_bitsize - 1; i++) {
+            mpi_montmul(&W[j], &W[j], N, mm, &T);
+        }
 
         /*
          * W[i] = W[i - 1] * W[1]
          */
-        for( i = j + 1; i < ( one << wsize ); i++ )
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
+        for (i = j + 1; i < w_table_used_size; i++) {
+            MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
 
-            mpi_montmul( &W[i], &W[1], N, mm, &T );
+            mpi_montmul(&W[i], &W[1], N, mm, &T);
         }
     }
 
     nblimbs = E->n;
     bufsize = 0;
     nbits   = 0;
-    wbits   = 0;
     state   = 0;
 
-    while( 1 )
-    {
-        if( bufsize == 0 )
-        {
-            if( nblimbs == 0 )
+    while (1) {
+        if (bufsize == 0) {
+            if (nblimbs == 0) {
                 break;
+            }
 
             nblimbs--;
 
-            bufsize = sizeof( mbedtls_mpi_uint ) << 3;
+            bufsize = sizeof(mbedtls_mpi_uint) << 3;
         }
 
         bufsize--;
@@ -2235,15 +1916,16 @@
         /*
          * skip leading 0s
          */
-        if( ei == 0 && state == 0 )
+        if (ei == 0 && state == 0) {
             continue;
+        }
 
-        if( ei == 0 && state == 1 )
-        {
+        if (ei == 0 && state == 1) {
             /*
-             * out of window, square X
+             * out of window, square W[x_index]
              */
-            mpi_montmul( X, X, N, mm, &T );
+            MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
+            mpi_montmul(&W[x_index], &WW, N, mm, &T);
             continue;
         }
 
@@ -2253,101 +1935,112 @@
         state = 2;
 
         nbits++;
-        wbits |= ( ei << ( wsize - nbits ) );
+        exponent_bits_in_window |= (ei << (window_bitsize - nbits));
 
-        if( nbits == wsize )
-        {
+        if (nbits == window_bitsize) {
             /*
-             * X = X^wsize R^-1 mod N
+             * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
              */
-            for( i = 0; i < wsize; i++ )
-                mpi_montmul( X, X, N, mm, &T );
+            for (i = 0; i < window_bitsize; i++) {
+                MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
+                                           x_index));
+                mpi_montmul(&W[x_index], &WW, N, mm, &T);
+            }
 
             /*
-             * X = X * W[wbits] R^-1 mod N
+             * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
              */
-            MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
-            mpi_montmul( X, &WW, N, mm, &T );
+            MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
+                                       exponent_bits_in_window));
+            mpi_montmul(&W[x_index], &WW, N, mm, &T);
 
             state--;
             nbits = 0;
-            wbits = 0;
+            exponent_bits_in_window = 0;
         }
     }
 
     /*
      * process the remaining bits
      */
-    for( i = 0; i < nbits; i++ )
-    {
-        mpi_montmul( X, X, N, mm, &T );
+    for (i = 0; i < nbits; i++) {
+        MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
+        mpi_montmul(&W[x_index], &WW, N, mm, &T);
 
-        wbits <<= 1;
+        exponent_bits_in_window <<= 1;
 
-        if( ( wbits & ( one << wsize ) ) != 0 )
-            mpi_montmul( X, &W[1], N, mm, &T );
+        if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
+            MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
+            mpi_montmul(&W[x_index], &WW, N, mm, &T);
+        }
     }
 
     /*
-     * X = A^E * R * R^-1 mod N = A^E mod N
+     * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
      */
-    mpi_montred( X, N, mm, &T );
+    mpi_montred(&W[x_index], N, mm, &T);
 
-    if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
-    {
-        X->s = -1;
-        MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
+    if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
+        W[x_index].s = -1;
+        MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
     }
 
+    /*
+     * Load the result in the output variable.
+     */
+    mbedtls_mpi_copy(X, &W[x_index]);
+
 cleanup:
 
-    if( W )
-        for( i = 0; i < array_size_W; i++ )
-            mbedtls_mpi_free( W + i );
-    mempool_free( mbedtls_mpi_mempool , W );
+    if (W)
+        for (i = 0; i < array_size_W; i++)
+            mbedtls_mpi_free(W + i);
+    mempool_free(mbedtls_mpi_mempool , W);
 
-    mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
-    mbedtls_mpi_free( &WW );
+    mbedtls_mpi_free(&T);
+    mbedtls_mpi_free(&Apos);
+    mbedtls_mpi_free(&WW);
 
-    if( prec_RR == NULL || prec_RR->p == NULL )
-        mbedtls_mpi_free( &RR );
+    if (prec_RR == NULL || prec_RR->p == NULL) {
+        mbedtls_mpi_free(&RR);
+    }
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Greatest common divisor: G = gcd(A, B)  (HAC 14.54)
  */
-int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
+int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t lz, lzt;
     mbedtls_mpi TA, TB;
 
-    MPI_VALIDATE_RET( G != NULL );
-    MPI_VALIDATE_RET( A != NULL );
-    MPI_VALIDATE_RET( B != NULL );
+    MPI_VALIDATE_RET(G != NULL);
+    MPI_VALIDATE_RET(A != NULL);
+    MPI_VALIDATE_RET(B != NULL);
 
-    mbedtls_mpi_init_mempool( &TA ); mbedtls_mpi_init_mempool( &TB );
+    mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TB);
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B));
 
-    lz = mbedtls_mpi_lsb( &TA );
-    lzt = mbedtls_mpi_lsb( &TB );
+    lz = mbedtls_mpi_lsb(&TA);
+    lzt = mbedtls_mpi_lsb(&TB);
 
     /* The loop below gives the correct result when A==0 but not when B==0.
      * So have a special case for B==0. Leverage the fact that we just
      * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
      * slightly more efficient than cmp_int(). */
-    if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 )
-    {
-        ret = mbedtls_mpi_copy( G, A );
+    if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) {
+        ret = mbedtls_mpi_copy(G, A);
         goto cleanup;
     }
 
-    if( lzt < lz )
+    if (lzt < lz) {
         lz = lzt;
+    }
 
     TA.s = TB.s = 1;
 
@@ -2384,11 +2077,10 @@
      * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
      * since in that case TB is calculated from TB-TA with the condition TB>TA).
      */
-    while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
-    {
+    while (mbedtls_mpi_cmp_int(&TA, 0) != 0) {
         /* Divisions by 2 preserve the invariant (I). */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA)));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB)));
 
         /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
          * TA-TB is even so the division by 2 has an integer result.
@@ -2397,15 +2089,12 @@
          * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
          * divides TA.
          */
-        if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
-        }
-        else
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
+        if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) {
+            MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1));
+        } else {
+            MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1));
         }
         /* Note that one of TA or TB is still odd. */
     }
@@ -2419,271 +2108,186 @@
      *   In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
      */
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB));
 
 cleanup:
 
-    mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
+    mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB);
 
-    return( ret );
-}
-
-/* Fill X with n_bytes random bytes.
- * X must already have room for those bytes.
- * The ordering of the bytes returned from the RNG is suitable for
- * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
- * The size and sign of X are unchanged.
- * n_bytes must not be 0.
- */
-static int mpi_fill_random_internal(
-    mbedtls_mpi *X, size_t n_bytes,
-    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    const size_t limbs = CHARS_TO_LIMBS( n_bytes );
-    const size_t overhead = ( limbs * ciL ) - n_bytes;
-
-    if( X->n < limbs )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-
-    memset( X->p, 0, overhead );
-    memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
-    MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
-    mpi_bigendian_to_host( X->p, limbs );
-
-cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
  * Fill X with size bytes of random.
- *
- * Use a temporary bytes representation to make sure the result is the same
- * regardless of the platform endianness (useful when f_rng is actually
- * deterministic, eg for tests).
+ * The bytes returned from the RNG are used in a specific order which
+ * is suitable for deterministic ECDSA (see the specification of
+ * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
  */
-int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
-                     int (*f_rng)(void *, unsigned char *, size_t),
-                     void *p_rng )
+int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t const limbs = CHARS_TO_LIMBS( size );
+    const size_t limbs = CHARS_TO_LIMBS(size);
 
-    MPI_VALIDATE_RET( X     != NULL );
-    MPI_VALIDATE_RET( f_rng != NULL );
+    MPI_VALIDATE_RET(X     != NULL);
+    MPI_VALIDATE_RET(f_rng != NULL);
 
     /* Ensure that target MPI has exactly the necessary number of limbs */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
-    if( size == 0 )
-        return( 0 );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
+    if (size == 0) {
+        return 0;
+    }
 
-    ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
+    ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng);
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
-int mbedtls_mpi_random( mbedtls_mpi *X,
-                        mbedtls_mpi_sint min,
-                        const mbedtls_mpi *N,
-                        int (*f_rng)(void *, unsigned char *, size_t),
-                        void *p_rng )
+int mbedtls_mpi_random(mbedtls_mpi *X,
+                       mbedtls_mpi_sint min,
+                       const mbedtls_mpi *N,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng)
 {
-    int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
-    int count;
-    unsigned lt_lower = 1, lt_upper = 0;
-    size_t n_bits = mbedtls_mpi_bitlen( N );
-    size_t n_bytes = ( n_bits + 7 ) / 8;
-    mbedtls_mpi lower_bound;
-
-    if( min < 0 )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-    if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-
-    /*
-     * When min == 0, each try has at worst a probability 1/2 of failing
-     * (the msb has a probability 1/2 of being 0, and then the result will
-     * be < N), so after 30 tries failure probability is a most 2**(-30).
-     *
-     * When N is just below a power of 2, as is the case when generating
-     * a random scalar on most elliptic curves, 1 try is enough with
-     * overwhelming probability. When N is just above a power of 2,
-     * as when generating a random scalar on secp224k1, each try has
-     * a probability of failing that is almost 1/2.
-     *
-     * The probabilities are almost the same if min is nonzero but negligible
-     * compared to N. This is always the case when N is crypto-sized, but
-     * it's convenient to support small N for testing purposes. When N
-     * is small, use a higher repeat count, otherwise the probability of
-     * failure is macroscopic.
-     */
-    count = ( n_bytes > 4 ? 30 : 250 );
-
-    mbedtls_mpi_init( &lower_bound );
+    if (min < 0) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+    if (mbedtls_mpi_cmp_int(N, min) <= 0) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
 
     /* Ensure that target MPI has exactly the same number of limbs
      * as the upper bound, even if the upper bound has leading zeros.
-     * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
-
-    /*
-     * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
-     * when f_rng is a suitably parametrized instance of HMAC_DRBG:
-     * - use the same byte ordering;
-     * - keep the leftmost n_bits bits of the generated octet string;
-     * - try until result is in the desired range.
-     * This also avoids any bias, which is especially important for ECDSA.
-     */
-    do
-    {
-        MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
-
-        if( --count == 0 )
-        {
-            ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
-            goto cleanup;
-        }
-
-        MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, &lt_lower ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &lt_upper ) );
+     * This is necessary for mbedtls_mpi_core_random. */
+    int ret = mbedtls_mpi_resize_clear(X, N->n);
+    if (ret != 0) {
+        return ret;
     }
-    while( lt_lower != 0 || lt_upper == 0 );
 
-cleanup:
-    mbedtls_mpi_free( &lower_bound );
-    return( ret );
+    return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng);
 }
 
 /*
  * Modular inverse: X = A^-1 mod N  (HAC 14.61 / 14.64)
  */
-int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
+int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( A != NULL );
-    MPI_VALIDATE_RET( N != NULL );
+    MPI_VALIDATE_RET(X != NULL);
+    MPI_VALIDATE_RET(A != NULL);
+    MPI_VALIDATE_RET(N != NULL);
 
-    if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+    if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
 
-    mbedtls_mpi_init_mempool( &TA ); mbedtls_mpi_init_mempool( &TU );
-    mbedtls_mpi_init_mempool( &U1 ); mbedtls_mpi_init_mempool( &U2 );
-    mbedtls_mpi_init_mempool( &G ); mbedtls_mpi_init_mempool( &TB );
-    mbedtls_mpi_init_mempool( &TV ); mbedtls_mpi_init_mempool( &V1 );
-    mbedtls_mpi_init_mempool( &V2 );
+    mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TU);
+    mbedtls_mpi_init_mempool(&U1); mbedtls_mpi_init_mempool(&U2);
+    mbedtls_mpi_init_mempool(&G); mbedtls_mpi_init_mempool(&TB);
+    mbedtls_mpi_init_mempool(&TV); mbedtls_mpi_init_mempool(&V1);
+    mbedtls_mpi_init_mempool(&V2);
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N));
 
-    if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
-    {
+    if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
         ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
         goto cleanup;
     }
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1));
 
-    do
-    {
-        while( ( TU.p[0] & 1 ) == 0 )
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
+    do {
+        while ((TU.p[0] & 1) == 0) {
+            MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1));
 
-            if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
-            {
-                MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
-                MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
+            if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) {
+                MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB));
+                MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA));
             }
 
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
+            MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1));
         }
 
-        while( ( TV.p[0] & 1 ) == 0 )
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
+        while ((TV.p[0] & 1) == 0) {
+            MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1));
 
-            if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
-            {
-                MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
-                MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
+            if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) {
+                MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB));
+                MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA));
             }
 
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
+            MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1));
         }
 
-        if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
+        if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) {
+            MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2));
+        } else {
+            MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2));
         }
-        else
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
-        }
+    } while (mbedtls_mpi_cmp_int(&TU, 0) != 0);
+
+    while (mbedtls_mpi_cmp_int(&V1, 0) < 0) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N));
     }
-    while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
 
-    while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
+    while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N));
+    }
 
-    while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1));
 
 cleanup:
 
-    mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
-    mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
-    mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
+    mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2);
+    mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV);
+    mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2);
 
-    return( ret );
+    return ret;
 }
 
 #if defined(MBEDTLS_GENPRIME)
 
 static const int small_prime[] =
 {
-        3,    5,    7,   11,   13,   17,   19,   23,
-       29,   31,   37,   41,   43,   47,   53,   59,
-       61,   67,   71,   73,   79,   83,   89,   97,
-      101,  103,  107,  109,  113,  127,  131,  137,
-      139,  149,  151,  157,  163,  167,  173,  179,
-      181,  191,  193,  197,  199,  211,  223,  227,
-      229,  233,  239,  241,  251,  257,  263,  269,
-      271,  277,  281,  283,  293,  307,  311,  313,
-      317,  331,  337,  347,  349,  353,  359,  367,
-      373,  379,  383,  389,  397,  401,  409,  419,
-      421,  431,  433,  439,  443,  449,  457,  461,
-      463,  467,  479,  487,  491,  499,  503,  509,
-      521,  523,  541,  547,  557,  563,  569,  571,
-      577,  587,  593,  599,  601,  607,  613,  617,
-      619,  631,  641,  643,  647,  653,  659,  661,
-      673,  677,  683,  691,  701,  709,  719,  727,
-      733,  739,  743,  751,  757,  761,  769,  773,
-      787,  797,  809,  811,  821,  823,  827,  829,
-      839,  853,  857,  859,  863,  877,  881,  883,
-      887,  907,  911,  919,  929,  937,  941,  947,
-      953,  967,  971,  977,  983,  991,  997, -103
+    3,    5,    7,   11,   13,   17,   19,   23,
+    29,   31,   37,   41,   43,   47,   53,   59,
+    61,   67,   71,   73,   79,   83,   89,   97,
+    101,  103,  107,  109,  113,  127,  131,  137,
+    139,  149,  151,  157,  163,  167,  173,  179,
+    181,  191,  193,  197,  199,  211,  223,  227,
+    229,  233,  239,  241,  251,  257,  263,  269,
+    271,  277,  281,  283,  293,  307,  311,  313,
+    317,  331,  337,  347,  349,  353,  359,  367,
+    373,  379,  383,  389,  397,  401,  409,  419,
+    421,  431,  433,  439,  443,  449,  457,  461,
+    463,  467,  479,  487,  491,  499,  503,  509,
+    521,  523,  541,  547,  557,  563,  569,  571,
+    577,  587,  593,  599,  601,  607,  613,  617,
+    619,  631,  641,  643,  647,  653,  659,  661,
+    673,  677,  683,  691,  701,  709,  719,  727,
+    733,  739,  743,  751,  757,  761,  769,  773,
+    787,  797,  809,  811,  821,  823,  827,  829,
+    839,  853,  857,  859,  863,  877,  881,  883,
+    887,  907,  911,  919,  929,  937,  941,  947,
+    953,  967,  971,  977,  983,  991,  997, -103
 };
 
 /*
@@ -2695,70 +2299,71 @@
  * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
  * other negative: error
  */
-static int mpi_check_small_factors( const mbedtls_mpi *X )
+static int mpi_check_small_factors(const mbedtls_mpi *X)
 {
     int ret = 0;
     size_t i;
     mbedtls_mpi_uint r;
 
-    if( ( X->p[0] & 1 ) == 0 )
-        return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
+    if ((X->p[0] & 1) == 0) {
+        return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
+    }
 
-    for( i = 0; small_prime[i] > 0; i++ )
-    {
-        if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
-            return( 1 );
+    for (i = 0; small_prime[i] > 0; i++) {
+        if (mbedtls_mpi_cmp_int(X, small_prime[i]) <= 0) {
+            return 1;
+        }
 
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, small_prime[i]));
 
-        if( r == 0 )
-            return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
+        if (r == 0) {
+            return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
+        }
     }
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
  * Miller-Rabin pseudo-primality test  (HAC 4.24)
  */
-static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
-                             int (*f_rng)(void *, unsigned char *, size_t),
-                             void *p_rng )
+static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng)
 {
     int ret, count;
     size_t i, j, k, s;
     mbedtls_mpi W, R, T, A, RR;
 
-    MPI_VALIDATE_RET( X     != NULL );
-    MPI_VALIDATE_RET( f_rng != NULL );
+    MPI_VALIDATE_RET(X     != NULL);
+    MPI_VALIDATE_RET(f_rng != NULL);
 
-    mbedtls_mpi_init_mempool( &W ); mbedtls_mpi_init_mempool( &R );
-    mbedtls_mpi_init_mempool( &T ); mbedtls_mpi_init_mempool( &A );
-    mbedtls_mpi_init_mempool( &RR );
+    mbedtls_mpi_init_mempool(&W); mbedtls_mpi_init_mempool(&R);
+    mbedtls_mpi_init_mempool(&T); mbedtls_mpi_init_mempool(&A);
+    mbedtls_mpi_init_mempool(&RR);
 
     /*
      * W = |X| - 1
      * R = W >> lsb( W )
      */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
-    s = mbedtls_mpi_lsb( &W );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1));
+    s = mbedtls_mpi_lsb(&W);
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s));
 
-    for( i = 0; i < rounds; i++ )
-    {
+    for (i = 0; i < rounds; i++) {
         /*
          * pick a random A, 1 < A < |X| - 1
          */
         count = 0;
         do {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
+            MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng));
 
-            j = mbedtls_mpi_bitlen( &A );
-            k = mbedtls_mpi_bitlen( &W );
+            j = mbedtls_mpi_bitlen(&A);
+            k = mbedtls_mpi_bitlen(&W);
             if (j > k) {
-                A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
+                A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1;
             }
 
             if (count++ > 300) {
@@ -2766,29 +2371,30 @@
                 goto cleanup;
             }
 
-        } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
-                  mbedtls_mpi_cmp_int( &A, 1 )  <= 0    );
+        } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 ||
+                 mbedtls_mpi_cmp_int(&A, 1)  <= 0);
 
         /*
          * A = A^R mod |X|
          */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR));
 
-        if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
-            mbedtls_mpi_cmp_int( &A,  1 ) == 0 )
+        if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 ||
+            mbedtls_mpi_cmp_int(&A,  1) == 0) {
             continue;
+        }
 
         j = 1;
-        while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
-        {
+        while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) {
             /*
              * A = A * A mod |X|
              */
-            MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X  ) );
+            MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X));
 
-            if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
+            if (mbedtls_mpi_cmp_int(&A, 1) == 0) {
                 break;
+            }
 
             j++;
         }
@@ -2796,75 +2402,56 @@
         /*
          * not prime if A != |X| - 1 or A == 1
          */
-        if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
-            mbedtls_mpi_cmp_int( &A,  1 ) == 0 )
-        {
+        if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 ||
+            mbedtls_mpi_cmp_int(&A,  1) == 0) {
             ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
             break;
         }
     }
 
 cleanup:
-    mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
-    mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
-    mbedtls_mpi_free( &RR );
+    mbedtls_mpi_free(&W); mbedtls_mpi_free(&R);
+    mbedtls_mpi_free(&T); mbedtls_mpi_free(&A);
+    mbedtls_mpi_free(&RR);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Pseudo-primality test: small factors, then Miller-Rabin
  */
-int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
-                              int (*f_rng)(void *, unsigned char *, size_t),
-                              void *p_rng )
+int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
+                             int (*f_rng)(void *, unsigned char *, size_t),
+                             void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_mpi XX;
-    MPI_VALIDATE_RET( X     != NULL );
-    MPI_VALIDATE_RET( f_rng != NULL );
+    MPI_VALIDATE_RET(X     != NULL);
+    MPI_VALIDATE_RET(f_rng != NULL);
 
     XX.s = 1;
     XX.n = X->n;
     XX.p = X->p;
 
-    if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
-        mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
-        return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
-
-    if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
-        return( 0 );
-
-    if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
-    {
-        if( ret == 1 )
-            return( 0 );
-
-        return( ret );
+    if (mbedtls_mpi_cmp_int(&XX, 0) == 0 ||
+        mbedtls_mpi_cmp_int(&XX, 1) == 0) {
+        return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
     }
 
-    return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
-}
+    if (mbedtls_mpi_cmp_int(&XX, 2) == 0) {
+        return 0;
+    }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-/*
- * Pseudo-primality test, error probability 2^-80
- */
-int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
-                  int (*f_rng)(void *, unsigned char *, size_t),
-                  void *p_rng )
-{
-    MPI_VALIDATE_RET( X     != NULL );
-    MPI_VALIDATE_RET( f_rng != NULL );
+    if ((ret = mpi_check_small_factors(&XX)) != 0) {
+        if (ret == 1) {
+            return 0;
+        }
 
-    /*
-     * In the past our key generation aimed for an error rate of at most
-     * 2^-80. Since this function is deprecated, aim for the same certainty
-     * here as well.
-     */
-    return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
+        return ret;
+    }
+
+    return mpi_miller_rabin(&XX, rounds, f_rng, p_rng);
 }
-#endif
 
 /*
  * Prime number generation
@@ -2873,9 +2460,9 @@
  * be either 1024 bits or 1536 bits long, and flags must contain
  * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
  */
-int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
-                   int (*f_rng)(void *, unsigned char *, size_t),
-                   void *p_rng )
+int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
+                          int (*f_rng)(void *, unsigned char *, size_t),
+                          void *p_rng)
 {
 #ifdef MBEDTLS_HAVE_INT64
 // ceil(2^63.5)
@@ -2890,107 +2477,108 @@
     mbedtls_mpi_uint r;
     mbedtls_mpi Y;
 
-    MPI_VALIDATE_RET( X     != NULL );
-    MPI_VALIDATE_RET( f_rng != NULL );
+    MPI_VALIDATE_RET(X     != NULL);
+    MPI_VALIDATE_RET(f_rng != NULL);
 
-    if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+    if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
 
-    mbedtls_mpi_init_mempool( &Y );
+    mbedtls_mpi_init_mempool(&Y);
 
-    n = BITS_TO_LIMBS( nbits );
+    n = BITS_TO_LIMBS(nbits);
 
-    if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
-    {
+    if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) {
         /*
          * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
          */
-        rounds = ( ( nbits >= 1300 ) ?  2 : ( nbits >=  850 ) ?  3 :
-                   ( nbits >=  650 ) ?  4 : ( nbits >=  350 ) ?  8 :
-                   ( nbits >=  250 ) ? 12 : ( nbits >=  150 ) ? 18 : 27 );
-    }
-    else
-    {
+        rounds = ((nbits >= 1300) ?  2 : (nbits >=  850) ?  3 :
+                  (nbits >=  650) ?  4 : (nbits >=  350) ?  8 :
+                  (nbits >=  250) ? 12 : (nbits >=  150) ? 18 : 27);
+    } else {
         /*
          * 2^-100 error probability, number of rounds computed based on HAC,
          * fact 4.48
          */
-        rounds = ( ( nbits >= 1450 ) ?  4 : ( nbits >=  1150 ) ?  5 :
-                   ( nbits >= 1000 ) ?  6 : ( nbits >=   850 ) ?  7 :
-                   ( nbits >=  750 ) ?  8 : ( nbits >=   500 ) ? 13 :
-                   ( nbits >=  250 ) ? 28 : ( nbits >=   150 ) ? 40 : 51 );
+        rounds = ((nbits >= 1450) ?  4 : (nbits >=  1150) ?  5 :
+                  (nbits >= 1000) ?  6 : (nbits >=   850) ?  7 :
+                  (nbits >=  750) ?  8 : (nbits >=   500) ? 13 :
+                  (nbits >=  250) ? 28 : (nbits >=   150) ? 40 : 51);
     }
 
-    while( 1 )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
+    while (1) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng));
         /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
-        if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
+        if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) {
+            continue;
+        }
 
         k = n * biL;
-        if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
+        if (k > nbits) {
+            MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits));
+        }
         X->p[0] |= 1;
 
-        if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
-        {
-            ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
+        if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) {
+            ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng);
 
-            if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
+            if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
                 goto cleanup;
-        }
-        else
-        {
+            }
+        } else {
             /*
-             * An necessary condition for Y and X = 2Y + 1 to be prime
+             * A necessary condition for Y and X = 2Y + 1 to be prime
              * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
              * Make sure it is satisfied, while keeping X = 3 mod 4
              */
 
             X->p[0] |= 2;
 
-            MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
-            if( r == 0 )
-                MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
-            else if( r == 1 )
-                MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
+            MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3));
+            if (r == 0) {
+                MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8));
+            } else if (r == 1) {
+                MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4));
+            }
 
             /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
-            MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
+            MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1));
 
-            while( 1 )
-            {
+            while (1) {
                 /*
                  * First, check small factors for X and Y
                  * before doing Miller-Rabin on any of them
                  */
-                if( ( ret = mpi_check_small_factors(  X         ) ) == 0 &&
-                    ( ret = mpi_check_small_factors( &Y         ) ) == 0 &&
-                    ( ret = mpi_miller_rabin(  X, rounds, f_rng, p_rng  ) )
-                                                                    == 0 &&
-                    ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng  ) )
-                                                                    == 0 )
+                if ((ret = mpi_check_small_factors(X)) == 0 &&
+                    (ret = mpi_check_small_factors(&Y)) == 0 &&
+                    (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng))
+                    == 0 &&
+                    (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng))
+                    == 0) {
                     goto cleanup;
+                }
 
-                if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
+                if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
                     goto cleanup;
+                }
 
                 /*
                  * Next candidates. We want to preserve Y = (X-1) / 2 and
                  * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
                  * so up Y by 6 and X by 12.
                  */
-                MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(  X,  X, 12 ) );
-                MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6  ) );
+                MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X,  X, 12));
+                MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6));
             }
         }
     }
 
 cleanup:
 
-    mbedtls_mpi_free( &Y );
+    mbedtls_mpi_free(&Y);
 
-    return( ret );
+    return ret;
 }
 
 #endif /* MBEDTLS_GENPRIME */
@@ -3009,164 +2597,175 @@
 /*
  * Checkup routine
  */
-int mbedtls_mpi_self_test( int verbose )
+int mbedtls_mpi_self_test(int verbose)
 {
     int ret, i;
     mbedtls_mpi A, E, N, X, Y, U, V;
 
-    mbedtls_mpi_init_mempool( &A ); mbedtls_mpi_init_mempool( &E );
-    mbedtls_mpi_init_mempool( &N ); mbedtls_mpi_init_mempool( &X );
-    mbedtls_mpi_init_mempool( &Y ); mbedtls_mpi_init_mempool( &U );
-    mbedtls_mpi_init_mempool( &V );
+    mbedtls_mpi_init_mempool(&A); mbedtls_mpi_init_mempool(&E);
+    mbedtls_mpi_init_mempool(&N); mbedtls_mpi_init_mempool(&X);
+    mbedtls_mpi_init_mempool(&Y); mbedtls_mpi_init_mempool(&U);
+    mbedtls_mpi_init_mempool(&V);
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
-        "EFE021C2645FD1DC586E69184AF4A31E" \
-        "D5F53E93B5F123FA41680867BA110131" \
-        "944FE7952E2517337780CB0DB80E61AA" \
-        "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16,
+                                            "EFE021C2645FD1DC586E69184AF4A31E" \
+                                            "D5F53E93B5F123FA41680867BA110131" \
+                                            "944FE7952E2517337780CB0DB80E61AA" \
+                                            "E7C8DDC6C5C6AADEB34EB38A2F40D5E6"));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
-        "B2E7EFD37075B9F03FF989C7C5051C20" \
-        "34D2A323810251127E7BF8625A4F49A5" \
-        "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
-        "5B5C25763222FEFCCFC38B832366C29E" ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16,
+                                            "B2E7EFD37075B9F03FF989C7C5051C20" \
+                                            "34D2A323810251127E7BF8625A4F49A5" \
+                                            "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
+                                            "5B5C25763222FEFCCFC38B832366C29E"));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
-        "0066A198186C18C10B2F5ED9B522752A" \
-        "9830B69916E535C8F047518A889A43A5" \
-        "94B6BED27A168D31D4A52F88925AA8F5" ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16,
+                                            "0066A198186C18C10B2F5ED9B522752A" \
+                                            "9830B69916E535C8F047518A889A43A5" \
+                                            "94B6BED27A168D31D4A52F88925AA8F5"));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
-        "602AB7ECA597A3D6B56FF9829A5E8B85" \
-        "9E857EA95A03512E2BAE7391688D264A" \
-        "A5663B0341DB9CCFD2C4C5F421FEC814" \
-        "8001B72E848A38CAE1C65F78E56ABDEF" \
-        "E12D3C039B8A02D6BE593F0BBBDA56F1" \
-        "ECF677152EF804370C1A305CAF3B5BF1" \
-        "30879B56C61DE584A0F53A2447A51E" ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
+                                            "602AB7ECA597A3D6B56FF9829A5E8B85" \
+                                            "9E857EA95A03512E2BAE7391688D264A" \
+                                            "A5663B0341DB9CCFD2C4C5F421FEC814" \
+                                            "8001B72E848A38CAE1C65F78E56ABDEF" \
+                                            "E12D3C039B8A02D6BE593F0BBBDA56F1" \
+                                            "ECF677152EF804370C1A305CAF3B5BF1" \
+                                            "30879B56C61DE584A0F53A2447A51E"));
 
-    if( verbose != 0 )
-        mbedtls_printf( "  MPI test #1 (mul_mpi): " );
+    if (verbose != 0) {
+        mbedtls_printf("  MPI test #1 (mul_mpi): ");
+    }
 
-    if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
+    if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("failed\n");
+        }
 
         ret = 1;
         goto cleanup;
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
-        "256567336059E52CAE22925474705F39A94" ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
+                                            "256567336059E52CAE22925474705F39A94"));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
-        "6613F26162223DF488E9CD48CC132C7A" \
-        "0AC93C701B001B092E4E5B9F73BCD27B" \
-        "9EE50D0657C77F374E903CDFA4C642" ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16,
+                                            "6613F26162223DF488E9CD48CC132C7A" \
+                                            "0AC93C701B001B092E4E5B9F73BCD27B" \
+                                            "9EE50D0657C77F374E903CDFA4C642"));
 
-    if( verbose != 0 )
-        mbedtls_printf( "  MPI test #2 (div_mpi): " );
+    if (verbose != 0) {
+        mbedtls_printf("  MPI test #2 (div_mpi): ");
+    }
 
-    if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
-        mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
+    if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 ||
+        mbedtls_mpi_cmp_mpi(&Y, &V) != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("failed\n");
+        }
 
         ret = 1;
         goto cleanup;
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
-        "36E139AEA55215609D2816998ED020BB" \
-        "BD96C37890F65171D948E9BC7CBAA4D9" \
-        "325D24D6A3C12710F10A09FA08AB87" ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
+                                            "36E139AEA55215609D2816998ED020BB" \
+                                            "BD96C37890F65171D948E9BC7CBAA4D9" \
+                                            "325D24D6A3C12710F10A09FA08AB87"));
 
-    if( verbose != 0 )
-        mbedtls_printf( "  MPI test #3 (exp_mod): " );
+    if (verbose != 0) {
+        mbedtls_printf("  MPI test #3 (exp_mod): ");
+    }
 
-    if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
+    if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("failed\n");
+        }
 
         ret = 1;
         goto cleanup;
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
-        "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
-        "C3DBA76456363A10869622EAC2DD84EC" \
-        "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16,
+                                            "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
+                                            "C3DBA76456363A10869622EAC2DD84EC" \
+                                            "C5B8A74DAC4D09E03B5E0BE779F2DF61"));
 
-    if( verbose != 0 )
-        mbedtls_printf( "  MPI test #4 (inv_mod): " );
+    if (verbose != 0) {
+        mbedtls_printf("  MPI test #4 (inv_mod): ");
+    }
 
-    if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
+    if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("failed\n");
+        }
 
         ret = 1;
         goto cleanup;
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
 
-    if( verbose != 0 )
-        mbedtls_printf( "  MPI test #5 (simple gcd): " );
+    if (verbose != 0) {
+        mbedtls_printf("  MPI test #5 (simple gcd): ");
+    }
 
-    for( i = 0; i < GCD_PAIR_COUNT; i++ )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
+    for (i = 0; i < GCD_PAIR_COUNT; i++) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0]));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1]));
 
-        MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y));
 
-        if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "failed at %d\n", i );
+        if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) {
+            if (verbose != 0) {
+                mbedtls_printf("failed at %d\n", i);
+            }
 
             ret = 1;
             goto cleanup;
         }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
 
 cleanup:
 
-    if( ret != 0 && verbose != 0 )
-        mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
+    if (ret != 0 && verbose != 0) {
+        mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
+    }
 
-    mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
-    mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
+    mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X);
+    mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V);
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
-    return( ret );
+    return ret;
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/lib/libmbedtls/mbedtls/library/bignum_core.c b/lib/libmbedtls/mbedtls/library/bignum_core.c
new file mode 100644
index 0000000..e50f043
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/bignum_core.c
@@ -0,0 +1,871 @@
+/*
+ *  Core bignum functions
+ *
+ *  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.
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_BIGNUM_C)
+
+#include <string.h>
+
+#include "mbedtls/error.h"
+#include "mbedtls/platform_util.h"
+#include "constant_time_internal.h"
+
+#include "mbedtls/platform.h"
+
+#include "bignum_core.h"
+#include "bn_mul.h"
+#include "constant_time_internal.h"
+
+size_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a)
+{
+    size_t j;
+    mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
+
+    for (j = 0; j < biL; j++) {
+        if (a & mask) {
+            break;
+        }
+
+        mask >>= 1;
+    }
+
+    return j;
+}
+
+size_t mbedtls_mpi_core_bitlen(const mbedtls_mpi_uint *A, size_t A_limbs)
+{
+    size_t i, j;
+
+    if (A_limbs == 0) {
+        return 0;
+    }
+
+    for (i = A_limbs - 1; i > 0; i--) {
+        if (A[i] != 0) {
+            break;
+        }
+    }
+
+    j = biL - mbedtls_mpi_core_clz(A[i]);
+
+    return (i * biL) + j;
+}
+
+/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
+ * into the storage form used by mbedtls_mpi. */
+static mbedtls_mpi_uint mpi_bigendian_to_host_c(mbedtls_mpi_uint a)
+{
+    uint8_t i;
+    unsigned char *a_ptr;
+    mbedtls_mpi_uint tmp = 0;
+
+    for (i = 0, a_ptr = (unsigned char *) &a; i < ciL; i++, a_ptr++) {
+        tmp <<= CHAR_BIT;
+        tmp |= (mbedtls_mpi_uint) *a_ptr;
+    }
+
+    return tmp;
+}
+
+static mbedtls_mpi_uint mpi_bigendian_to_host(mbedtls_mpi_uint a)
+{
+    if (MBEDTLS_IS_BIG_ENDIAN) {
+        /* Nothing to do on bigendian systems. */
+        return a;
+    } 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);
+    }
+}
+
+void mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A,
+                                        size_t A_limbs)
+{
+    mbedtls_mpi_uint *cur_limb_left;
+    mbedtls_mpi_uint *cur_limb_right;
+    if (A_limbs == 0) {
+        return;
+    }
+
+    /*
+     * Traverse limbs and
+     * - adapt byte-order in each limb
+     * - swap the limbs themselves.
+     * For that, simultaneously traverse the limbs from left to right
+     * and from right to left, as long as the left index is not bigger
+     * than the right index (it's not a problem if limbs is odd and the
+     * indices coincide in the last iteration).
+     */
+    for (cur_limb_left = A, cur_limb_right = A + (A_limbs - 1);
+         cur_limb_left <= cur_limb_right;
+         cur_limb_left++, cur_limb_right--) {
+        mbedtls_mpi_uint tmp;
+        /* Note that if cur_limb_left == cur_limb_right,
+         * this code effectively swaps the bytes only once. */
+        tmp             = mpi_bigendian_to_host(*cur_limb_left);
+        *cur_limb_left  = mpi_bigendian_to_host(*cur_limb_right);
+        *cur_limb_right = tmp;
+    }
+}
+
+/* Whether min <= A, in constant time.
+ * A_limbs must be at least 1. */
+unsigned mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,
+                                      const mbedtls_mpi_uint *A,
+                                      size_t A_limbs)
+{
+    /* min <= least significant limb? */
+    unsigned min_le_lsl = 1 ^ mbedtls_ct_mpi_uint_lt(A[0], min);
+
+    /* limbs other than the least significant one are all zero? */
+    mbedtls_mpi_uint msll_mask = 0;
+    for (size_t i = 1; i < A_limbs; i++) {
+        msll_mask |= A[i];
+    }
+    /* The most significant limbs of A are not all zero iff msll_mask != 0. */
+    unsigned msll_nonzero = mbedtls_ct_mpi_uint_mask(msll_mask) & 1;
+
+    /* min <= A iff the lowest limb of A is >= min or the other limbs
+     * are not all zero. */
+    return min_le_lsl | msll_nonzero;
+}
+
+void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X,
+                                  const mbedtls_mpi_uint *A,
+                                  size_t limbs,
+                                  unsigned char assign)
+{
+    if (X == A) {
+        return;
+    }
+
+    mbedtls_ct_mpi_uint_cond_assign(limbs, X, A, assign);
+}
+
+void mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X,
+                                mbedtls_mpi_uint *Y,
+                                size_t limbs,
+                                unsigned char swap)
+{
+    if (X == Y) {
+        return;
+    }
+
+    /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
+    mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask(swap);
+
+    for (size_t i = 0; i < limbs; i++) {
+        mbedtls_mpi_uint tmp = X[i];
+        X[i] = (X[i] & ~limb_mask) | (Y[i] & limb_mask);
+        Y[i] = (Y[i] & ~limb_mask) | (tmp & limb_mask);
+    }
+}
+
+int mbedtls_mpi_core_read_le(mbedtls_mpi_uint *X,
+                             size_t X_limbs,
+                             const unsigned char *input,
+                             size_t input_length)
+{
+    const size_t limbs = CHARS_TO_LIMBS(input_length);
+
+    if (X_limbs < limbs) {
+        return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
+    }
+
+    if (X != NULL) {
+        memset(X, 0, X_limbs * ciL);
+
+        for (size_t i = 0; i < input_length; i++) {
+            size_t offset = ((i % ciL) << 3);
+            X[i / ciL] |= ((mbedtls_mpi_uint) input[i]) << offset;
+        }
+    }
+
+    return 0;
+}
+
+int mbedtls_mpi_core_read_be(mbedtls_mpi_uint *X,
+                             size_t X_limbs,
+                             const unsigned char *input,
+                             size_t input_length)
+{
+    const size_t limbs = CHARS_TO_LIMBS(input_length);
+
+    if (X_limbs < limbs) {
+        return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
+    }
+
+    /* If X_limbs is 0, input_length must also be 0 (from previous test).
+     * Nothing to do. */
+    if (X_limbs == 0) {
+        return 0;
+    }
+
+    memset(X, 0, X_limbs * ciL);
+
+    /* memcpy() with (NULL, 0) is undefined behaviour */
+    if (input_length != 0) {
+        size_t overhead = (X_limbs * ciL) - input_length;
+        unsigned char *Xp = (unsigned char *) X;
+        memcpy(Xp + overhead, input, input_length);
+    }
+
+    mbedtls_mpi_core_bigendian_to_host(X, X_limbs);
+
+    return 0;
+}
+
+int mbedtls_mpi_core_write_le(const mbedtls_mpi_uint *A,
+                              size_t A_limbs,
+                              unsigned char *output,
+                              size_t output_length)
+{
+    size_t stored_bytes = A_limbs * ciL;
+    size_t bytes_to_copy;
+
+    if (stored_bytes < output_length) {
+        bytes_to_copy = stored_bytes;
+    } else {
+        bytes_to_copy = output_length;
+
+        /* The output buffer is smaller than the allocated size of A.
+         * However A may fit if its leading bytes are zero. */
+        for (size_t i = bytes_to_copy; i < stored_bytes; i++) {
+            if (GET_BYTE(A, i) != 0) {
+                return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
+            }
+        }
+    }
+
+    for (size_t i = 0; i < bytes_to_copy; i++) {
+        output[i] = GET_BYTE(A, i);
+    }
+
+    if (stored_bytes < output_length) {
+        /* Write trailing 0 bytes */
+        memset(output + stored_bytes, 0, output_length - stored_bytes);
+    }
+
+    return 0;
+}
+
+int mbedtls_mpi_core_write_be(const mbedtls_mpi_uint *X,
+                              size_t X_limbs,
+                              unsigned char *output,
+                              size_t output_length)
+{
+    size_t stored_bytes;
+    size_t bytes_to_copy;
+    unsigned char *p;
+
+    stored_bytes = X_limbs * ciL;
+
+    if (stored_bytes < output_length) {
+        /* There is enough space in the output buffer. Write initial
+         * null bytes and record the position at which to start
+         * writing the significant bytes. In this case, the execution
+         * trace of this function does not depend on the value of the
+         * number. */
+        bytes_to_copy = stored_bytes;
+        p = output + output_length - stored_bytes;
+        memset(output, 0, output_length - stored_bytes);
+    } else {
+        /* The output buffer is smaller than the allocated size of X.
+         * However X may fit if its leading bytes are zero. */
+        bytes_to_copy = output_length;
+        p = output;
+        for (size_t i = bytes_to_copy; i < stored_bytes; i++) {
+            if (GET_BYTE(X, i) != 0) {
+                return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL;
+            }
+        }
+    }
+
+    for (size_t i = 0; i < bytes_to_copy; i++) {
+        p[bytes_to_copy - i - 1] = GET_BYTE(X, i);
+    }
+
+    return 0;
+}
+
+void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs,
+                              size_t count)
+{
+    size_t i, v0, v1;
+    mbedtls_mpi_uint r0 = 0, r1;
+
+    v0 = count /  biL;
+    v1 = count & (biL - 1);
+
+    if (v0 > limbs || (v0 == limbs && v1 > 0)) {
+        memset(X, 0, limbs * ciL);
+        return;
+    }
+
+    /*
+     * shift by count / limb_size
+     */
+    if (v0 > 0) {
+        for (i = 0; i < limbs - v0; i++) {
+            X[i] = X[i + v0];
+        }
+
+        for (; i < limbs; i++) {
+            X[i] = 0;
+        }
+    }
+
+    /*
+     * shift by count % limb_size
+     */
+    if (v1 > 0) {
+        for (i = limbs; i > 0; i--) {
+            r1 = X[i - 1] << (biL - v1);
+            X[i - 1] >>= v1;
+            X[i - 1] |= r0;
+            r0 = r1;
+        }
+    }
+}
+
+mbedtls_mpi_uint mbedtls_mpi_core_add(mbedtls_mpi_uint *X,
+                                      const mbedtls_mpi_uint *A,
+                                      const mbedtls_mpi_uint *B,
+                                      size_t limbs)
+{
+    mbedtls_mpi_uint c = 0;
+
+    for (size_t i = 0; i < limbs; i++) {
+        mbedtls_mpi_uint t = c + A[i];
+        c = (t < A[i]);
+        t += B[i];
+        c += (t < B[i]);
+        X[i] = t;
+    }
+
+    return c;
+}
+
+mbedtls_mpi_uint mbedtls_mpi_core_add_if(mbedtls_mpi_uint *X,
+                                         const mbedtls_mpi_uint *A,
+                                         size_t limbs,
+                                         unsigned cond)
+{
+    mbedtls_mpi_uint c = 0;
+
+    /* all-bits 0 if cond is 0, all-bits 1 if cond is non-0 */
+    const mbedtls_mpi_uint mask = mbedtls_ct_mpi_uint_mask(cond);
+
+    for (size_t i = 0; i < limbs; i++) {
+        mbedtls_mpi_uint add = mask & A[i];
+        mbedtls_mpi_uint t = c + X[i];
+        c = (t < X[i]);
+        t += add;
+        c += (t < add);
+        X[i] = t;
+    }
+
+    return c;
+}
+
+mbedtls_mpi_uint mbedtls_mpi_core_sub(mbedtls_mpi_uint *X,
+                                      const mbedtls_mpi_uint *A,
+                                      const mbedtls_mpi_uint *B,
+                                      size_t limbs)
+{
+    mbedtls_mpi_uint c = 0;
+
+    for (size_t i = 0; i < limbs; i++) {
+        mbedtls_mpi_uint z = (A[i] < c);
+        mbedtls_mpi_uint t = A[i] - c;
+        c = (t < B[i]) + z;
+        X[i] = t - B[i];
+    }
+
+    return c;
+}
+
+mbedtls_mpi_uint mbedtls_mpi_core_mla(mbedtls_mpi_uint *d, size_t d_len,
+                                      const mbedtls_mpi_uint *s, size_t s_len,
+                                      mbedtls_mpi_uint b)
+{
+    mbedtls_mpi_uint c = 0; /* carry */
+    /*
+     * It is a documented precondition of this function that d_len >= s_len.
+     * If that's not the case, we swap these round: this turns what would be
+     * a buffer overflow into an incorrect result.
+     */
+    if (d_len < s_len) {
+        s_len = d_len;
+    }
+    size_t excess_len = d_len - s_len;
+    size_t steps_x8 = s_len / 8;
+    size_t steps_x1 = s_len & 7;
+
+    while (steps_x8--) {
+        MULADDC_X8_INIT
+        MULADDC_X8_CORE
+            MULADDC_X8_STOP
+    }
+
+    while (steps_x1--) {
+        MULADDC_X1_INIT
+        MULADDC_X1_CORE
+            MULADDC_X1_STOP
+    }
+
+    while (excess_len--) {
+        *d += c;
+        c = (*d < c);
+        d++;
+    }
+
+    return c;
+}
+
+/*
+ * Fast Montgomery initialization (thanks to Tom St Denis).
+ */
+mbedtls_mpi_uint mbedtls_mpi_core_montmul_init(const mbedtls_mpi_uint *N)
+{
+    mbedtls_mpi_uint x = N[0];
+
+    x += ((N[0] + 2) & 4) << 1;
+
+    for (unsigned int i = biL; i >= 8; i /= 2) {
+        x *= (2 - (N[0] * x));
+    }
+
+    return ~x + 1;
+}
+
+void mbedtls_mpi_core_montmul(mbedtls_mpi_uint *X,
+                              const mbedtls_mpi_uint *A,
+                              const mbedtls_mpi_uint *B,
+                              size_t B_limbs,
+                              const mbedtls_mpi_uint *N,
+                              size_t AN_limbs,
+                              mbedtls_mpi_uint mm,
+                              mbedtls_mpi_uint *T)
+{
+    memset(T, 0, (2 * AN_limbs + 1) * ciL);
+
+    for (size_t i = 0; i < AN_limbs; i++) {
+        /* T = (T + u0*B + u1*N) / 2^biL */
+        mbedtls_mpi_uint u0 = A[i];
+        mbedtls_mpi_uint u1 = (T[0] + u0 * B[0]) * mm;
+
+        (void) mbedtls_mpi_core_mla(T, AN_limbs + 2, B, B_limbs, u0);
+        (void) mbedtls_mpi_core_mla(T, AN_limbs + 2, N, AN_limbs, u1);
+
+        T++;
+    }
+
+    /*
+     * The result we want is (T >= N) ? T - N : T.
+     *
+     * For better constant-time properties in this function, we always do the
+     * subtraction, with the result in X.
+     *
+     * We also look to see if there was any carry in the final additions in the
+     * loop above.
+     */
+
+    mbedtls_mpi_uint carry  = T[AN_limbs];
+    mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, T, N, AN_limbs);
+
+    /*
+     * Using R as the Montgomery radix (auxiliary modulus) i.e. 2^(biL*AN_limbs):
+     *
+     * T can be in one of 3 ranges:
+     *
+     * 1) T < N      : (carry, borrow) = (0, 1): we want T
+     * 2) N <= T < R : (carry, borrow) = (0, 0): we want X
+     * 3) T >= R     : (carry, borrow) = (1, 1): we want X
+     *
+     * and (carry, borrow) = (1, 0) can't happen.
+     *
+     * So the correct return value is already in X if (carry ^ borrow) = 0,
+     * but is in (the lower AN_limbs limbs of) T if (carry ^ borrow) = 1.
+     */
+    mbedtls_ct_mpi_uint_cond_assign(AN_limbs, X, T, (unsigned char) (carry ^ borrow));
+}
+
+int mbedtls_mpi_core_get_mont_r2_unsafe(mbedtls_mpi *X,
+                                        const mbedtls_mpi *N)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 1));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(X, N->n * 2 * biL));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(X, N->n));
+
+cleanup:
+    return ret;
+}
+
+MBEDTLS_STATIC_TESTABLE
+void mbedtls_mpi_core_ct_uint_table_lookup(mbedtls_mpi_uint *dest,
+                                           const mbedtls_mpi_uint *table,
+                                           size_t limbs,
+                                           size_t count,
+                                           size_t index)
+{
+    for (size_t i = 0; i < count; i++, table += limbs) {
+        unsigned char assign = mbedtls_ct_size_bool_eq(i, index);
+        mbedtls_mpi_core_cond_assign(dest, table, limbs, assign);
+    }
+}
+
+/* Fill X with n_bytes random bytes.
+ * X must already have room for those bytes.
+ * The ordering of the bytes returned from the RNG is suitable for
+ * deterministic ECDSA (see RFC 6979 §3.3 and the specification of
+ * mbedtls_mpi_core_random()).
+ */
+int mbedtls_mpi_core_fill_random(
+    mbedtls_mpi_uint *X, size_t X_limbs,
+    size_t n_bytes,
+    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const size_t limbs = CHARS_TO_LIMBS(n_bytes);
+    const size_t overhead = (limbs * ciL) - n_bytes;
+
+    if (X_limbs < limbs) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+
+    memset(X, 0, overhead);
+    memset((unsigned char *) X + limbs * ciL, 0, (X_limbs - limbs) * ciL);
+    MBEDTLS_MPI_CHK(f_rng(p_rng, (unsigned char *) X + overhead, n_bytes));
+    mbedtls_mpi_core_bigendian_to_host(X, limbs);
+
+cleanup:
+    return ret;
+}
+
+int mbedtls_mpi_core_random(mbedtls_mpi_uint *X,
+                            mbedtls_mpi_uint min,
+                            const mbedtls_mpi_uint *N,
+                            size_t limbs,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng)
+{
+    unsigned ge_lower = 1, lt_upper = 0;
+    size_t n_bits = mbedtls_mpi_core_bitlen(N, limbs);
+    size_t n_bytes = (n_bits + 7) / 8;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    /*
+     * When min == 0, each try has at worst a probability 1/2 of failing
+     * (the msb has a probability 1/2 of being 0, and then the result will
+     * be < N), so after 30 tries failure probability is a most 2**(-30).
+     *
+     * When N is just below a power of 2, as is the case when generating
+     * a random scalar on most elliptic curves, 1 try is enough with
+     * overwhelming probability. When N is just above a power of 2,
+     * as when generating a random scalar on secp224k1, each try has
+     * a probability of failing that is almost 1/2.
+     *
+     * The probabilities are almost the same if min is nonzero but negligible
+     * compared to N. This is always the case when N is crypto-sized, but
+     * it's convenient to support small N for testing purposes. When N
+     * is small, use a higher repeat count, otherwise the probability of
+     * failure is macroscopic.
+     */
+    int count = (n_bytes > 4 ? 30 : 250);
+
+    /*
+     * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
+     * when f_rng is a suitably parametrized instance of HMAC_DRBG:
+     * - use the same byte ordering;
+     * - keep the leftmost n_bits bits of the generated octet string;
+     * - try until result is in the desired range.
+     * This also avoids any bias, which is especially important for ECDSA.
+     */
+    do {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_core_fill_random(X, limbs,
+                                                     n_bytes,
+                                                     f_rng, p_rng));
+        mbedtls_mpi_core_shift_r(X, limbs, 8 * n_bytes - n_bits);
+
+        if (--count == 0) {
+            ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
+            goto cleanup;
+        }
+
+        ge_lower = mbedtls_mpi_core_uint_le_mpi(min, X, limbs);
+        lt_upper = mbedtls_mpi_core_lt_ct(X, N, limbs);
+    } while (ge_lower == 0 || lt_upper == 0);
+
+cleanup:
+    return ret;
+}
+
+/* BEGIN MERGE SLOT 1 */
+
+static size_t exp_mod_get_window_size(size_t Ebits)
+{
+    size_t wsize = (Ebits > 671) ? 6 : (Ebits > 239) ? 5 :
+                   (Ebits >  79) ? 4 : 1;
+
+#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
+    if (wsize > MBEDTLS_MPI_WINDOW_SIZE) {
+        wsize = MBEDTLS_MPI_WINDOW_SIZE;
+    }
+#endif
+
+    return wsize;
+}
+
+size_t mbedtls_mpi_core_exp_mod_working_limbs(size_t AN_limbs, size_t E_limbs)
+{
+    const size_t wsize = exp_mod_get_window_size(E_limbs * biL);
+    const size_t welem = ((size_t) 1) << wsize;
+
+    /* How big does each part of the working memory pool need to be? */
+    const size_t table_limbs   = welem * AN_limbs;
+    const size_t select_limbs  = AN_limbs;
+    const size_t temp_limbs    = 2 * AN_limbs + 1;
+
+    return table_limbs + select_limbs + temp_limbs;
+}
+
+static void exp_mod_precompute_window(const mbedtls_mpi_uint *A,
+                                      const mbedtls_mpi_uint *N,
+                                      size_t AN_limbs,
+                                      mbedtls_mpi_uint mm,
+                                      const mbedtls_mpi_uint *RR,
+                                      size_t welem,
+                                      mbedtls_mpi_uint *Wtable,
+                                      mbedtls_mpi_uint *temp)
+{
+    /* W[0] = 1 (in Montgomery presentation) */
+    memset(Wtable, 0, AN_limbs * ciL);
+    Wtable[0] = 1;
+    mbedtls_mpi_core_montmul(Wtable, Wtable, RR, AN_limbs, N, AN_limbs, mm, temp);
+
+    /* W[1] = A (already in Montgomery presentation) */
+    mbedtls_mpi_uint *W1 = Wtable + AN_limbs;
+    memcpy(W1, A, AN_limbs * ciL);
+
+    /* W[i+1] = W[i] * W[1], i >= 2 */
+    mbedtls_mpi_uint *Wprev = W1;
+    for (size_t i = 2; i < welem; i++) {
+        mbedtls_mpi_uint *Wcur = Wprev + AN_limbs;
+        mbedtls_mpi_core_montmul(Wcur, Wprev, W1, AN_limbs, N, AN_limbs, mm, temp);
+        Wprev = Wcur;
+    }
+}
+
+/* Exponentiation: X := A^E mod N.
+ *
+ * A must already be in Montgomery form.
+ *
+ * As in other bignum functions, assume that AN_limbs and E_limbs are nonzero.
+ *
+ * RR must contain 2^{2*biL} mod N.
+ *
+ * The algorithm is a variant of Left-to-right k-ary exponentiation: HAC 14.82
+ * (The difference is that the body in our loop processes a single bit instead
+ * of a full window.)
+ */
+void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X,
+                              const mbedtls_mpi_uint *A,
+                              const mbedtls_mpi_uint *N,
+                              size_t AN_limbs,
+                              const mbedtls_mpi_uint *E,
+                              size_t E_limbs,
+                              const mbedtls_mpi_uint *RR,
+                              mbedtls_mpi_uint *T)
+{
+    const size_t wsize = exp_mod_get_window_size(E_limbs * biL);
+    const size_t welem = ((size_t) 1) << wsize;
+
+    /* This is how we will use the temporary storage T, which must have space
+     * for table_limbs, select_limbs and (2 * AN_limbs + 1) for montmul. */
+    const size_t table_limbs  = welem * AN_limbs;
+    const size_t select_limbs = AN_limbs;
+
+    /* Pointers to specific parts of the temporary working memory pool */
+    mbedtls_mpi_uint *const Wtable  = T;
+    mbedtls_mpi_uint *const Wselect = Wtable  +  table_limbs;
+    mbedtls_mpi_uint *const temp    = Wselect + select_limbs;
+
+    /*
+     * Window precomputation
+     */
+
+    const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N);
+
+    /* Set Wtable[i] = A^(2^i) (in Montgomery representation) */
+    exp_mod_precompute_window(A, N, AN_limbs,
+                              mm, RR,
+                              welem, Wtable, temp);
+
+    /*
+     * Fixed window exponentiation
+     */
+
+    /* X = 1 (in Montgomery presentation) initially */
+    memcpy(X, Wtable, AN_limbs * ciL);
+
+    /* We'll process the bits of E from most significant
+     * (limb_index=E_limbs-1, E_bit_index=biL-1) to least significant
+     * (limb_index=0, E_bit_index=0). */
+    size_t E_limb_index = E_limbs;
+    size_t E_bit_index = 0;
+    /* At any given time, window contains window_bits bits from E.
+     * window_bits can go up to wsize. */
+    size_t window_bits = 0;
+    mbedtls_mpi_uint window = 0;
+
+    do {
+        /* Square */
+        mbedtls_mpi_core_montmul(X, X, X, AN_limbs, N, AN_limbs, mm, temp);
+
+        /* Move to the next bit of the exponent */
+        if (E_bit_index == 0) {
+            --E_limb_index;
+            E_bit_index = biL - 1;
+        } else {
+            --E_bit_index;
+        }
+        /* Insert next exponent bit into window */
+        ++window_bits;
+        window <<= 1;
+        window |= (E[E_limb_index] >> E_bit_index) & 1;
+
+        /* Clear window if it's full. Also clear the window at the end,
+         * when we've finished processing the exponent. */
+        if (window_bits == wsize ||
+            (E_bit_index == 0 && E_limb_index == 0)) {
+            /* Select Wtable[window] without leaking window through
+             * memory access patterns. */
+            mbedtls_mpi_core_ct_uint_table_lookup(Wselect, Wtable,
+                                                  AN_limbs, welem, window);
+            /* Multiply X by the selected element. */
+            mbedtls_mpi_core_montmul(X, X, Wselect, AN_limbs, N, AN_limbs, mm,
+                                     temp);
+            window = 0;
+            window_bits = 0;
+        }
+    } while (!(E_bit_index == 0 && E_limb_index == 0));
+}
+
+/* END MERGE SLOT 1 */
+
+/* BEGIN MERGE SLOT 2 */
+
+/* END MERGE SLOT 2 */
+
+/* BEGIN MERGE SLOT 3 */
+
+mbedtls_mpi_uint mbedtls_mpi_core_sub_int(mbedtls_mpi_uint *X,
+                                          const mbedtls_mpi_uint *A,
+                                          mbedtls_mpi_uint c,  /* doubles as carry */
+                                          size_t limbs)
+{
+    for (size_t i = 0; i < limbs; i++) {
+        mbedtls_mpi_uint s = A[i];
+        mbedtls_mpi_uint t = s - c;
+        c = (t > s);
+        X[i] = t;
+    }
+
+    return c;
+}
+
+mbedtls_mpi_uint mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A,
+                                                size_t limbs)
+{
+    mbedtls_mpi_uint bits = 0;
+
+    for (size_t i = 0; i < limbs; i++) {
+        bits |= A[i];
+    }
+
+    return bits;
+}
+
+void mbedtls_mpi_core_to_mont_rep(mbedtls_mpi_uint *X,
+                                  const mbedtls_mpi_uint *A,
+                                  const mbedtls_mpi_uint *N,
+                                  size_t AN_limbs,
+                                  mbedtls_mpi_uint mm,
+                                  const mbedtls_mpi_uint *rr,
+                                  mbedtls_mpi_uint *T)
+{
+    mbedtls_mpi_core_montmul(X, A, rr, AN_limbs, N, AN_limbs, mm, T);
+}
+
+void mbedtls_mpi_core_from_mont_rep(mbedtls_mpi_uint *X,
+                                    const mbedtls_mpi_uint *A,
+                                    const mbedtls_mpi_uint *N,
+                                    size_t AN_limbs,
+                                    mbedtls_mpi_uint mm,
+                                    mbedtls_mpi_uint *T)
+{
+    const mbedtls_mpi_uint Rinv = 1;    /* 1/R in Mont. rep => 1 */
+
+    mbedtls_mpi_core_montmul(X, A, &Rinv, 1, N, AN_limbs, mm, T);
+}
+
+/* END MERGE SLOT 3 */
+
+/* BEGIN MERGE SLOT 4 */
+
+/* END MERGE SLOT 4 */
+
+/* BEGIN MERGE SLOT 5 */
+
+/* END MERGE SLOT 5 */
+
+/* BEGIN MERGE SLOT 6 */
+
+/* END MERGE SLOT 6 */
+
+/* BEGIN MERGE SLOT 7 */
+
+/* END MERGE SLOT 7 */
+
+/* BEGIN MERGE SLOT 8 */
+
+/* END MERGE SLOT 8 */
+
+/* BEGIN MERGE SLOT 9 */
+
+/* END MERGE SLOT 9 */
+
+/* BEGIN MERGE SLOT 10 */
+
+/* END MERGE SLOT 10 */
+
+#endif /* MBEDTLS_BIGNUM_C */
diff --git a/lib/libmbedtls/mbedtls/library/bignum_core.h b/lib/libmbedtls/mbedtls/library/bignum_core.h
new file mode 100644
index 0000000..05bc923
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/bignum_core.h
@@ -0,0 +1,767 @@
+/**
+ *  Core bignum functions
+ *
+ *  This interface should only be used by the legacy bignum module (bignum.h)
+ *  and the modular bignum modules (bignum_mod.c, bignum_mod_raw.c). All other
+ *  modules should use the high-level modular bignum interface (bignum_mod.h)
+ *  or the legacy bignum interface (bignum.h).
+ *
+ * This module is about processing non-negative integers with a fixed upper
+ * bound that's of the form 2^n-1 where n is a multiple of #biL.
+ * These can be thought of integers written in base 2^#biL with a fixed
+ * number of digits. Digits in this base are called *limbs*.
+ * Many operations treat these numbers as the principal representation of
+ * a number modulo 2^n or a smaller bound.
+ *
+ * The functions in this module obey the following conventions unless
+ * explicitly indicated otherwise:
+ *
+ * - **Overflow**: some functions indicate overflow from the range
+ *   [0, 2^n-1] by returning carry parameters, while others operate
+ *   modulo and so cannot overflow. This should be clear from the function
+ *   documentation.
+ * - **Bignum parameters**: Bignums are passed as pointers to an array of
+ *   limbs. A limb has the type #mbedtls_mpi_uint. Unless otherwise specified:
+ *     - Bignum parameters called \p A, \p B, ... are inputs, and are
+ *       not modified by the function.
+ *     - For operations modulo some number, the modulus is called \p N
+ *       and is input-only.
+ *     - Bignum parameters called \p X, \p Y are outputs or input-output.
+ *       The initial content of output-only parameters is ignored.
+ *     - Some functions use different names that reflect traditional
+ *       naming of operands of certain operations (e.g.
+ *       divisor/dividend/quotient/remainder).
+ *     - \p T is a temporary storage area. The initial content of such
+ *       parameter is ignored and the final content is unspecified.
+ * - **Bignum sizes**: bignum sizes are always expressed in limbs.
+ *   Most functions work on bignums of a given size and take a single
+ *   \p limbs parameter that applies to all parameters that are limb arrays.
+ *   All bignum sizes must be at least 1 and must be significantly less than
+ *   #SIZE_MAX. The behavior if a size is 0 is undefined. The behavior if the
+ *   total size of all parameters overflows #SIZE_MAX is undefined.
+ * - **Parameter ordering**: for bignum parameters, outputs come before inputs.
+ *   Temporaries come last.
+ * - **Aliasing**: in general, output bignums may be aliased to one or more
+ *   inputs. As an exception, parameters that are documented as a modulus value
+ *   may not be aliased to an output. Outputs may not be aliased to one another.
+ *   Temporaries may not be aliased to any other parameter.
+ * - **Overlap**: apart from aliasing of limb array pointers (where two
+ *   arguments are equal pointers), overlap is not supported and may result
+ *   in undefined behavior.
+ * - **Error handling**: This is a low-level module. Functions generally do not
+ *   try to protect against invalid arguments such as nonsensical sizes or
+ *   null pointers. Note that some functions that operate on bignums of
+ *   different sizes have constraints about their size, and violating those
+ *   constraints may lead to buffer overflows.
+ * - **Modular representatives**: functions that operate modulo \p N expect
+ *   all modular inputs to be in the range [0, \p N - 1] and guarantee outputs
+ *   in the range [0, \p N - 1]. If an input is out of range, outputs are
+ *   fully unspecified, though bignum values out of range should not cause
+ *   buffer overflows (beware that this is not extensively tested).
+ */
+
+/*
+ *  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_BIGNUM_CORE_H
+#define MBEDTLS_BIGNUM_CORE_H
+
+#include "common.h"
+
+#if defined(MBEDTLS_BIGNUM_C)
+#include "mbedtls/bignum.h"
+#endif
+
+#define ciL    (sizeof(mbedtls_mpi_uint))     /** chars in limb  */
+#define biL    (ciL << 3)                     /** bits  in limb  */
+#define biH    (ciL << 2)                     /** half limb size */
+
+/*
+ * Convert between bits/chars and number of limbs
+ * Divide first in order to avoid potential overflows
+ */
+#define BITS_TO_LIMBS(i)  ((i) / biL + ((i) % biL != 0))
+#define CHARS_TO_LIMBS(i) ((i) / ciL + ((i) % ciL != 0))
+/* Get a specific byte, without range checks. */
+#define GET_BYTE(X, i)                                \
+    (((X)[(i) / ciL] >> (((i) % ciL) * 8)) & 0xff)
+
+/** Count leading zero bits in a given integer.
+ *
+ * \param a     Integer to count leading zero bits.
+ *
+ * \return      The number of leading zero bits in \p a.
+ */
+size_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a);
+
+/** Return the minimum number of bits required to represent the value held
+ * in the MPI.
+ *
+ * \note This function returns 0 if all the limbs of \p A are 0.
+ *
+ * \param[in] A     The address of the MPI.
+ * \param A_limbs   The number of limbs of \p A.
+ *
+ * \return      The number of bits in \p A.
+ */
+size_t mbedtls_mpi_core_bitlen(const mbedtls_mpi_uint *A, size_t A_limbs);
+
+/** Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
+ * into the storage form used by mbedtls_mpi.
+ *
+ * \param[in,out] A     The address of the MPI.
+ * \param A_limbs       The number of limbs of \p A.
+ */
+void mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A,
+                                        size_t A_limbs);
+
+/** \brief         Compare a machine integer with an MPI.
+ *
+ *                 This function operates in constant time with respect
+ *                 to the values of \p min and \p A.
+ *
+ * \param min      A machine integer.
+ * \param[in] A    An MPI.
+ * \param A_limbs  The number of limbs of \p A.
+ *                 This must be at least 1.
+ *
+ * \return         1 if \p min is less than or equal to \p A, otherwise 0.
+ */
+unsigned mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,
+                                      const mbedtls_mpi_uint *A,
+                                      size_t A_limbs);
+
+/**
+ * \brief   Perform a safe conditional copy of an MPI which doesn't reveal
+ *          whether assignment was done or not.
+ *
+ * \param[out] X        The address of the destination MPI.
+ *                      This must be initialized. Must have enough limbs to
+ *                      store the full value of \p A.
+ * \param[in]  A        The address of the source MPI. This must be initialized.
+ * \param      limbs    The number of limbs of \p A.
+ * \param      assign   The condition deciding whether to perform the
+ *                      assignment or not. Must be either 0 or 1:
+ *                      * \c 1: Perform the assignment `X = A`.
+ *                      * \c 0: Keep the original value of \p X.
+ *
+ * \note           This function avoids leaking any information about whether
+ *                 the assignment was done or not.
+ *
+ * \warning        If \p assign is neither 0 nor 1, the result of this function
+ *                 is indeterminate, and the resulting value in \p X might be
+ *                 neither its original value nor the value in \p A.
+ */
+void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X,
+                                  const mbedtls_mpi_uint *A,
+                                  size_t limbs,
+                                  unsigned char assign);
+
+/**
+ * \brief   Perform a safe conditional swap of two MPIs which doesn't reveal
+ *          whether the swap was done or not.
+ *
+ * \param[in,out] X         The address of the first MPI.
+ *                          This must be initialized.
+ * \param[in,out] Y         The address of the second MPI.
+ *                          This must be initialized.
+ * \param         limbs     The number of limbs of \p X and \p Y.
+ * \param         swap      The condition deciding whether to perform
+ *                          the swap or not. Must be either 0 or 1:
+ *                          * \c 1: Swap the values of \p X and \p Y.
+ *                          * \c 0: Keep the original values of \p X and \p Y.
+ *
+ * \note           This function avoids leaking any information about whether
+ *                 the swap was done or not.
+ *
+ * \warning        If \p swap is neither 0 nor 1, the result of this function
+ *                 is indeterminate, and both \p X and \p Y might end up with
+ *                 values different to either of the original ones.
+ */
+void mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X,
+                                mbedtls_mpi_uint *Y,
+                                size_t limbs,
+                                unsigned char swap);
+
+/** Import X from unsigned binary data, little-endian.
+ *
+ * The MPI needs to have enough limbs to store the full value (including any
+ * most significant zero bytes in the input).
+ *
+ * \param[out] X         The address of the MPI.
+ * \param X_limbs        The number of limbs of \p X.
+ * \param[in] input      The input buffer to import from.
+ * \param input_length   The length bytes of \p input.
+ *
+ * \return       \c 0 if successful.
+ * \return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't
+ *               large enough to hold the value in \p input.
+ */
+int mbedtls_mpi_core_read_le(mbedtls_mpi_uint *X,
+                             size_t X_limbs,
+                             const unsigned char *input,
+                             size_t input_length);
+
+/** Import X from unsigned binary data, big-endian.
+ *
+ * The MPI needs to have enough limbs to store the full value (including any
+ * most significant zero bytes in the input).
+ *
+ * \param[out] X        The address of the MPI.
+ *                      May only be #NULL if \p X_limbs is 0 and \p input_length
+ *                      is 0.
+ * \param X_limbs       The number of limbs of \p X.
+ * \param[in] input     The input buffer to import from.
+ *                      May only be #NULL if \p input_length is 0.
+ * \param input_length  The length in bytes of \p input.
+ *
+ * \return       \c 0 if successful.
+ * \return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't
+ *               large enough to hold the value in \p input.
+ */
+int mbedtls_mpi_core_read_be(mbedtls_mpi_uint *X,
+                             size_t X_limbs,
+                             const unsigned char *input,
+                             size_t input_length);
+
+/** Export A into unsigned binary data, little-endian.
+ *
+ * \note If \p output is shorter than \p A the export is still successful if the
+ *       value held in \p A fits in the buffer (that is, if enough of the most
+ *       significant bytes of \p A are 0).
+ *
+ * \param[in] A         The address of the MPI.
+ * \param A_limbs       The number of limbs of \p A.
+ * \param[out] output   The output buffer to export to.
+ * \param output_length The length in bytes of \p output.
+ *
+ * \return       \c 0 if successful.
+ * \return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't
+ *               large enough to hold the value of \p A.
+ */
+int mbedtls_mpi_core_write_le(const mbedtls_mpi_uint *A,
+                              size_t A_limbs,
+                              unsigned char *output,
+                              size_t output_length);
+
+/** Export A into unsigned binary data, big-endian.
+ *
+ * \note If \p output is shorter than \p A the export is still successful if the
+ *       value held in \p A fits in the buffer (that is, if enough of the most
+ *       significant bytes of \p A are 0).
+ *
+ * \param[in] A         The address of the MPI.
+ * \param A_limbs       The number of limbs of \p A.
+ * \param[out] output   The output buffer to export to.
+ * \param output_length The length in bytes of \p output.
+ *
+ * \return       \c 0 if successful.
+ * \return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't
+ *               large enough to hold the value of \p A.
+ */
+int mbedtls_mpi_core_write_be(const mbedtls_mpi_uint *A,
+                              size_t A_limbs,
+                              unsigned char *output,
+                              size_t output_length);
+
+/** \brief              Shift an MPI right in place by a number of bits.
+ *
+ *                      Shifting by more bits than there are bit positions
+ *                      in \p X is valid and results in setting \p X to 0.
+ *
+ *                      This function's execution time depends on the value
+ *                      of \p count (and of course \p limbs).
+ *
+ * \param[in,out] X     The number to shift.
+ * \param limbs         The number of limbs of \p X. This must be at least 1.
+ * \param count         The number of bits to shift by.
+ */
+void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs,
+                              size_t count);
+
+/**
+ * \brief Add two fixed-size large unsigned integers, returning the carry.
+ *
+ * Calculates `A + B` where `A` and `B` have the same size.
+ *
+ * This function operates modulo `2^(biL*limbs)` and returns the carry
+ * (1 if there was a wraparound, and 0 otherwise).
+ *
+ * \p X may be aliased to \p A or \p B.
+ *
+ * \param[out] X    The result of the addition.
+ * \param[in] A     Little-endian presentation of the left operand.
+ * \param[in] B     Little-endian presentation of the right operand.
+ * \param limbs     Number of limbs of \p X, \p A and \p B.
+ *
+ * \return          1 if `A + B >= 2^(biL*limbs)`, 0 otherwise.
+ */
+mbedtls_mpi_uint mbedtls_mpi_core_add(mbedtls_mpi_uint *X,
+                                      const mbedtls_mpi_uint *A,
+                                      const mbedtls_mpi_uint *B,
+                                      size_t limbs);
+
+/**
+ * \brief Conditional addition of two fixed-size large unsigned integers,
+ *        returning the carry.
+ *
+ * Functionally equivalent to
+ *
+ * ```
+ * if( cond )
+ *    X += A;
+ * return carry;
+ * ```
+ *
+ * This function operates modulo `2^(biL*limbs)`.
+ *
+ * \param[in,out] X  The pointer to the (little-endian) array
+ *                   representing the bignum to accumulate onto.
+ * \param[in] A      The pointer to the (little-endian) array
+ *                   representing the bignum to conditionally add
+ *                   to \p X. This may be aliased to \p X but may not
+ *                   overlap otherwise.
+ * \param limbs      Number of limbs of \p X and \p A.
+ * \param cond       Condition bit dictating whether addition should
+ *                   happen or not. This must be \c 0 or \c 1.
+ *
+ * \warning          If \p cond is neither 0 nor 1, the result of this function
+ *                   is unspecified, and the resulting value in \p X might be
+ *                   neither its original value nor \p X + \p A.
+ *
+ * \return           1 if `X + cond * A >= 2^(biL*limbs)`, 0 otherwise.
+ */
+mbedtls_mpi_uint mbedtls_mpi_core_add_if(mbedtls_mpi_uint *X,
+                                         const mbedtls_mpi_uint *A,
+                                         size_t limbs,
+                                         unsigned cond);
+
+/**
+ * \brief Subtract two fixed-size large unsigned integers, returning the borrow.
+ *
+ * Calculate `A - B` where \p A and \p B have the same size.
+ * This function operates modulo `2^(biL*limbs)` and returns the carry
+ * (1 if there was a wraparound, i.e. if `A < B`, and 0 otherwise).
+ *
+ * \p X may be aliased to \p A or \p B, or even both, but may not overlap
+ * either otherwise.
+ *
+ * \param[out] X    The result of the subtraction.
+ * \param[in] A     Little-endian presentation of left operand.
+ * \param[in] B     Little-endian presentation of right operand.
+ * \param limbs     Number of limbs of \p X, \p A and \p B.
+ *
+ * \return          1 if `A < B`.
+ *                  0 if `A >= B`.
+ */
+mbedtls_mpi_uint mbedtls_mpi_core_sub(mbedtls_mpi_uint *X,
+                                      const mbedtls_mpi_uint *A,
+                                      const mbedtls_mpi_uint *B,
+                                      size_t limbs);
+
+/**
+ * \brief Perform a fixed-size multiply accumulate operation: X += b * A
+ *
+ * \p X may be aliased to \p A (when \p X_limbs == \p A_limbs), but may not
+ * otherwise overlap.
+ *
+ * This function operates modulo `2^(biL*X_limbs)`.
+ *
+ * \param[in,out] X  The pointer to the (little-endian) array
+ *                   representing the bignum to accumulate onto.
+ * \param X_limbs    The number of limbs of \p X. This must be
+ *                   at least \p A_limbs.
+ * \param[in] A      The pointer to the (little-endian) array
+ *                   representing the bignum to multiply with.
+ *                   This may be aliased to \p X but may not overlap
+ *                   otherwise.
+ * \param A_limbs    The number of limbs of \p A.
+ * \param b          X scalar to multiply with.
+ *
+ * \return           The carry at the end of the operation.
+ */
+mbedtls_mpi_uint mbedtls_mpi_core_mla(mbedtls_mpi_uint *X, size_t X_limbs,
+                                      const mbedtls_mpi_uint *A, size_t A_limbs,
+                                      mbedtls_mpi_uint b);
+
+/**
+ * \brief Calculate initialisation value for fast Montgomery modular
+ *        multiplication
+ *
+ * \param[in] N  Little-endian presentation of the modulus. This must have
+ *               at least one limb.
+ *
+ * \return       The initialisation value for fast Montgomery modular multiplication
+ */
+mbedtls_mpi_uint mbedtls_mpi_core_montmul_init(const mbedtls_mpi_uint *N);
+
+/**
+ * \brief Montgomery multiplication: X = A * B * R^-1 mod N (HAC 14.36)
+ *
+ * \p A and \p B must be in canonical form. That is, < \p N.
+ *
+ * \p X may be aliased to \p A or \p N, or even \p B (if \p AN_limbs ==
+ * \p B_limbs) but may not overlap any parameters otherwise.
+ *
+ * \p A and \p B may alias each other, if \p AN_limbs == \p B_limbs. They may
+ * not alias \p N (since they must be in canonical form, they cannot == \p N).
+ *
+ * \param[out]    X         The destination MPI, as a little-endian array of
+ *                          length \p AN_limbs.
+ *                          On successful completion, X contains the result of
+ *                          the multiplication `A * B * R^-1` mod N where
+ *                          `R = 2^(biL*AN_limbs)`.
+ * \param[in]     A         Little-endian presentation of first operand.
+ *                          Must have the same number of limbs as \p N.
+ * \param[in]     B         Little-endian presentation of second operand.
+ * \param[in]     B_limbs   The number of limbs in \p B.
+ *                          Must be <= \p AN_limbs.
+ * \param[in]     N         Little-endian presentation of the modulus.
+ *                          This must be odd, and have exactly the same number
+ *                          of limbs as \p A.
+ *                          It may alias \p X, but must not alias or otherwise
+ *                          overlap any of the other parameters.
+ * \param[in]     AN_limbs  The number of limbs in \p X, \p A and \p N.
+ * \param         mm        The Montgomery constant for \p N: -N^-1 mod 2^biL.
+ *                          This can be calculated by `mbedtls_mpi_core_montmul_init()`.
+ * \param[in,out] T         Temporary storage of size at least 2*AN_limbs+1 limbs.
+ *                          Its initial content is unused and
+ *                          its final content is indeterminate.
+ *                          It must not alias or otherwise overlap any of the
+ *                          other parameters.
+ */
+void mbedtls_mpi_core_montmul(mbedtls_mpi_uint *X,
+                              const mbedtls_mpi_uint *A,
+                              const mbedtls_mpi_uint *B, size_t B_limbs,
+                              const mbedtls_mpi_uint *N, size_t AN_limbs,
+                              mbedtls_mpi_uint mm, mbedtls_mpi_uint *T);
+
+/**
+ * \brief Calculate the square of the Montgomery constant. (Needed
+ *        for conversion and operations in Montgomery form.)
+ *
+ * \param[out] X  A pointer to the result of the calculation of
+ *                the square of the Montgomery constant:
+ *                2^{2*n*biL} mod N.
+ * \param[in]  N  Little-endian presentation of the modulus, which must be odd.
+ *
+ * \return        0 if successful.
+ * \return        #MBEDTLS_ERR_MPI_ALLOC_FAILED if there is not enough space
+ *                to store the value of Montgomery constant squared.
+ * \return        #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p N modulus is zero.
+ * \return        #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p N modulus is negative.
+ */
+int mbedtls_mpi_core_get_mont_r2_unsafe(mbedtls_mpi *X,
+                                        const mbedtls_mpi *N);
+
+#if defined(MBEDTLS_TEST_HOOKS)
+/**
+ * Copy an MPI from a table without leaking the index.
+ *
+ * \param dest              The destination buffer. This must point to a writable
+ *                          buffer of at least \p limbs limbs.
+ * \param table             The address of the table. This must point to a readable
+ *                          array of \p count elements of \p limbs limbs each.
+ * \param limbs             The number of limbs in each table entry.
+ * \param count             The number of entries in \p table.
+ * \param index             The (secret) table index to look up. This must be in the
+ *                          range `0 .. count-1`.
+ */
+void mbedtls_mpi_core_ct_uint_table_lookup(mbedtls_mpi_uint *dest,
+                                           const mbedtls_mpi_uint *table,
+                                           size_t limbs,
+                                           size_t count,
+                                           size_t index);
+#endif /* MBEDTLS_TEST_HOOKS */
+
+/**
+ * \brief          Fill an integer with a number of random bytes.
+ *
+ * \param X        The destination MPI.
+ * \param X_limbs  The number of limbs of \p X.
+ * \param bytes    The number of random bytes to generate.
+ * \param f_rng    The RNG function to use. This must not be \c NULL.
+ * \param p_rng    The RNG parameter to be passed to \p f_rng. This may be
+ *                 \c NULL if \p f_rng doesn't need a context argument.
+ *
+ * \return         \c 0 if successful.
+ * \return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p X does not have
+ *                 enough room for \p bytes bytes.
+ * \return         A negative error code on RNG failure.
+ *
+ * \note           The bytes obtained from the RNG are interpreted
+ *                 as a big-endian representation of an MPI; this can
+ *                 be relevant in applications like deterministic ECDSA.
+ */
+int mbedtls_mpi_core_fill_random(mbedtls_mpi_uint *X, size_t X_limbs,
+                                 size_t bytes,
+                                 int (*f_rng)(void *, unsigned char *, size_t),
+                                 void *p_rng);
+
+/** Generate a random number uniformly in a range.
+ *
+ * This function generates a random number between \p min inclusive and
+ * \p N exclusive.
+ *
+ * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)
+ * when the RNG is a suitably parametrized instance of HMAC_DRBG
+ * and \p min is \c 1.
+ *
+ * \note           There are `N - min` possible outputs. The lower bound
+ *                 \p min can be reached, but the upper bound \p N cannot.
+ *
+ * \param X        The destination MPI, with \p limbs limbs.
+ *                 It must not be aliased with \p N or otherwise overlap it.
+ * \param min      The minimum value to return.
+ * \param N        The upper bound of the range, exclusive, with \p limbs limbs.
+ *                 In other words, this is one plus the maximum value to return.
+ *                 \p N must be strictly larger than \p min.
+ * \param limbs    The number of limbs of \p N and \p X.
+ *                 This must not be 0.
+ * \param f_rng    The RNG function to use. This must not be \c NULL.
+ * \param p_rng    The RNG parameter to be passed to \p f_rng.
+ *
+ * \return         \c 0 if successful.
+ * \return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was
+ *                 unable to find a suitable value within a limited number
+ *                 of attempts. This has a negligible probability if \p N
+ *                 is significantly larger than \p min, which is the case
+ *                 for all usual cryptographic applications.
+ */
+int mbedtls_mpi_core_random(mbedtls_mpi_uint *X,
+                            mbedtls_mpi_uint min,
+                            const mbedtls_mpi_uint *N,
+                            size_t limbs,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng);
+
+/* BEGIN MERGE SLOT 1 */
+
+/**
+ * \brief          Returns the number of limbs of working memory required for
+ *                 a call to `mbedtls_mpi_core_exp_mod()`.
+ *
+ * \note           This will always be at least
+ *                 `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`,
+ *                 i.e. sufficient for a call to `mbedtls_mpi_core_montmul()`.
+ *
+ * \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_core_exp_mod()`.
+ * \param E_limbs  The number of limbs in the exponent `E` that will be given
+ *                 to `mbedtls_mpi_core_exp_mod()`.
+ *
+ * \return         The number of limbs of working memory required by
+ *                 `mbedtls_mpi_core_exp_mod()`.
+ */
+size_t mbedtls_mpi_core_exp_mod_working_limbs(size_t AN_limbs, size_t E_limbs);
+
+/**
+ * \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.
+ *                   Must be in Montgomery form.
+ * \param[in] N      The modulus, as a little endian array of length \p AN_limbs.
+ * \param AN_limbs   The number of limbs in \p X, \p A, \p N, \p RR.
+ * \param[in] E      The exponent, as a little endian array of length \p E_limbs.
+ * \param E_limbs    The number of limbs in \p E.
+ * \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_core_exp_mod_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_core_exp_mod(mbedtls_mpi_uint *X,
+                              const mbedtls_mpi_uint *A,
+                              const mbedtls_mpi_uint *N, size_t AN_limbs,
+                              const mbedtls_mpi_uint *E, size_t E_limbs,
+                              const mbedtls_mpi_uint *RR,
+                              mbedtls_mpi_uint *T);
+
+/* END MERGE SLOT 1 */
+
+/* BEGIN MERGE SLOT 2 */
+
+/* END MERGE SLOT 2 */
+
+/* BEGIN MERGE SLOT 3 */
+
+/**
+ * \brief Subtract unsigned integer from known-size large unsigned integers.
+ *        Return the borrow.
+ *
+ * \param[out] X    The result of the subtraction.
+ * \param[in] A     The left operand.
+ * \param b         The unsigned scalar to subtract.
+ * \param limbs     Number of limbs of \p X and \p A.
+ *
+ * \return          1 if `A < b`.
+ *                  0 if `A >= b`.
+ */
+mbedtls_mpi_uint mbedtls_mpi_core_sub_int(mbedtls_mpi_uint *X,
+                                          const mbedtls_mpi_uint *A,
+                                          mbedtls_mpi_uint b,
+                                          size_t limbs);
+
+/**
+ * \brief Determine if a given MPI has the value \c 0 in constant time with
+ *        respect to the value (but not with respect to the number of limbs).
+ *
+ * \param[in] A   The MPI to test.
+ * \param limbs   Number of limbs in \p A.
+ *
+ * \return        0 if `A == 0`
+ *                non-0 (may be any value) if `A != 0`.
+ */
+mbedtls_mpi_uint mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A,
+                                                size_t limbs);
+
+/**
+ * \brief          Returns the number of limbs of working memory required for
+ *                 a call to `mbedtls_mpi_core_montmul()`.
+ *
+ * \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_core_montmul()` or one of the other functions
+ *                 that specifies this as the amount of working memory needed.
+ *
+ * \return         The number of limbs of working memory required by
+ *                 `mbedtls_mpi_core_montmul()` (or other similar function).
+ */
+static inline size_t mbedtls_mpi_core_montmul_working_limbs(size_t AN_limbs)
+{
+    return 2 * AN_limbs + 1;
+}
+
+/** Convert an MPI into Montgomery form.
+ *
+ * \p X may be aliased to \p A, but may not otherwise overlap it.
+ *
+ * \p X may not alias \p N (it is in canonical form, so must be strictly less
+ * than \p N). Nor may it alias or overlap \p rr (this is unlikely to be
+ * required in practice.)
+ *
+ * This function is a thin wrapper around `mbedtls_mpi_core_montmul()` that is
+ * an alternative to calling `mbedtls_mpi_mod_raw_to_mont_rep()` when we
+ * don't want to allocate memory.
+ *
+ * \param[out]    X         The result of the conversion.
+ *                          Must have the same number of limbs as \p A.
+ * \param[in]     A         The MPI to convert into Montgomery form.
+ *                          Must have the same number of limbs as the modulus.
+ * \param[in]     N         The address of the modulus, which gives the size of
+ *                          the base `R` = 2^(biL*N->limbs).
+ * \param[in]     AN_limbs  The number of limbs in \p X, \p A, \p N and \p rr.
+ * \param         mm        The Montgomery constant for \p N: -N^-1 mod 2^biL.
+ *                          This can be determined by calling
+ *                          `mbedtls_mpi_core_montmul_init()`.
+ * \param[in]     rr        The residue for `2^{2*n*biL} mod N`.
+ * \param[in,out] T         Temporary storage of size at least
+ *                          `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`
+ *                          limbs.
+ *                          Its initial content is unused and
+ *                          its final content is indeterminate.
+ *                          It must not alias or otherwise overlap any of the
+ *                          other parameters.
+ */
+void mbedtls_mpi_core_to_mont_rep(mbedtls_mpi_uint *X,
+                                  const mbedtls_mpi_uint *A,
+                                  const mbedtls_mpi_uint *N,
+                                  size_t AN_limbs,
+                                  mbedtls_mpi_uint mm,
+                                  const mbedtls_mpi_uint *rr,
+                                  mbedtls_mpi_uint *T);
+
+/** Convert an MPI from Montgomery form.
+ *
+ * \p X may be aliased to \p A, but may not otherwise overlap it.
+ *
+ * \p X may not alias \p N (it is in canonical form, so must be strictly less
+ * than \p N).
+ *
+ * This function is a thin wrapper around `mbedtls_mpi_core_montmul()` that is
+ * an alternative to calling `mbedtls_mpi_mod_raw_from_mont_rep()` when we
+ * don't want to allocate memory.
+ *
+ * \param[out]    X         The result of the conversion.
+ *                          Must have the same number of limbs as \p A.
+ * \param[in]     A         The MPI to convert from Montgomery form.
+ *                          Must have the same number of limbs as the modulus.
+ * \param[in]     N         The address of the modulus, which gives the size of
+ *                          the base `R` = 2^(biL*N->limbs).
+ * \param[in]     AN_limbs  The number of limbs in \p X, \p A and \p N.
+ * \param         mm        The Montgomery constant for \p N: -N^-1 mod 2^biL.
+ *                          This can be determined by calling
+ *                          `mbedtls_mpi_core_montmul_init()`.
+ * \param[in,out] T         Temporary storage of size at least
+ *                          `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`
+ *                          limbs.
+ *                          Its initial content is unused and
+ *                          its final content is indeterminate.
+ *                          It must not alias or otherwise overlap any of the
+ *                          other parameters.
+ */
+void mbedtls_mpi_core_from_mont_rep(mbedtls_mpi_uint *X,
+                                    const mbedtls_mpi_uint *A,
+                                    const mbedtls_mpi_uint *N,
+                                    size_t AN_limbs,
+                                    mbedtls_mpi_uint mm,
+                                    mbedtls_mpi_uint *T);
+
+/* END MERGE SLOT 3 */
+
+/* BEGIN MERGE SLOT 4 */
+
+/* END MERGE SLOT 4 */
+
+/* BEGIN MERGE SLOT 5 */
+
+/* END MERGE SLOT 5 */
+
+/* BEGIN MERGE SLOT 6 */
+
+/* END MERGE SLOT 6 */
+
+/* BEGIN MERGE SLOT 7 */
+
+/* END MERGE SLOT 7 */
+
+/* BEGIN MERGE SLOT 8 */
+
+/* END MERGE SLOT 8 */
+
+/* BEGIN MERGE SLOT 9 */
+
+/* END MERGE SLOT 9 */
+
+/* BEGIN MERGE SLOT 10 */
+
+/* END MERGE SLOT 10 */
+
+#endif /* MBEDTLS_BIGNUM_CORE_H */
diff --git a/lib/libmbedtls/mbedtls/library/bignum_mod.c b/lib/libmbedtls/mbedtls/library/bignum_mod.c
new file mode 100644
index 0000000..e986865
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/bignum_mod.c
@@ -0,0 +1,434 @@
+/**
+ *  Modular bignum functions
+ *
+ *  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.
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_BIGNUM_C)
+
+#include <string.h>
+
+#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
+#include "mbedtls/bignum.h"
+
+#include "mbedtls/platform.h"
+
+#include "bignum_core.h"
+#include "bignum_mod.h"
+#include "bignum_mod_raw.h"
+#include "constant_time_internal.h"
+
+int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r,
+                                  const mbedtls_mpi_mod_modulus *N,
+                                  mbedtls_mpi_uint *p,
+                                  size_t p_limbs)
+{
+    if (p_limbs != N->limbs || !mbedtls_mpi_core_lt_ct(p, N->p, N->limbs)) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+
+    r->limbs = N->limbs;
+    r->p = p;
+
+    return 0;
+}
+
+void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r)
+{
+    if (r == NULL) {
+        return;
+    }
+
+    r->limbs = 0;
+    r->p = NULL;
+}
+
+void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N)
+{
+    if (N == NULL) {
+        return;
+    }
+
+    N->p = NULL;
+    N->limbs = 0;
+    N->bits = 0;
+    N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
+}
+
+void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N)
+{
+    if (N == NULL) {
+        return;
+    }
+
+    switch (N->int_rep) {
+        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
+            if (N->rep.mont.rr != NULL) {
+                mbedtls_platform_zeroize((mbedtls_mpi_uint *) N->rep.mont.rr,
+                                         N->limbs * sizeof(mbedtls_mpi_uint));
+                mbedtls_free((mbedtls_mpi_uint *) N->rep.mont.rr);
+                N->rep.mont.rr = NULL;
+            }
+            N->rep.mont.mm = 0;
+            break;
+        case MBEDTLS_MPI_MOD_REP_OPT_RED:
+            mbedtls_free(N->rep.ored);
+            break;
+        case MBEDTLS_MPI_MOD_REP_INVALID:
+            break;
+    }
+
+    N->p = NULL;
+    N->limbs = 0;
+    N->bits = 0;
+    N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
+}
+
+static int set_mont_const_square(const mbedtls_mpi_uint **X,
+                                 const mbedtls_mpi_uint *A,
+                                 size_t limbs)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_mpi N;
+    mbedtls_mpi RR;
+    *X = NULL;
+
+    mbedtls_mpi_init(&N);
+    mbedtls_mpi_init(&RR);
+
+    if (A == NULL || limbs == 0 || limbs >= (MBEDTLS_MPI_MAX_LIMBS / 2) - 2) {
+        goto cleanup;
+    }
+
+    if (mbedtls_mpi_grow(&N, limbs)) {
+        goto cleanup;
+    }
+
+    memcpy(N.p, A, sizeof(mbedtls_mpi_uint) * limbs);
+
+    ret = mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N);
+
+    if (ret == 0) {
+        *X = RR.p;
+        RR.p = NULL;
+    }
+
+cleanup:
+    mbedtls_mpi_free(&N);
+    mbedtls_mpi_free(&RR);
+    ret = (ret != 0) ? MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED : 0;
+    return ret;
+}
+
+int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,
+                                  const mbedtls_mpi_uint *p,
+                                  size_t p_limbs,
+                                  mbedtls_mpi_mod_rep_selector int_rep)
+{
+    int ret = 0;
+
+    N->p = p;
+    N->limbs = p_limbs;
+    N->bits = mbedtls_mpi_core_bitlen(p, p_limbs);
+
+    switch (int_rep) {
+        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
+            N->int_rep = int_rep;
+            N->rep.mont.mm = mbedtls_mpi_core_montmul_init(N->p);
+            ret = set_mont_const_square(&N->rep.mont.rr, N->p, N->limbs);
+            break;
+        case MBEDTLS_MPI_MOD_REP_OPT_RED:
+            N->int_rep = int_rep;
+            N->rep.ored = NULL;
+            break;
+        default:
+            ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+            goto exit;
+    }
+
+exit:
+
+    if (ret != 0) {
+        mbedtls_mpi_mod_modulus_free(N);
+    }
+
+    return ret;
+}
+
+/* BEGIN MERGE SLOT 1 */
+
+/* END MERGE SLOT 1 */
+
+/* BEGIN MERGE SLOT 2 */
+
+int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X,
+                        const mbedtls_mpi_mod_residue *A,
+                        const mbedtls_mpi_mod_residue *B,
+                        const mbedtls_mpi_mod_modulus *N)
+{
+    if (N->limbs == 0) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+
+    if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+
+    mbedtls_mpi_uint *T = mbedtls_calloc(N->limbs * 2 + 1, ciL);
+    if (T == NULL) {
+        return MBEDTLS_ERR_MPI_ALLOC_FAILED;
+    }
+
+    mbedtls_mpi_mod_raw_mul(X->p, A->p, B->p, N, T);
+
+    mbedtls_free(T);
+
+    return 0;
+}
+
+/* END MERGE SLOT 2 */
+
+/* BEGIN MERGE SLOT 3 */
+int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X,
+                        const mbedtls_mpi_mod_residue *A,
+                        const mbedtls_mpi_mod_residue *B,
+                        const mbedtls_mpi_mod_modulus *N)
+{
+    if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+
+    mbedtls_mpi_mod_raw_sub(X->p, A->p, B->p, N);
+
+    return 0;
+}
+
+static int mbedtls_mpi_mod_inv_mont(mbedtls_mpi_mod_residue *X,
+                                    const mbedtls_mpi_mod_residue *A,
+                                    const mbedtls_mpi_mod_modulus *N,
+                                    mbedtls_mpi_uint *working_memory)
+{
+    /* Input already in Montgomery form, so there's little to do */
+    mbedtls_mpi_mod_raw_inv_prime(X->p, A->p,
+                                  N->p, N->limbs,
+                                  N->rep.mont.rr,
+                                  working_memory);
+    return 0;
+}
+
+static int mbedtls_mpi_mod_inv_non_mont(mbedtls_mpi_mod_residue *X,
+                                        const mbedtls_mpi_mod_residue *A,
+                                        const mbedtls_mpi_mod_modulus *N,
+                                        mbedtls_mpi_uint *working_memory)
+{
+    /* Need to convert input into Montgomery form */
+
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    mbedtls_mpi_mod_modulus Nmont;
+    mbedtls_mpi_mod_modulus_init(&Nmont);
+
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_modulus_setup(&Nmont, N->p, N->limbs,
+                                                  MBEDTLS_MPI_MOD_REP_MONTGOMERY));
+
+    /* We'll use X->p to hold the Montgomery form of the input A->p */
+    mbedtls_mpi_core_to_mont_rep(X->p, A->p, Nmont.p, Nmont.limbs,
+                                 Nmont.rep.mont.mm, Nmont.rep.mont.rr,
+                                 working_memory);
+
+    mbedtls_mpi_mod_raw_inv_prime(X->p, X->p,
+                                  Nmont.p, Nmont.limbs,
+                                  Nmont.rep.mont.rr,
+                                  working_memory);
+
+    /* And convert back from Montgomery form */
+
+    mbedtls_mpi_core_from_mont_rep(X->p, X->p, Nmont.p, Nmont.limbs,
+                                   Nmont.rep.mont.mm, working_memory);
+
+cleanup:
+    mbedtls_mpi_mod_modulus_free(&Nmont);
+    return ret;
+}
+
+int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X,
+                        const mbedtls_mpi_mod_residue *A,
+                        const mbedtls_mpi_mod_modulus *N)
+{
+    if (X->limbs != N->limbs || A->limbs != N->limbs) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+
+    /* Zero has the same value regardless of Montgomery form or not */
+    if (mbedtls_mpi_core_check_zero_ct(A->p, A->limbs) == 0) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+
+    size_t working_limbs =
+        mbedtls_mpi_mod_raw_inv_prime_working_limbs(N->limbs);
+
+    mbedtls_mpi_uint *working_memory = mbedtls_calloc(working_limbs,
+                                                      sizeof(mbedtls_mpi_uint));
+    if (working_memory == NULL) {
+        return MBEDTLS_ERR_MPI_ALLOC_FAILED;
+    }
+
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    switch (N->int_rep) {
+        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
+            ret = mbedtls_mpi_mod_inv_mont(X, A, N, working_memory);
+            break;
+        case MBEDTLS_MPI_MOD_REP_OPT_RED:
+            ret = mbedtls_mpi_mod_inv_non_mont(X, A, N, working_memory);
+            break;
+        default:
+            ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+            break;
+    }
+
+    mbedtls_platform_zeroize(working_memory,
+                             working_limbs * sizeof(mbedtls_mpi_uint));
+    mbedtls_free(working_memory);
+
+    return ret;
+}
+/* END MERGE SLOT 3 */
+
+/* BEGIN MERGE SLOT 4 */
+
+/* END MERGE SLOT 4 */
+
+/* BEGIN MERGE SLOT 5 */
+int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X,
+                        const mbedtls_mpi_mod_residue *A,
+                        const mbedtls_mpi_mod_residue *B,
+                        const mbedtls_mpi_mod_modulus *N)
+{
+    if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+
+    mbedtls_mpi_mod_raw_add(X->p, A->p, B->p, N);
+
+    return 0;
+}
+/* END MERGE SLOT 5 */
+
+/* BEGIN MERGE SLOT 6 */
+
+int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X,
+                           mbedtls_mpi_uint min,
+                           const mbedtls_mpi_mod_modulus *N,
+                           int (*f_rng)(void *, unsigned char *, size_t),
+                           void *p_rng)
+{
+    if (X->limbs != N->limbs) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+    return mbedtls_mpi_mod_raw_random(X->p, min, N, f_rng, p_rng);
+}
+
+/* END MERGE SLOT 6 */
+
+/* BEGIN MERGE SLOT 7 */
+int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r,
+                         const mbedtls_mpi_mod_modulus *N,
+                         const unsigned char *buf,
+                         size_t buflen,
+                         mbedtls_mpi_mod_ext_rep ext_rep)
+{
+    int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+
+    /* Do our best to check if r and m have been set up */
+    if (r->limbs == 0 || N->limbs == 0) {
+        goto cleanup;
+    }
+    if (r->limbs != N->limbs) {
+        goto cleanup;
+    }
+
+    ret = mbedtls_mpi_mod_raw_read(r->p, N, buf, buflen, ext_rep);
+    if (ret != 0) {
+        goto cleanup;
+    }
+
+    r->limbs = N->limbs;
+
+    ret = mbedtls_mpi_mod_raw_canonical_to_modulus_rep(r->p, N);
+
+cleanup:
+    return ret;
+}
+
+int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r,
+                          const mbedtls_mpi_mod_modulus *N,
+                          unsigned char *buf,
+                          size_t buflen,
+                          mbedtls_mpi_mod_ext_rep ext_rep)
+{
+    int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+
+    /* Do our best to check if r and m have been set up */
+    if (r->limbs == 0 || N->limbs == 0) {
+        goto cleanup;
+    }
+    if (r->limbs != N->limbs) {
+        goto cleanup;
+    }
+
+    if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
+        ret = mbedtls_mpi_mod_raw_from_mont_rep(r->p, N);
+        if (ret != 0) {
+            goto cleanup;
+        }
+    }
+
+    ret = mbedtls_mpi_mod_raw_write(r->p, N, buf, buflen, ext_rep);
+
+    if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
+        /* If this fails, the value of r is corrupted and we want to return
+         * this error (as opposed to the error code from the write above) to
+         * let the caller know. If it succeeds, we want to return the error
+         * code from write above. */
+        int conv_ret = mbedtls_mpi_mod_raw_to_mont_rep(r->p, N);
+        if (ret == 0) {
+            ret = conv_ret;
+        }
+    }
+
+cleanup:
+
+    return ret;
+}
+/* END MERGE SLOT 7 */
+
+/* BEGIN MERGE SLOT 8 */
+
+/* END MERGE SLOT 8 */
+
+/* BEGIN MERGE SLOT 9 */
+
+/* END MERGE SLOT 9 */
+
+/* BEGIN MERGE SLOT 10 */
+
+/* END MERGE SLOT 10 */
+
+#endif /* MBEDTLS_BIGNUM_C */
diff --git a/lib/libmbedtls/mbedtls/library/bignum_mod.h b/lib/libmbedtls/mbedtls/library/bignum_mod.h
new file mode 100644
index 0000000..d4c1d5d
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/bignum_mod.h
@@ -0,0 +1,481 @@
+/**
+ *  Modular bignum functions
+ *
+ * This module implements operations on integers modulo some fixed modulus.
+ *
+ * The functions in this module obey the following conventions unless
+ * explicitly indicated otherwise:
+ *
+ * - **Modulus parameters**: the modulus is passed as a pointer to a structure
+ *   of type #mbedtls_mpi_mod_modulus. The structure must be set up with an
+ *   array of limbs storing the bignum value of the modulus. The modulus must
+ *   be odd and is assumed to have no leading zeroes. The modulus is usually
+ *   named \c N and is usually input-only. Functions which take a parameter
+ *   of type \c const #mbedtls_mpi_mod_modulus* must not modify its value.
+ * - **Bignum parameters**: Bignums are passed as pointers to an array of
+ *   limbs or to a #mbedtls_mpi_mod_residue structure. A limb has the type
+ *   #mbedtls_mpi_uint. Residues must be initialized before use, and must be
+ *   associated with the modulus \c N. Unless otherwise specified:
+ *     - Bignum parameters called \c A, \c B, ... are inputs and are not
+ *       modified by the function. Functions which take a parameter of
+ *       type \c const #mbedtls_mpi_mod_residue* must not modify its value.
+ *     - Bignum parameters called \c X, \c Y, ... are outputs or input-output.
+ *       The initial bignum value of output-only parameters is ignored, but
+ *       they must be set up and associated with the modulus \c N. Some
+ *       functions (typically constant-flow) require that the limbs in an
+ *       output residue are initialized.
+ *     - Bignum parameters called \c p are inputs used to set up a modulus or
+ *       residue. These must be pointers to an array of limbs.
+ *     - \c T is a temporary storage area. The initial content of such a
+ *       parameter is ignored and the final content is unspecified.
+ *     - Some functions use different names, such as \c r for the residue.
+ * - **Bignum sizes**: bignum sizes are always expressed in limbs. Both
+ *   #mbedtls_mpi_mod_modulus and #mbedtls_mpi_mod_residue have a \c limbs
+ *   member storing its size. All bignum parameters must have the same
+ *   number of limbs as the modulus. All bignum sizes must be at least 1 and
+ *   must be significantly less than #SIZE_MAX. The behavior if a size is 0 is
+ *   undefined.
+ * - **Bignum representation**: the representation of inputs and outputs is
+ *   specified by the \c int_rep field of the modulus.
+ * - **Parameter ordering**: for bignum parameters, outputs come before inputs.
+ *   The modulus is passed after residues. Temporaries come last.
+ * - **Aliasing**: in general, output bignums may be aliased to one or more
+ *   inputs. Modulus values may not be aliased to any other parameter. Outputs
+ *   may not be aliased to one another. Temporaries may not be aliased to any
+ *   other parameter.
+ * - **Overlap**: apart from aliasing of residue pointers (where two residue
+ *   arguments are equal pointers), overlap is not supported and may result
+ *   in undefined behavior.
+ * - **Error handling**: functions generally check compatibility of input
+ *   sizes. Most functions will not check that input values are in canonical
+ *   form (i.e. that \c A < \c N), this is only checked during setup of a
+ *   residue structure.
+ * - **Modular representatives**: all functions expect inputs to be in the
+ *   range [0, \c N - 1] and guarantee outputs in the range [0, \c N - 1].
+ *   Residues are set up with an associated modulus, and operations are only
+ *   guaranteed to work if the modulus is associated with all residue
+ *   parameters. If a residue is passed with a modulus other than the one it
+ *   is associated with, then it may be out of range. If an input is out of
+ *   range, outputs are fully unspecified, though bignum values out of range
+ *   should not cause buffer overflows (beware that this is not extensively
+ *   tested).
+ */
+
+/*
+ *  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_BIGNUM_MOD_H
+#define MBEDTLS_BIGNUM_MOD_H
+
+#include "common.h"
+
+#if defined(MBEDTLS_BIGNUM_C)
+#include "mbedtls/bignum.h"
+#endif
+
+/** How residues associated with a modulus are represented.
+ *
+ * This also determines which fields of the modulus structure are valid and
+ * what their contents are (see #mbedtls_mpi_mod_modulus).
+ */
+typedef enum {
+    /** Representation not chosen (makes the modulus structure invalid). */
+    MBEDTLS_MPI_MOD_REP_INVALID    = 0,
+    /* Skip 1 as it is slightly easier to accidentally pass to functions. */
+    /** Montgomery representation. */
+    MBEDTLS_MPI_MOD_REP_MONTGOMERY = 2,
+    /** TODO: document this.
+     *
+     * Residues are in canonical representation.
+     */
+    MBEDTLS_MPI_MOD_REP_OPT_RED,
+} mbedtls_mpi_mod_rep_selector;
+
+/* Make mbedtls_mpi_mod_rep_selector and mbedtls_mpi_mod_ext_rep disjoint to
+ * make it easier to catch when they are accidentally swapped. */
+typedef enum {
+    MBEDTLS_MPI_MOD_EXT_REP_INVALID = 0,
+    MBEDTLS_MPI_MOD_EXT_REP_LE      = 8,
+    MBEDTLS_MPI_MOD_EXT_REP_BE
+} mbedtls_mpi_mod_ext_rep;
+
+typedef struct {
+    mbedtls_mpi_uint *p;
+    size_t limbs;
+} mbedtls_mpi_mod_residue;
+
+typedef struct {
+    mbedtls_mpi_uint const *rr;  /* The residue for 2^{2*n*biL} mod N */
+    mbedtls_mpi_uint mm;         /* Montgomery const for -N^{-1} mod 2^{ciL} */
+} mbedtls_mpi_mont_struct;
+
+typedef void *mbedtls_mpi_opt_red_struct;
+
+typedef struct {
+    const mbedtls_mpi_uint *p;
+    size_t limbs;                            // number of limbs
+    size_t bits;                             // bitlen of p
+    mbedtls_mpi_mod_rep_selector int_rep;    // selector to signal the active member of the union
+    union rep {
+        /* if int_rep == #MBEDTLS_MPI_MOD_REP_MONTGOMERY */
+        mbedtls_mpi_mont_struct mont;
+        /* if int_rep == #MBEDTLS_MPI_MOD_REP_OPT_RED */
+        mbedtls_mpi_opt_red_struct ored;
+    } rep;
+} mbedtls_mpi_mod_modulus;
+
+/** Setup a residue structure.
+ *
+ * The residue will be set up with the buffer \p p and modulus \p N.
+ *
+ * The memory pointed to by \p p will be used by the resulting residue structure.
+ * The value at the pointed-to memory will be the initial value of \p r and must
+ * hold a value that is less than the modulus. This value will be used as-is
+ * and interpreted according to the value of the `N->int_rep` field.
+ *
+ * The modulus \p N will be the modulus associated with \p r. The residue \p r
+ * should only be used in operations where the modulus is \p N.
+ *
+ * \param[out] r    The address of the residue to setup.
+ * \param[in] N     The address of the modulus related to \p r.
+ * \param[in] p     The address of the limb array containing the value of \p r.
+ *                  The memory pointed to by \p p will be used by \p r and must
+ *                  not be modified in any way until after
+ *                  mbedtls_mpi_mod_residue_release() is called. The data
+ *                  pointed to by \p p must be less than the modulus (the value
+ *                  pointed to by `N->p`) and already in the representation
+ *                  indicated by `N->int_rep`.
+ * \param p_limbs   The number of limbs of \p p. Must be the same as the number
+ *                  of limbs in the modulus \p N.
+ *
+ * \return      \c 0 if successful.
+ * \return      #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p p_limbs is less than the
+ *              limbs in \p N or if \p p is not less than \p N.
+ */
+int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r,
+                                  const mbedtls_mpi_mod_modulus *N,
+                                  mbedtls_mpi_uint *p,
+                                  size_t p_limbs);
+
+/** Unbind elements of a residue structure.
+ *
+ * This function removes the reference to the limb array that was passed to
+ * mbedtls_mpi_mod_residue_setup() to make it safe to free or use again.
+ *
+ * This function invalidates \p r and it must not be used until after
+ * mbedtls_mpi_mod_residue_setup() is called on it again.
+ *
+ * \param[out] r     The address of residue to release.
+ */
+void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r);
+
+/** Initialize a modulus structure.
+ *
+ * \param[out] N     The address of the modulus structure to initialize.
+ */
+void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N);
+
+/** Setup a modulus structure.
+ *
+ * \param[out] N    The address of the modulus structure to populate.
+ * \param[in] p     The address of the limb array storing the value of \p N.
+ *                  The memory pointed to by \p p will be used by \p N and must
+ *                  not be modified in any way until after
+ *                  mbedtls_mpi_mod_modulus_free() is called.
+ * \param p_limbs   The number of limbs of \p p.
+ * \param int_rep   The internal representation to be used for residues
+ *                  associated with \p N (see #mbedtls_mpi_mod_rep_selector).
+ *
+ * \return      \c 0 if successful.
+ * \return      #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p int_rep is invalid.
+ */
+int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,
+                                  const mbedtls_mpi_uint *p,
+                                  size_t p_limbs,
+                                  mbedtls_mpi_mod_rep_selector int_rep);
+
+/** Free elements of a modulus structure.
+ *
+ * This function frees any memory allocated by mbedtls_mpi_mod_modulus_setup().
+ *
+ * \warning This function does not free the limb array passed to
+ *          mbedtls_mpi_mod_modulus_setup() only removes the reference to it,
+ *          making it safe to free or to use it again.
+ *
+ * \param[in,out] N     The address of the modulus structure to free.
+ */
+void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N);
+
+/* BEGIN MERGE SLOT 1 */
+
+/* END MERGE SLOT 1 */
+
+/* BEGIN MERGE SLOT 2 */
+
+/** \brief  Multiply two residues, returning the residue modulo the specified
+ *          modulus.
+ *
+ * \note Currently handles the case when `N->int_rep` is
+ * MBEDTLS_MPI_MOD_REP_MONTGOMERY.
+ *
+ * The size of the operation is determined by \p N. \p A, \p B and \p X must
+ * all be associated with the modulus \p N and must all have the same number
+ * of limbs as \p N.
+ *
+ * \p X may be aliased to \p A or \p B, or even both, but may not overlap
+ * either otherwise. They may not alias \p N (since they must be in canonical
+ * form, they cannot == \p N).
+ *
+ * \param[out] X        The address of the result MPI. Must have the same
+ *                      number of limbs as \p N.
+ *                      On successful completion, \p X contains the result of
+ *                      the multiplication `A * B * R^-1` mod N where
+ *                      `R = 2^(biL * N->limbs)`.
+ * \param[in]  A        The address of the first MPI.
+ * \param[in]  B        The address of the second MPI.
+ * \param[in]  N        The address of the modulus. Used to perform a modulo
+ *                      operation on the result of the multiplication.
+ *
+ * \return      \c 0 if successful.
+ * \return      #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if all the parameters do not
+ *              have the same number of limbs or \p N is invalid.
+ * \return      #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X,
+                        const mbedtls_mpi_mod_residue *A,
+                        const mbedtls_mpi_mod_residue *B,
+                        const mbedtls_mpi_mod_modulus *N);
+
+/* END MERGE SLOT 2 */
+
+/* BEGIN MERGE SLOT 3 */
+/**
+ * \brief Perform a fixed-size modular subtraction.
+ *
+ * Calculate `A - B modulo N`.
+ *
+ * \p A, \p B and \p X must all have the same number of limbs as \p N.
+ *
+ * \p X may be aliased to \p A or \p B, or even both, but may not overlap
+ * either otherwise.
+ *
+ * \note This function does not check that \p A or \p B are in canonical
+ *       form (that is, are < \p N) - that will have been done by
+ *       mbedtls_mpi_mod_residue_setup().
+ *
+ * \param[out] X    The address of the result MPI. Must be initialized.
+ *                  Must have the same number of limbs as the modulus \p N.
+ * \param[in]  A    The address of the first MPI.
+ * \param[in]  B    The address of the second MPI.
+ * \param[in]  N    The address of the modulus. Used to perform a modulo
+ *                  operation on the result of the subtraction.
+ *
+ * \return          \c 0 if successful.
+ * \return          #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not
+ *                  have the correct number of limbs.
+ */
+int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X,
+                        const mbedtls_mpi_mod_residue *A,
+                        const mbedtls_mpi_mod_residue *B,
+                        const mbedtls_mpi_mod_modulus *N);
+
+/**
+ * \brief Perform modular inversion of an MPI with respect to a modulus \p N.
+ *
+ * \p A and \p X must be associated with the modulus \p N and will therefore
+ * have the same number of limbs as \p N.
+ *
+ * \p X may be aliased to \p A.
+ *
+ * \warning  Currently only supports prime moduli, but does not check for them.
+ *
+ * \param[out] X   The modular inverse of \p A with respect to \p N.
+ * \param[in] A    The number to calculate the modular inverse of.
+ *                 Must not be 0.
+ * \param[in] N    The modulus to use.
+ *
+ * \return         \c 0 if successful.
+ * \return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p A and \p N do not
+ *                 have the same number of limbs.
+ * \return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p A is zero.
+ * \return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough
+ *                 memory (needed for conversion to and from Mongtomery form
+ *                 when not in Montgomery form already, and for temporary use
+ *                 by the inversion calculation itself).
+ */
+
+int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X,
+                        const mbedtls_mpi_mod_residue *A,
+                        const mbedtls_mpi_mod_modulus *N);
+/* END MERGE SLOT 3 */
+
+/* BEGIN MERGE SLOT 4 */
+
+/* END MERGE SLOT 4 */
+
+/* BEGIN MERGE SLOT 5 */
+/**
+ * \brief Perform a fixed-size modular addition.
+ *
+ * Calculate `A + B modulo N`.
+ *
+ * \p A, \p B and \p X must all be associated with the modulus \p N and must
+ * all have the same number of limbs as \p N.
+ *
+ * \p X may be aliased to \p A or \p B, or even both, but may not overlap
+ * either otherwise.
+ *
+ * \note This function does not check that \p A or \p B are in canonical
+ *       form (that is, are < \p N) - that will have been done by
+ *       mbedtls_mpi_mod_residue_setup().
+ *
+ * \param[out] X    The address of the result residue. Must be initialized.
+ *                  Must have the same number of limbs as the modulus \p N.
+ * \param[in]  A    The address of the first input residue.
+ * \param[in]  B    The address of the second input residue.
+ * \param[in]  N    The address of the modulus. Used to perform a modulo
+ *                  operation on the result of the addition.
+ *
+ * \return          \c 0 if successful.
+ * \return          #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not
+ *                  have the correct number of limbs.
+ */
+int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X,
+                        const mbedtls_mpi_mod_residue *A,
+                        const mbedtls_mpi_mod_residue *B,
+                        const mbedtls_mpi_mod_modulus *N);
+/* END MERGE SLOT 5 */
+
+/* BEGIN MERGE SLOT 6 */
+
+/** Generate a random number uniformly in a range.
+ *
+ * This function generates a random number between \p min inclusive and
+ * \p N exclusive.
+ *
+ * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)
+ * when the RNG is a suitably parametrized instance of HMAC_DRBG
+ * and \p min is \c 1.
+ *
+ * \note           There are `N - min` possible outputs. The lower bound
+ *                 \p min can be reached, but the upper bound \p N cannot.
+ *
+ * \param X        The destination residue.
+ * \param min      The minimum value to return. It must be strictly smaller
+ *                 than \b N.
+ * \param N        The modulus.
+ *                 This is the upper bound of the output range, exclusive.
+ * \param f_rng    The RNG function to use. This must not be \c NULL.
+ * \param p_rng    The RNG parameter to be passed to \p f_rng.
+ *
+ * \return         \c 0 if successful.
+ * \return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was
+ *                 unable to find a suitable value within a limited number
+ *                 of attempts. This has a negligible probability if \p N
+ *                 is significantly larger than \p min, which is the case
+ *                 for all usual cryptographic applications.
+ */
+int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X,
+                           mbedtls_mpi_uint min,
+                           const mbedtls_mpi_mod_modulus *N,
+                           int (*f_rng)(void *, unsigned char *, size_t),
+                           void *p_rng);
+
+/* END MERGE SLOT 6 */
+
+/* BEGIN MERGE SLOT 7 */
+/** Read a residue from a byte buffer.
+ *
+ * The residue will be automatically converted to the internal representation
+ * based on the value of the `N->int_rep` field.
+ *
+ * The modulus \p N will be the modulus associated with \p r. The residue \p r
+ * should only be used in operations where the modulus is \p N or a modulus
+ * equivalent to \p N (in the sense that all their fields or memory pointed by
+ * their fields hold the same value).
+ *
+ * \param[out] r    The address of the residue. It must have exactly the same
+ *                  number of limbs as the modulus \p N.
+ * \param[in] N     The address of the modulus.
+ * \param[in] buf   The input buffer to import from.
+ * \param buflen    The length in bytes of \p buf.
+ * \param ext_rep   The endianness of the number in the input buffer.
+ *
+ * \return       \c 0 if successful.
+ * \return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p r isn't
+ *               large enough to hold the value in \p buf.
+ * \return       #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p ext_rep
+ *               is invalid or the value in the buffer is not less than \p N.
+ */
+int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r,
+                         const mbedtls_mpi_mod_modulus *N,
+                         const unsigned char *buf,
+                         size_t buflen,
+                         mbedtls_mpi_mod_ext_rep ext_rep);
+
+/** Write a residue into a byte buffer.
+ *
+ * The modulus \p N must be the modulus associated with \p r (see
+ * mbedtls_mpi_mod_residue_setup() and mbedtls_mpi_mod_read()).
+ *
+ * The residue will be automatically converted from the internal representation
+ * based on the value of `N->int_rep` field.
+ *
+ * \warning     If the buffer is smaller than `N->bits`, the number of
+ *              leading zeroes is leaked through timing. If \p r is
+ *              secret, the caller must ensure that \p buflen is at least
+ *              (`N->bits`+7)/8.
+ *
+ * \param[in] r     The address of the residue. It must have the same number of
+ *                  limbs as the modulus \p N. (\p r is an input parameter, but
+ *                  its value will be modified during execution and restored
+ *                  before the function returns.)
+ * \param[in] N     The address of the modulus associated with \p r.
+ * \param[out] buf  The output buffer to export to.
+ * \param buflen    The length in bytes of \p buf.
+ * \param ext_rep   The endianness in which the number should be written into
+ *                  the output buffer.
+ *
+ * \return       \c 0 if successful.
+ * \return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't
+ *               large enough to hold the value of \p r (without leading
+ *               zeroes).
+ * \return       #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p ext_rep is invalid.
+ * \return       #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough
+ *               memory for conversion. Can occur only for moduli with
+ *               MBEDTLS_MPI_MOD_REP_MONTGOMERY.
+ */
+int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r,
+                          const mbedtls_mpi_mod_modulus *N,
+                          unsigned char *buf,
+                          size_t buflen,
+                          mbedtls_mpi_mod_ext_rep ext_rep);
+/* END MERGE SLOT 7 */
+
+/* BEGIN MERGE SLOT 8 */
+
+/* END MERGE SLOT 8 */
+
+/* BEGIN MERGE SLOT 9 */
+
+/* END MERGE SLOT 9 */
+
+/* BEGIN MERGE SLOT 10 */
+
+/* END MERGE SLOT 10 */
+
+#endif /* MBEDTLS_BIGNUM_MOD_H */
diff --git a/lib/libmbedtls/mbedtls/library/bignum_mod_raw.c b/lib/libmbedtls/mbedtls/library/bignum_mod_raw.c
new file mode 100644
index 0000000..bf0cb25
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/bignum_mod_raw.c
@@ -0,0 +1,306 @@
+/*
+ *  Low-level modular bignum functions
+ *
+ *  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.
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_BIGNUM_C)
+
+#include <string.h>
+
+#include "mbedtls/error.h"
+#include "mbedtls/platform_util.h"
+
+#include "mbedtls/platform.h"
+
+#include "bignum_core.h"
+#include "bignum_mod_raw.h"
+#include "bignum_mod.h"
+#include "constant_time_internal.h"
+
+#include "bignum_mod_raw_invasive.h"
+
+void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X,
+                                     const mbedtls_mpi_uint *A,
+                                     const mbedtls_mpi_mod_modulus *N,
+                                     unsigned char assign)
+{
+    mbedtls_mpi_core_cond_assign(X, A, N->limbs, assign);
+}
+
+void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X,
+                                   mbedtls_mpi_uint *Y,
+                                   const mbedtls_mpi_mod_modulus *N,
+                                   unsigned char swap)
+{
+    mbedtls_mpi_core_cond_swap(X, Y, N->limbs, swap);
+}
+
+int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X,
+                             const mbedtls_mpi_mod_modulus *N,
+                             const unsigned char *input,
+                             size_t input_length,
+                             mbedtls_mpi_mod_ext_rep ext_rep)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    switch (ext_rep) {
+        case MBEDTLS_MPI_MOD_EXT_REP_LE:
+            ret = mbedtls_mpi_core_read_le(X, N->limbs,
+                                           input, input_length);
+            break;
+        case MBEDTLS_MPI_MOD_EXT_REP_BE:
+            ret = mbedtls_mpi_core_read_be(X, N->limbs,
+                                           input, input_length);
+            break;
+        default:
+            return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+
+    if (ret != 0) {
+        goto cleanup;
+    }
+
+    if (!mbedtls_mpi_core_lt_ct(X, N->p, N->limbs)) {
+        ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+        goto cleanup;
+    }
+
+cleanup:
+
+    return ret;
+}
+
+int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A,
+                              const mbedtls_mpi_mod_modulus *N,
+                              unsigned char *output,
+                              size_t output_length,
+                              mbedtls_mpi_mod_ext_rep ext_rep)
+{
+    switch (ext_rep) {
+        case MBEDTLS_MPI_MOD_EXT_REP_LE:
+            return mbedtls_mpi_core_write_le(A, N->limbs,
+                                             output, output_length);
+        case MBEDTLS_MPI_MOD_EXT_REP_BE:
+            return mbedtls_mpi_core_write_be(A, N->limbs,
+                                             output, output_length);
+        default:
+            return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+}
+
+/* BEGIN MERGE SLOT 1 */
+
+/* END MERGE SLOT 1 */
+
+/* BEGIN MERGE SLOT 2 */
+
+void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X,
+                             const mbedtls_mpi_uint *A,
+                             const mbedtls_mpi_uint *B,
+                             const mbedtls_mpi_mod_modulus *N)
+{
+    mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, A, B, N->limbs);
+
+    (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
+}
+
+#if defined(MBEDTLS_TEST_HOOKS)
+
+MBEDTLS_STATIC_TESTABLE
+void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X,
+                                             const mbedtls_mpi_mod_modulus *N)
+{
+    mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
+
+    (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
+}
+
+#endif /* MBEDTLS_TEST_HOOKS */
+
+void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X,
+                             const mbedtls_mpi_uint *A,
+                             const mbedtls_mpi_uint *B,
+                             const mbedtls_mpi_mod_modulus *N,
+                             mbedtls_mpi_uint *T)
+{
+    mbedtls_mpi_core_montmul(X, A, B, N->limbs, N->p, N->limbs,
+                             N->rep.mont.mm, T);
+}
+
+/* END MERGE SLOT 2 */
+
+/* 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 */
+
+/* END MERGE SLOT 4 */
+
+/* BEGIN MERGE SLOT 5 */
+void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X,
+                             const mbedtls_mpi_uint *A,
+                             const mbedtls_mpi_uint *B,
+                             const mbedtls_mpi_mod_modulus *N)
+{
+    mbedtls_mpi_uint carry, borrow;
+    carry  = mbedtls_mpi_core_add(X, A, B, N->limbs);
+    borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
+    (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) (carry ^ borrow));
+}
+/* END MERGE SLOT 5 */
+
+/* BEGIN MERGE SLOT 6 */
+
+int mbedtls_mpi_mod_raw_canonical_to_modulus_rep(
+    mbedtls_mpi_uint *X,
+    const mbedtls_mpi_mod_modulus *N)
+{
+    switch (N->int_rep) {
+        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
+            return mbedtls_mpi_mod_raw_to_mont_rep(X, N);
+        case MBEDTLS_MPI_MOD_REP_OPT_RED:
+            return 0;
+        default:
+            return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+}
+
+int mbedtls_mpi_mod_raw_modulus_to_canonical_rep(
+    mbedtls_mpi_uint *X,
+    const mbedtls_mpi_mod_modulus *N)
+{
+    switch (N->int_rep) {
+        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
+            return mbedtls_mpi_mod_raw_from_mont_rep(X, N);
+        case MBEDTLS_MPI_MOD_REP_OPT_RED:
+            return 0;
+        default:
+            return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+}
+
+int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X,
+                               mbedtls_mpi_uint min,
+                               const mbedtls_mpi_mod_modulus *N,
+                               int (*f_rng)(void *, unsigned char *, size_t),
+                               void *p_rng)
+{
+    int ret = mbedtls_mpi_core_random(X, min, N->p, N->limbs, f_rng, p_rng);
+    if (ret != 0) {
+        return ret;
+    }
+    return mbedtls_mpi_mod_raw_canonical_to_modulus_rep(X, N);
+}
+
+/* END MERGE SLOT 6 */
+
+/* BEGIN MERGE SLOT 7 */
+int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X,
+                                    const mbedtls_mpi_mod_modulus *N)
+{
+    mbedtls_mpi_uint *T;
+    const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs);
+
+    if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) {
+        return MBEDTLS_ERR_MPI_ALLOC_FAILED;
+    }
+
+    mbedtls_mpi_core_to_mont_rep(X, X, N->p, N->limbs,
+                                 N->rep.mont.mm, N->rep.mont.rr, T);
+
+    mbedtls_platform_zeroize(T, t_limbs * ciL);
+    mbedtls_free(T);
+    return 0;
+}
+
+int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X,
+                                      const mbedtls_mpi_mod_modulus *N)
+{
+    const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs);
+    mbedtls_mpi_uint *T;
+
+    if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) {
+        return MBEDTLS_ERR_MPI_ALLOC_FAILED;
+    }
+
+    mbedtls_mpi_core_from_mont_rep(X, X, N->p, N->limbs, N->rep.mont.mm, T);
+
+    mbedtls_platform_zeroize(T, t_limbs * ciL);
+    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 *N)
+{
+    mbedtls_mpi_core_sub(X, N->p, A, N->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, N->p, N->limbs);
+    (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) borrow);
+}
+/* END MERGE SLOT 7 */
+
+/* BEGIN MERGE SLOT 8 */
+
+/* END MERGE SLOT 8 */
+
+/* BEGIN MERGE SLOT 9 */
+
+/* END MERGE SLOT 9 */
+
+/* BEGIN MERGE SLOT 10 */
+
+/* END MERGE SLOT 10 */
+
+#endif /* MBEDTLS_BIGNUM_C */
diff --git a/lib/libmbedtls/mbedtls/library/bignum_mod_raw.h b/lib/libmbedtls/mbedtls/library/bignum_mod_raw.h
new file mode 100644
index 0000000..a32500f
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/bignum_mod_raw.h
@@ -0,0 +1,464 @@
+/**
+ *  Low-level modular bignum functions
+ *
+ *  This interface should only be used by the higher-level modular bignum
+ *  module (bignum_mod.c) and the ECP module (ecp.c, ecp_curves.c). All other
+ *  modules should use the high-level modular bignum interface (bignum_mod.h)
+ *  or the legacy bignum interface (bignum.h).
+ *
+ * This is a low-level interface to operations on integers modulo which
+ * has no protection against passing invalid arguments such as arrays of
+ * the wrong size. The functions in bignum_mod.h provide a higher-level
+ * interface that includes protections against accidental misuse, at the
+ * expense of code size and sometimes more cumbersome memory management.
+ *
+ * The functions in this module obey the following conventions unless
+ * explicitly indicated otherwise:
+ * - **Modulus parameters**: the modulus is passed as a pointer to a structure
+ *   of type #mbedtls_mpi_mod_modulus. The structure must be set up with an
+ *   array of limbs storing the bignum value of the modulus. The modulus must
+ *   be odd and is assumed to have no leading zeroes. The modulus is usually
+ *   named \c N and is usually input-only.
+ * - **Bignum parameters**: Bignums are passed as pointers to an array of
+ *   limbs. A limb has the type #mbedtls_mpi_uint. Unless otherwise specified:
+ *     - Bignum parameters called \c A, \c B, ... are inputs, and are not
+ *       modified by the function.
+ *     - Bignum parameters called \c X, \c Y are outputs or input-output.
+ *       The initial content of output-only parameters is ignored.
+ *     - \c T is a temporary storage area. The initial content of such a
+ *       parameter is ignored and the final content is unspecified.
+ * - **Bignum sizes**: bignum sizes are usually expressed by the \c limbs
+ *   member of the modulus argument. All bignum parameters must have the same
+ *   number of limbs as the modulus. All bignum sizes must be at least 1 and
+ *   must be significantly less than #SIZE_MAX. The behavior if a size is 0 is
+ *   undefined.
+ * - **Bignum representation**: the representation of inputs and outputs is
+ *   specified by the \c int_rep field of the modulus for arithmetic
+ *   functions. Utility functions may allow for different representation.
+ * - **Parameter ordering**: for bignum parameters, outputs come before inputs.
+ *   The modulus is passed after other bignum input parameters. Temporaries
+ *   come last.
+ * - **Aliasing**: in general, output bignums may be aliased to one or more
+ *   inputs. Modulus values may not be aliased to any other parameter. Outputs
+ *   may not be aliased to one another. Temporaries may not be aliased to any
+ *   other parameter.
+ * - **Overlap**: apart from aliasing of limb array pointers (where two
+ *   arguments are equal pointers), overlap is not supported and may result
+ *   in undefined behavior.
+ * - **Error handling**: This is a low-level module. Functions generally do not
+ *   try to protect against invalid arguments such as nonsensical sizes or
+ *   null pointers. Note that passing bignums with a different size than the
+ *   modulus may lead to buffer overflows. Some functions which allocate
+ *   memory or handle reading/writing of bignums will return an error if
+ *   memory allocation fails or if buffer sizes are invalid.
+ * - **Modular representatives**: all functions expect inputs to be in the
+ *   range [0, \c N - 1] and guarantee outputs in the range [0, \c N - 1]. If
+ *   an input is out of range, outputs are fully unspecified, though bignum
+ *   values out of range should not cause buffer overflows (beware that this is
+ *   not extensively tested).
+ */
+
+/*
+ *  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_BIGNUM_MOD_RAW_H
+#define MBEDTLS_BIGNUM_MOD_RAW_H
+
+#include "common.h"
+
+#if defined(MBEDTLS_BIGNUM_C)
+#include "mbedtls/bignum.h"
+#endif
+
+#include "bignum_mod.h"
+
+/**
+ * \brief   Perform a safe conditional copy of an MPI which doesn't reveal
+ *          whether the assignment was done or not.
+ *
+ * The size to copy is determined by \p N.
+ *
+ * \param[out] X        The address of the destination MPI.
+ *                      This must be initialized. Must have enough limbs to
+ *                      store the full value of \p A.
+ * \param[in]  A        The address of the source MPI. This must be initialized.
+ * \param[in]  N        The address of the modulus related to \p X and \p A.
+ * \param      assign   The condition deciding whether to perform the
+ *                      assignment or not. Must be either 0 or 1:
+ *                      * \c 1: Perform the assignment `X = A`.
+ *                      * \c 0: Keep the original value of \p X.
+ *
+ * \note           This function avoids leaking any information about whether
+ *                 the assignment was done or not.
+ *
+ * \warning        If \p assign is neither 0 nor 1, the result of this function
+ *                 is indeterminate, and the resulting value in \p X might be
+ *                 neither its original value nor the value in \p A.
+ */
+void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X,
+                                     const mbedtls_mpi_uint *A,
+                                     const mbedtls_mpi_mod_modulus *N,
+                                     unsigned char assign);
+
+/**
+ * \brief   Perform a safe conditional swap of two MPIs which doesn't reveal
+ *          whether the swap was done or not.
+ *
+ * The size to swap is determined by \p N.
+ *
+ * \param[in,out] X     The address of the first MPI. This must be initialized.
+ * \param[in,out] Y     The address of the second MPI. This must be initialized.
+ * \param[in]     N     The address of the modulus related to \p X and \p Y.
+ * \param         swap  The condition deciding whether to perform
+ *                      the swap or not. Must be either 0 or 1:
+ *                      * \c 1: Swap the values of \p X and \p Y.
+ *                      * \c 0: Keep the original values of \p X and \p Y.
+ *
+ * \note           This function avoids leaking any information about whether
+ *                 the swap was done or not.
+ *
+ * \warning        If \p swap is neither 0 nor 1, the result of this function
+ *                 is indeterminate, and both \p X and \p Y might end up with
+ *                 values different to either of the original ones.
+ */
+void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X,
+                                   mbedtls_mpi_uint *Y,
+                                   const mbedtls_mpi_mod_modulus *N,
+                                   unsigned char swap);
+
+/** Import X from unsigned binary data.
+ *
+ * The MPI needs to have enough limbs to store the full value (including any
+ * most significant zero bytes in the input).
+ *
+ * \param[out] X        The address of the MPI. The size is determined by \p N.
+ *                      (In particular, it must have at least as many limbs as
+ *                      the modulus \p N.)
+ * \param[in] N         The address of the modulus related to \p X.
+ * \param[in] input     The input buffer to import from.
+ * \param input_length  The length in bytes of \p input.
+ * \param ext_rep       The endianness of the number in the input buffer.
+ *
+ * \return       \c 0 if successful.
+ * \return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't
+ *               large enough to hold the value in \p input.
+ * \return       #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the external representation
+ *               of \p N is invalid or \p X is not less than \p N.
+ */
+int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X,
+                             const mbedtls_mpi_mod_modulus *N,
+                             const unsigned char *input,
+                             size_t input_length,
+                             mbedtls_mpi_mod_ext_rep ext_rep);
+
+/** Export A into unsigned binary data.
+ *
+ * \param[in] A         The address of the MPI. The size is determined by \p N.
+ *                      (In particular, it must have at least as many limbs as
+ *                      the modulus \p N.)
+ * \param[in] N         The address of the modulus related to \p A.
+ * \param[out] output   The output buffer to export to.
+ * \param output_length The length in bytes of \p output.
+ * \param ext_rep       The endianness in which the number should be written into the output buffer.
+ *
+ * \return       \c 0 if successful.
+ * \return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't
+ *               large enough to hold the value of \p A.
+ * \return       #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the external representation
+ *               of \p N is invalid.
+ */
+int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A,
+                              const mbedtls_mpi_mod_modulus *N,
+                              unsigned char *output,
+                              size_t output_length,
+                              mbedtls_mpi_mod_ext_rep ext_rep);
+
+/* BEGIN MERGE SLOT 1 */
+
+/* END MERGE SLOT 1 */
+
+/* BEGIN MERGE SLOT 2 */
+
+/** \brief  Subtract two MPIs, returning the residue modulo the specified
+ *          modulus.
+ *
+ * The size of the operation is determined by \p N. \p A and \p B must have
+ * the same number of limbs as \p N.
+ *
+ * \p X may be aliased to \p A or \p B, or even both, but may not overlap
+ * either otherwise.
+ *
+ * \param[out] X        The address of the result MPI.
+ *                      This must be initialized. Must have enough limbs to
+ *                      store the full value of the result.
+ * \param[in]  A        The address of the first MPI. This must be initialized.
+ * \param[in]  B        The address of the second MPI. This must be initialized.
+ * \param[in]  N        The address of the modulus. Used to perform a modulo
+ *                      operation on the result of the subtraction.
+ */
+void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X,
+                             const mbedtls_mpi_uint *A,
+                             const mbedtls_mpi_uint *B,
+                             const mbedtls_mpi_mod_modulus *N);
+
+/** \brief  Multiply two MPIs, returning the residue modulo the specified
+ *          modulus.
+ *
+ * \note Currently handles the case when `N->int_rep` is
+ * MBEDTLS_MPI_MOD_REP_MONTGOMERY.
+ *
+ * The size of the operation is determined by \p N. \p A, \p B and \p X must
+ * all be associated with the modulus \p N and must all have the same number
+ * of limbs as \p N.
+ *
+ * \p X may be aliased to \p A or \p B, or even both, but may not overlap
+ * either otherwise. They may not alias \p N (since they must be in canonical
+ * form, they cannot == \p N).
+ *
+ * \param[out] X        The address of the result MPI. Must have the same
+ *                      number of limbs as \p N.
+ *                      On successful completion, \p X contains the result of
+ *                      the multiplication `A * B * R^-1` mod N where
+ *                      `R = 2^(biL * N->limbs)`.
+ * \param[in]  A        The address of the first MPI.
+ * \param[in]  B        The address of the second MPI.
+ * \param[in]  N        The address of the modulus. Used to perform a modulo
+ *                      operation on the result of the multiplication.
+ * \param[in,out] T     Temporary storage of size at least 2 * N->limbs + 1
+ *                      limbs. Its initial content is unused and
+ *                      its final content is indeterminate.
+ *                      It must not alias or otherwise overlap any of the
+ *                      other parameters.
+ */
+void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X,
+                             const mbedtls_mpi_uint *A,
+                             const mbedtls_mpi_uint *B,
+                             const mbedtls_mpi_mod_modulus *N,
+                             mbedtls_mpi_uint *T);
+
+/* END MERGE SLOT 2 */
+
+/* BEGIN MERGE SLOT 3 */
+
+/**
+ * \brief          Returns the number of limbs of working memory required for
+ *                 a call to `mbedtls_mpi_mod_raw_inv_prime()`.
+ *
+ * \note           This will always be at least
+ *                 `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`,
+ *                 i.e. sufficient for a call to `mbedtls_mpi_core_montmul()`.
+ *
+ * \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 */
+
+/* END MERGE SLOT 4 */
+
+/* BEGIN MERGE SLOT 5 */
+/**
+ * \brief Perform a known-size modular addition.
+ *
+ * Calculate `A + B modulo N`.
+ *
+ * The number of limbs in each operand, and the result, is given by the
+ * modulus \p N.
+ *
+ * \p X may be aliased to \p A or \p B, or even both, but may not overlap
+ * either otherwise.
+ *
+ * \param[out] X    The result of the modular addition.
+ * \param[in] A     Little-endian presentation of the left operand. This
+ *                  must be smaller than \p N.
+ * \param[in] B     Little-endian presentation of the right operand. This
+ *                  must be smaller than \p N.
+ * \param[in] N     The address of the modulus.
+ */
+void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X,
+                             const mbedtls_mpi_uint *A,
+                             const mbedtls_mpi_uint *B,
+                             const mbedtls_mpi_mod_modulus *N);
+/* END MERGE SLOT 5 */
+
+/* BEGIN MERGE SLOT 6 */
+
+/** Convert an MPI from canonical representation (little-endian limb array)
+ * to the representation associated with the modulus.
+ *
+ * \param[in,out] X The limb array to convert.
+ *                  It must have as many limbs as \p N.
+ *                  It is converted in place.
+ *                  If this function returns an error, the content of \p X
+ *                  is unspecified.
+ * \param[in] N     The modulus structure.
+ *
+ * \return          \c 0 if successful.
+ *                  Otherwise an \c MBEDTLS_ERR_MPI_xxx error code.
+ */
+int mbedtls_mpi_mod_raw_canonical_to_modulus_rep(
+    mbedtls_mpi_uint *X,
+    const mbedtls_mpi_mod_modulus *N);
+
+/** Convert an MPI from the representation associated with the modulus
+ * to canonical representation (little-endian limb array).
+ *
+ * \param[in,out] X The limb array to convert.
+ *                  It must have as many limbs as \p N.
+ *                  It is converted in place.
+ *                  If this function returns an error, the content of \p X
+ *                  is unspecified.
+ * \param[in] N     The modulus structure.
+ *
+ * \return          \c 0 if successful.
+ *                  Otherwise an \c MBEDTLS_ERR_MPI_xxx error code.
+ */
+int mbedtls_mpi_mod_raw_modulus_to_canonical_rep(
+    mbedtls_mpi_uint *X,
+    const mbedtls_mpi_mod_modulus *N);
+
+/** Generate a random number uniformly in a range.
+ *
+ * This function generates a random number between \p min inclusive and
+ * \p N exclusive.
+ *
+ * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)
+ * when the RNG is a suitably parametrized instance of HMAC_DRBG
+ * and \p min is \c 1.
+ *
+ * \note           There are `N - min` possible outputs. The lower bound
+ *                 \p min can be reached, but the upper bound \p N cannot.
+ *
+ * \param X        The destination MPI, in canonical representation modulo \p N.
+ *                 It must not be aliased with \p N or otherwise overlap it.
+ * \param min      The minimum value to return. It must be strictly smaller
+ *                 than \b N.
+ * \param N        The modulus.
+ *                 This is the upper bound of the output range, exclusive.
+ * \param f_rng    The RNG function to use. This must not be \c NULL.
+ * \param p_rng    The RNG parameter to be passed to \p f_rng.
+ *
+ * \return         \c 0 if successful.
+ * \return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was
+ *                 unable to find a suitable value within a limited number
+ *                 of attempts. This has a negligible probability if \p N
+ *                 is significantly larger than \p min, which is the case
+ *                 for all usual cryptographic applications.
+ */
+int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X,
+                               mbedtls_mpi_uint min,
+                               const mbedtls_mpi_mod_modulus *N,
+                               int (*f_rng)(void *, unsigned char *, size_t),
+                               void *p_rng);
+
+/* END MERGE SLOT 6 */
+
+/* BEGIN MERGE SLOT 7 */
+/** Convert an MPI into Montgomery form.
+ *
+ * \param X      The address of the MPI.
+ *               Must have the same number of limbs as \p N.
+ * \param N      The address of the modulus, which gives the size of
+ *               the base `R` = 2^(biL*N->limbs).
+ *
+ * \return       \c 0 if successful.
+ */
+int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X,
+                                    const mbedtls_mpi_mod_modulus *N);
+
+/** Convert an MPI back from Montgomery representation.
+ *
+ * \param X      The address of the MPI.
+ *               Must have the same number of limbs as \p N.
+ * \param N      The address of the modulus, which gives the size of
+ *               the base `R`= 2^(biL*N->limbs).
+ *
+ * \return       \c 0 if successful.
+ */
+int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X,
+                                      const mbedtls_mpi_mod_modulus *N);
+
+/** \brief  Perform fixed width modular negation.
+ *
+ * The size of the operation is determined by \p N. \p A must have
+ * the same number of limbs as \p N.
+ *
+ * \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 N.
+ * \param[in] N         The modulus to use.
+ */
+void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X,
+                             const mbedtls_mpi_uint *A,
+                             const mbedtls_mpi_mod_modulus *N);
+/* END MERGE SLOT 7 */
+
+/* BEGIN MERGE SLOT 8 */
+
+/* END MERGE SLOT 8 */
+
+/* BEGIN MERGE SLOT 9 */
+
+/* END MERGE SLOT 9 */
+
+/* BEGIN MERGE SLOT 10 */
+
+/* END MERGE SLOT 10 */
+
+#endif /* MBEDTLS_BIGNUM_MOD_RAW_H */
diff --git a/lib/libmbedtls/mbedtls/library/bignum_mod_raw_invasive.h b/lib/libmbedtls/mbedtls/library/bignum_mod_raw_invasive.h
new file mode 100644
index 0000000..ead8394
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/bignum_mod_raw_invasive.h
@@ -0,0 +1,46 @@
+/**
+ * \file bignum_mod_raw_invasive.h
+ *
+ * \brief Function declarations for invasive functions of Low-level
+ *        modular bignum.
+ */
+/**
+ *  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_BIGNUM_MOD_RAW_INVASIVE_H
+#define MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H
+
+#include "common.h"
+#include "mbedtls/bignum.h"
+#include "bignum_mod.h"
+
+#if defined(MBEDTLS_TEST_HOOKS)
+
+/** Convert the result of a quasi-reduction to its canonical representative.
+ *
+ * \param[in,out] X     The address of the MPI to be converted. Must have the
+ *                      same number of limbs as \p N. The input value must
+ *                      be in range 0 <= X < 2N.
+ * \param[in]     N     The address of the modulus.
+ */
+MBEDTLS_STATIC_TESTABLE
+void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X,
+                                             const mbedtls_mpi_mod_modulus *N);
+
+#endif /* MBEDTLS_TEST_HOOKS */
+
+#endif /* MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H */
diff --git a/lib/libmbedtls/mbedtls/library/blowfish.c b/lib/libmbedtls/mbedtls/library/blowfish.c
deleted file mode 100644
index 621e9f7..0000000
--- a/lib/libmbedtls/mbedtls/library/blowfish.c
+++ /dev/null
@@ -1,667 +0,0 @@
-/*
- *  Blowfish implementation
- *
- *  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.
- */
-/*
- *  The Blowfish block cipher was designed by Bruce Schneier in 1993.
- *  http://www.schneier.com/blowfish.html
- *  http://en.wikipedia.org/wiki/Blowfish_%28cipher%29
- *
- */
-
-#include "common.h"
-
-#if defined(MBEDTLS_BLOWFISH_C)
-
-#include "mbedtls/blowfish.h"
-#include "mbedtls/platform_util.h"
-
-#include <string.h>
-
-#if !defined(MBEDTLS_BLOWFISH_ALT)
-
-/* Parameter validation macros */
-#define BLOWFISH_VALIDATE_RET( cond )                                       \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA )
-#define BLOWFISH_VALIDATE( cond )                                           \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
-
-static const uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2] = {
-        0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L,
-        0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L,
-        0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL,
-        0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L,
-        0x9216D5D9L, 0x8979FB1BL
-};
-
-/* declarations of data at the end of this file */
-static const uint32_t S[4][256];
-
-static uint32_t F( mbedtls_blowfish_context *ctx, uint32_t x )
-{
-   unsigned short a, b, c, d;
-   uint32_t  y;
-
-   d = MBEDTLS_BYTE_0( x );
-   x >>= 8;
-   c = MBEDTLS_BYTE_0( x );
-   x >>= 8;
-   b = MBEDTLS_BYTE_0( x );
-   x >>= 8;
-   a = MBEDTLS_BYTE_0( x );
-   y = ctx->S[0][a] + ctx->S[1][b];
-   y = y ^ ctx->S[2][c];
-   y = y + ctx->S[3][d];
-
-   return( y );
-}
-
-static void blowfish_enc( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr )
-{
-    uint32_t  Xl, Xr, temp;
-    short i;
-
-    Xl = *xl;
-    Xr = *xr;
-
-    for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS; ++i )
-    {
-        Xl = Xl ^ ctx->P[i];
-        Xr = F( ctx, Xl ) ^ Xr;
-
-        temp = Xl;
-        Xl = Xr;
-        Xr = temp;
-    }
-
-    temp = Xl;
-    Xl = Xr;
-    Xr = temp;
-
-    Xr = Xr ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS];
-    Xl = Xl ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS + 1];
-
-    *xl = Xl;
-    *xr = Xr;
-}
-
-static void blowfish_dec( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr )
-{
-    uint32_t  Xl, Xr, temp;
-    short i;
-
-    Xl = *xl;
-    Xr = *xr;
-
-    for( i = MBEDTLS_BLOWFISH_ROUNDS + 1; i > 1; --i )
-    {
-        Xl = Xl ^ ctx->P[i];
-        Xr = F( ctx, Xl ) ^ Xr;
-
-        temp = Xl;
-        Xl = Xr;
-        Xr = temp;
-    }
-
-    temp = Xl;
-    Xl = Xr;
-    Xr = temp;
-
-    Xr = Xr ^ ctx->P[1];
-    Xl = Xl ^ ctx->P[0];
-
-    *xl = Xl;
-    *xr = Xr;
-}
-
-void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx )
-{
-    BLOWFISH_VALIDATE( ctx != NULL );
-    memset( ctx, 0, sizeof( mbedtls_blowfish_context ) );
-}
-
-void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx )
-{
-    if( ctx == NULL )
-        return;
-
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_blowfish_context ) );
-}
-
-/*
- * Blowfish key schedule
- */
-int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx,
-                             const unsigned char *key,
-                             unsigned int keybits )
-{
-    unsigned int i, j, k;
-    uint32_t data, datal, datar;
-    BLOWFISH_VALIDATE_RET( ctx != NULL );
-    BLOWFISH_VALIDATE_RET( key != NULL );
-
-    if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS    ||
-        keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS    ||
-        keybits % 8 != 0 )
-    {
-        return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA );
-    }
-
-    keybits >>= 3;
-
-    for( i = 0; i < 4; i++ )
-    {
-        for( j = 0; j < 256; j++ )
-            ctx->S[i][j] = S[i][j];
-    }
-
-    j = 0;
-    for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; ++i )
-    {
-        data = 0x00000000;
-        for( k = 0; k < 4; ++k )
-        {
-            data = ( data << 8 ) | key[j++];
-            if( j >= keybits )
-                j = 0;
-        }
-        ctx->P[i] = P[i] ^ data;
-    }
-
-    datal = 0x00000000;
-    datar = 0x00000000;
-
-    for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; i += 2 )
-    {
-        blowfish_enc( ctx, &datal, &datar );
-        ctx->P[i] = datal;
-        ctx->P[i + 1] = datar;
-    }
-
-    for( i = 0; i < 4; i++ )
-    {
-       for( j = 0; j < 256; j += 2 )
-       {
-            blowfish_enc( ctx, &datal, &datar );
-            ctx->S[i][j] = datal;
-            ctx->S[i][j + 1] = datar;
-        }
-    }
-    return( 0 );
-}
-
-/*
- * Blowfish-ECB block encryption/decryption
- */
-int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx,
-                    int mode,
-                    const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE],
-                    unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] )
-{
-    uint32_t X0, X1;
-    BLOWFISH_VALIDATE_RET( ctx != NULL );
-    BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT ||
-                           mode == MBEDTLS_BLOWFISH_DECRYPT );
-    BLOWFISH_VALIDATE_RET( input  != NULL );
-    BLOWFISH_VALIDATE_RET( output != NULL );
-
-    X0 = MBEDTLS_GET_UINT32_BE( input,  0 );
-    X1 = MBEDTLS_GET_UINT32_BE( input,  4 );
-
-    if( mode == MBEDTLS_BLOWFISH_DECRYPT )
-    {
-        blowfish_dec( ctx, &X0, &X1 );
-    }
-    else /* MBEDTLS_BLOWFISH_ENCRYPT */
-    {
-        blowfish_enc( ctx, &X0, &X1 );
-    }
-
-    MBEDTLS_PUT_UINT32_BE( X0, output,  0 );
-    MBEDTLS_PUT_UINT32_BE( X1, output,  4 );
-
-    return( 0 );
-}
-
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-/*
- * Blowfish-CBC buffer encryption/decryption
- */
-int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx,
-                    int mode,
-                    size_t length,
-                    unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE],
-                    const unsigned char *input,
-                    unsigned char *output )
-{
-    int i;
-    unsigned char temp[MBEDTLS_BLOWFISH_BLOCKSIZE];
-    BLOWFISH_VALIDATE_RET( ctx != NULL );
-    BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT ||
-                           mode == MBEDTLS_BLOWFISH_DECRYPT );
-    BLOWFISH_VALIDATE_RET( iv != NULL );
-    BLOWFISH_VALIDATE_RET( length == 0 || input  != NULL );
-    BLOWFISH_VALIDATE_RET( length == 0 || output != NULL );
-
-    if( length % MBEDTLS_BLOWFISH_BLOCKSIZE )
-        return( MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH );
-
-    if( mode == MBEDTLS_BLOWFISH_DECRYPT )
-    {
-        while( length > 0 )
-        {
-            memcpy( temp, input, MBEDTLS_BLOWFISH_BLOCKSIZE );
-            mbedtls_blowfish_crypt_ecb( ctx, mode, input, output );
-
-            for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE;i++ )
-                output[i] = (unsigned char)( output[i] ^ iv[i] );
-
-            memcpy( iv, temp, MBEDTLS_BLOWFISH_BLOCKSIZE );
-
-            input  += MBEDTLS_BLOWFISH_BLOCKSIZE;
-            output += MBEDTLS_BLOWFISH_BLOCKSIZE;
-            length -= MBEDTLS_BLOWFISH_BLOCKSIZE;
-        }
-    }
-    else
-    {
-        while( length > 0 )
-        {
-            for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE; i++ )
-                output[i] = (unsigned char)( input[i] ^ iv[i] );
-
-            mbedtls_blowfish_crypt_ecb( ctx, mode, output, output );
-            memcpy( iv, output, MBEDTLS_BLOWFISH_BLOCKSIZE );
-
-            input  += MBEDTLS_BLOWFISH_BLOCKSIZE;
-            output += MBEDTLS_BLOWFISH_BLOCKSIZE;
-            length -= MBEDTLS_BLOWFISH_BLOCKSIZE;
-        }
-    }
-
-    return( 0 );
-}
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-
-#if defined(MBEDTLS_CIPHER_MODE_CFB)
-/*
- * Blowfish CFB buffer encryption/decryption
- */
-int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx,
-                       int mode,
-                       size_t length,
-                       size_t *iv_off,
-                       unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE],
-                       const unsigned char *input,
-                       unsigned char *output )
-{
-    int c;
-    size_t n;
-
-    BLOWFISH_VALIDATE_RET( ctx != NULL );
-    BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT ||
-                           mode == MBEDTLS_BLOWFISH_DECRYPT );
-    BLOWFISH_VALIDATE_RET( iv     != NULL );
-    BLOWFISH_VALIDATE_RET( iv_off != NULL );
-    BLOWFISH_VALIDATE_RET( length == 0 || input  != NULL );
-    BLOWFISH_VALIDATE_RET( length == 0 || output != NULL );
-
-    n = *iv_off;
-    if( n >= 8 )
-        return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA );
-
-    if( mode == MBEDTLS_BLOWFISH_DECRYPT )
-    {
-        while( length-- )
-        {
-            if( n == 0 )
-                mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv );
-
-            c = *input++;
-            *output++ = (unsigned char)( c ^ iv[n] );
-            iv[n] = (unsigned char) c;
-
-            n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE;
-        }
-    }
-    else
-    {
-        while( length-- )
-        {
-            if( n == 0 )
-                mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv );
-
-            iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
-
-            n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE;
-        }
-    }
-
-    *iv_off = n;
-
-    return( 0 );
-}
-#endif /*MBEDTLS_CIPHER_MODE_CFB */
-
-#if defined(MBEDTLS_CIPHER_MODE_CTR)
-/*
- * Blowfish CTR buffer encryption/decryption
- */
-int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx,
-                       size_t length,
-                       size_t *nc_off,
-                       unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE],
-                       unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE],
-                       const unsigned char *input,
-                       unsigned char *output )
-{
-    int c, i;
-    size_t n;
-    BLOWFISH_VALIDATE_RET( ctx != NULL );
-    BLOWFISH_VALIDATE_RET( nonce_counter != NULL );
-    BLOWFISH_VALIDATE_RET( stream_block  != NULL );
-    BLOWFISH_VALIDATE_RET( nc_off != NULL );
-    BLOWFISH_VALIDATE_RET( length == 0 || input  != NULL );
-    BLOWFISH_VALIDATE_RET( length == 0 || output != NULL );
-
-    n = *nc_off;
-    if( n >= 8 )
-        return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA );
-
-    while( length-- )
-    {
-        if( n == 0 ) {
-            mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, nonce_counter,
-                                stream_block );
-
-            for( i = MBEDTLS_BLOWFISH_BLOCKSIZE; i > 0; i-- )
-                if( ++nonce_counter[i - 1] != 0 )
-                    break;
-        }
-        c = *input++;
-        *output++ = (unsigned char)( c ^ stream_block[n] );
-
-        n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE;
-    }
-
-    *nc_off = n;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_CIPHER_MODE_CTR */
-
-static const uint32_t S[4][256] = {
-    {   0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L,
-        0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L,
-        0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L,
-        0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL,
-        0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL,
-        0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L,
-        0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL,
-        0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL,
-        0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L,
-        0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L,
-        0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL,
-        0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL,
-        0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL,
-        0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L,
-        0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L,
-        0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L,
-        0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L,
-        0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L,
-        0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL,
-        0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L,
-        0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L,
-        0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L,
-        0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L,
-        0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL,
-        0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L,
-        0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL,
-        0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL,
-        0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L,
-        0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL,
-        0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L,
-        0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL,
-        0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L,
-        0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L,
-        0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL,
-        0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L,
-        0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L,
-        0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL,
-        0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L,
-        0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL,
-        0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L,
-        0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L,
-        0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL,
-        0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L,
-        0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L,
-        0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L,
-        0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L,
-        0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L,
-        0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL,
-        0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL,
-        0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L,
-        0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L,
-        0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L,
-        0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L,
-        0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL,
-        0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L,
-        0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL,
-        0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL,
-        0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L,
-        0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L,
-        0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L,
-        0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L,
-        0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L,
-        0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L,
-        0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL   },
-    {   0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L,
-        0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L,
-        0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L,
-        0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL,
-        0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L,
-        0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L,
-        0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL,
-        0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L,
-        0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L,
-        0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L,
-        0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL,
-        0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL,
-        0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L,
-        0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L,
-        0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L,
-        0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L,
-        0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL,
-        0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL,
-        0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL,
-        0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L,
-        0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL,
-        0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L,
-        0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L,
-        0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL,
-        0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL,
-        0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L,
-        0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL,
-        0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L,
-        0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL,
-        0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL,
-        0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L,
-        0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L,
-        0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L,
-        0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L,
-        0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L,
-        0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L,
-        0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L,
-        0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL,
-        0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L,
-        0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL,
-        0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L,
-        0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L,
-        0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L,
-        0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L,
-        0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L,
-        0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L,
-        0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L,
-        0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L,
-        0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L,
-        0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L,
-        0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L,
-        0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L,
-        0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L,
-        0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L,
-        0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L,
-        0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L,
-        0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL,
-        0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL,
-        0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L,
-        0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL,
-        0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L,
-        0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L,
-        0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L,
-        0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L   },
-    {   0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L,
-        0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L,
-        0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL,
-        0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L,
-        0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L,
-        0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L,
-        0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL,
-        0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL,
-        0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL,
-        0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L,
-        0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L,
-        0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL,
-        0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L,
-        0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL,
-        0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L,
-        0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL,
-        0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L,
-        0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL,
-        0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L,
-        0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL,
-        0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L,
-        0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L,
-        0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL,
-        0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L,
-        0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L,
-        0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L,
-        0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L,
-        0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL,
-        0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L,
-        0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL,
-        0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L,
-        0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL,
-        0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L,
-        0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL,
-        0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL,
-        0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL,
-        0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L,
-        0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L,
-        0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL,
-        0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL,
-        0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL,
-        0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL,
-        0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL,
-        0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L,
-        0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L,
-        0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L,
-        0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L,
-        0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL,
-        0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL,
-        0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L,
-        0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L,
-        0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L,
-        0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L,
-        0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L,
-        0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L,
-        0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L,
-        0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L,
-        0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L,
-        0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L,
-        0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL,
-        0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L,
-        0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL,
-        0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L,
-        0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L  },
-    {   0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL,
-        0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL,
-        0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL,
-        0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L,
-        0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L,
-        0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L,
-        0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L,
-        0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L,
-        0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L,
-        0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L,
-        0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L,
-        0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L,
-        0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L,
-        0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L,
-        0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L,
-        0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL,
-        0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL,
-        0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L,
-        0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL,
-        0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL,
-        0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL,
-        0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L,
-        0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL,
-        0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL,
-        0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L,
-        0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L,
-        0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L,
-        0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L,
-        0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL,
-        0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL,
-        0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L,
-        0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L,
-        0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L,
-        0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL,
-        0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L,
-        0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L,
-        0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L,
-        0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL,
-        0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L,
-        0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L,
-        0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L,
-        0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL,
-        0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL,
-        0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L,
-        0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L,
-        0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L,
-        0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L,
-        0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL,
-        0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L,
-        0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL,
-        0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL,
-        0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L,
-        0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L,
-        0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL,
-        0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L,
-        0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL,
-        0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L,
-        0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL,
-        0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L,
-        0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L,
-        0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL,
-        0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L,
-        0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL,
-        0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L  }
-};
-
-#endif /* !MBEDTLS_BLOWFISH_ALT */
-#endif /* MBEDTLS_BLOWFISH_C */
diff --git a/lib/libmbedtls/mbedtls/library/bn_mul.h b/lib/libmbedtls/mbedtls/library/bn_mul.h
new file mode 100644
index 0000000..ab59fbd
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/bn_mul.h
@@ -0,0 +1,1072 @@
+/**
+ * \file bn_mul.h
+ *
+ * \brief Multi-precision integer library
+ */
+/*
+ *  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.
+ */
+/*
+ *      Multiply source vector [s] with b, add result
+ *       to destination vector [d] and set carry c.
+ *
+ *      Currently supports:
+ *
+ *         . IA-32 (386+)         . AMD64 / EM64T
+ *         . IA-32 (SSE2)         . Motorola 68000
+ *         . PowerPC, 32-bit      . MicroBlaze
+ *         . PowerPC, 64-bit      . TriCore
+ *         . SPARC v8             . ARM v3+
+ *         . Alpha                . MIPS32
+ *         . C, longlong          . C, generic
+ */
+#ifndef MBEDTLS_BN_MUL_H
+#define MBEDTLS_BN_MUL_H
+
+#include "mbedtls/build_info.h"
+
+#include "mbedtls/bignum.h"
+
+
+/*
+ * Conversion macros for embedded constants:
+ * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2
+ */
+#if defined(MBEDTLS_HAVE_INT32)
+
+#define MBEDTLS_BYTES_TO_T_UINT_4(a, b, c, d)               \
+    ((mbedtls_mpi_uint) (a) <<  0) |                        \
+    ((mbedtls_mpi_uint) (b) <<  8) |                        \
+    ((mbedtls_mpi_uint) (c) << 16) |                        \
+    ((mbedtls_mpi_uint) (d) << 24)
+
+#define MBEDTLS_BYTES_TO_T_UINT_2(a, b)                   \
+    MBEDTLS_BYTES_TO_T_UINT_4(a, b, 0, 0)
+
+#define MBEDTLS_BYTES_TO_T_UINT_8(a, b, c, d, e, f, g, h) \
+    MBEDTLS_BYTES_TO_T_UINT_4(a, b, c, d),                \
+    MBEDTLS_BYTES_TO_T_UINT_4(e, f, g, h)
+
+#else /* 64-bits */
+
+#define MBEDTLS_BYTES_TO_T_UINT_8(a, b, c, d, e, f, g, h)   \
+    ((mbedtls_mpi_uint) (a) <<  0) |                        \
+    ((mbedtls_mpi_uint) (b) <<  8) |                        \
+    ((mbedtls_mpi_uint) (c) << 16) |                        \
+    ((mbedtls_mpi_uint) (d) << 24) |                        \
+    ((mbedtls_mpi_uint) (e) << 32) |                        \
+    ((mbedtls_mpi_uint) (f) << 40) |                        \
+    ((mbedtls_mpi_uint) (g) << 48) |                        \
+    ((mbedtls_mpi_uint) (h) << 56)
+
+#define MBEDTLS_BYTES_TO_T_UINT_4(a, b, c, d)             \
+    MBEDTLS_BYTES_TO_T_UINT_8(a, b, c, d, 0, 0, 0, 0)
+
+#define MBEDTLS_BYTES_TO_T_UINT_2(a, b)                   \
+    MBEDTLS_BYTES_TO_T_UINT_8(a, b, 0, 0, 0, 0, 0, 0)
+
+#endif /* bits in mbedtls_mpi_uint */
+
+/* *INDENT-OFF* */
+#if defined(MBEDTLS_HAVE_ASM)
+
+/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */
+#if defined(__GNUC__) && \
+    ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 )
+
+/*
+ * GCC < 5.0 treated the x86 ebx (which is used for the GOT) as a
+ * fixed reserved register when building as PIC, leading to errors
+ * like: bn_mul.h:46:13: error: PIC register clobbered by 'ebx' in 'asm'
+ *
+ * This is fixed by an improved register allocator in GCC 5+. From the
+ * release notes:
+ * Register allocation improvements: Reuse of the PIC hard register,
+ * instead of using a fixed register, was implemented on x86/x86-64
+ * targets. This improves generated PIC code performance as more hard
+ * registers can be used.
+ */
+#if defined(__GNUC__) && __GNUC__ < 5 && defined(__PIC__)
+#define MULADDC_CANNOT_USE_EBX
+#endif
+
+/*
+ * Disable use of the i386 assembly code below if option -O0, to disable all
+ * compiler optimisations, is passed, detected with __OPTIMIZE__
+ * This is done as the number of registers used in the assembly code doesn't
+ * work with the -O0 option.
+ */
+#if defined(__i386__) && defined(__OPTIMIZE__) && !defined(MULADDC_CANNOT_USE_EBX)
+
+#define MULADDC_X1_INIT                     \
+    { mbedtls_mpi_uint t;                   \
+    asm(                                    \
+        "movl   %%ebx, %0           \n\t"   \
+        "movl   %5, %%esi           \n\t"   \
+        "movl   %6, %%edi           \n\t"   \
+        "movl   %7, %%ecx           \n\t"   \
+        "movl   %8, %%ebx           \n\t"
+
+#define MULADDC_X1_CORE                     \
+        "lodsl                      \n\t"   \
+        "mull   %%ebx               \n\t"   \
+        "addl   %%ecx,   %%eax      \n\t"   \
+        "adcl   $0,      %%edx      \n\t"   \
+        "addl   (%%edi), %%eax      \n\t"   \
+        "adcl   $0,      %%edx      \n\t"   \
+        "movl   %%edx,   %%ecx      \n\t"   \
+        "stosl                      \n\t"
+
+#define MULADDC_X1_STOP                                 \
+        "movl   %4, %%ebx       \n\t"                   \
+        "movl   %%ecx, %1       \n\t"                   \
+        "movl   %%edi, %2       \n\t"                   \
+        "movl   %%esi, %3       \n\t"                   \
+        : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
+        : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
+        : "eax", "ebx", "ecx", "edx", "esi", "edi"      \
+    ); }
+
+#if defined(MBEDTLS_HAVE_SSE2)
+
+#define MULADDC_X8_INIT MULADDC_X1_INIT
+
+#define MULADDC_X8_CORE                         \
+        "movd     %%ecx,     %%mm1      \n\t"   \
+        "movd     %%ebx,     %%mm0      \n\t"   \
+        "movd     (%%edi),   %%mm3      \n\t"   \
+        "paddq    %%mm3,     %%mm1      \n\t"   \
+        "movd     (%%esi),   %%mm2      \n\t"   \
+        "pmuludq  %%mm0,     %%mm2      \n\t"   \
+        "movd     4(%%esi),  %%mm4      \n\t"   \
+        "pmuludq  %%mm0,     %%mm4      \n\t"   \
+        "movd     8(%%esi),  %%mm6      \n\t"   \
+        "pmuludq  %%mm0,     %%mm6      \n\t"   \
+        "movd     12(%%esi), %%mm7      \n\t"   \
+        "pmuludq  %%mm0,     %%mm7      \n\t"   \
+        "paddq    %%mm2,     %%mm1      \n\t"   \
+        "movd     4(%%edi),  %%mm3      \n\t"   \
+        "paddq    %%mm4,     %%mm3      \n\t"   \
+        "movd     8(%%edi),  %%mm5      \n\t"   \
+        "paddq    %%mm6,     %%mm5      \n\t"   \
+        "movd     12(%%edi), %%mm4      \n\t"   \
+        "paddq    %%mm4,     %%mm7      \n\t"   \
+        "movd     %%mm1,     (%%edi)    \n\t"   \
+        "movd     16(%%esi), %%mm2      \n\t"   \
+        "pmuludq  %%mm0,     %%mm2      \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "movd     20(%%esi), %%mm4      \n\t"   \
+        "pmuludq  %%mm0,     %%mm4      \n\t"   \
+        "paddq    %%mm3,     %%mm1      \n\t"   \
+        "movd     24(%%esi), %%mm6      \n\t"   \
+        "pmuludq  %%mm0,     %%mm6      \n\t"   \
+        "movd     %%mm1,     4(%%edi)   \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "movd     28(%%esi), %%mm3      \n\t"   \
+        "pmuludq  %%mm0,     %%mm3      \n\t"   \
+        "paddq    %%mm5,     %%mm1      \n\t"   \
+        "movd     16(%%edi), %%mm5      \n\t"   \
+        "paddq    %%mm5,     %%mm2      \n\t"   \
+        "movd     %%mm1,     8(%%edi)   \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm7,     %%mm1      \n\t"   \
+        "movd     20(%%edi), %%mm5      \n\t"   \
+        "paddq    %%mm5,     %%mm4      \n\t"   \
+        "movd     %%mm1,     12(%%edi)  \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm2,     %%mm1      \n\t"   \
+        "movd     24(%%edi), %%mm5      \n\t"   \
+        "paddq    %%mm5,     %%mm6      \n\t"   \
+        "movd     %%mm1,     16(%%edi)  \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm4,     %%mm1      \n\t"   \
+        "movd     28(%%edi), %%mm5      \n\t"   \
+        "paddq    %%mm5,     %%mm3      \n\t"   \
+        "movd     %%mm1,     20(%%edi)  \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm6,     %%mm1      \n\t"   \
+        "movd     %%mm1,     24(%%edi)  \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "paddq    %%mm3,     %%mm1      \n\t"   \
+        "movd     %%mm1,     28(%%edi)  \n\t"   \
+        "addl     $32,       %%edi      \n\t"   \
+        "addl     $32,       %%esi      \n\t"   \
+        "psrlq    $32,       %%mm1      \n\t"   \
+        "movd     %%mm1,     %%ecx      \n\t"
+
+#define MULADDC_X8_STOP                 \
+        "emms                   \n\t"   \
+        "movl   %4, %%ebx       \n\t"   \
+        "movl   %%ecx, %1       \n\t"   \
+        "movl   %%edi, %2       \n\t"   \
+        "movl   %%esi, %3       \n\t"   \
+        : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
+        : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
+        : "eax", "ebx", "ecx", "edx", "esi", "edi"      \
+    ); }                                                \
+
+#endif /* SSE2 */
+
+#endif /* i386 */
+
+#if defined(__amd64__) || defined (__x86_64__)
+
+#define MULADDC_X1_INIT                        \
+    asm(                                    \
+        "xorq   %%r8, %%r8\n"
+
+#define MULADDC_X1_CORE                        \
+        "movq   (%%rsi), %%rax\n"           \
+        "mulq   %%rbx\n"                    \
+        "addq   $8, %%rsi\n"                \
+        "addq   %%rcx, %%rax\n"             \
+        "movq   %%r8, %%rcx\n"              \
+        "adcq   $0, %%rdx\n"                \
+        "nop    \n"                         \
+        "addq   %%rax, (%%rdi)\n"           \
+        "adcq   %%rdx, %%rcx\n"             \
+        "addq   $8, %%rdi\n"
+
+#define MULADDC_X1_STOP                                              \
+        : "+c" (c), "+D" (d), "+S" (s), "+m" (*(uint64_t (*)[16]) d) \
+        : "b" (b), "m" (*(const uint64_t (*)[16]) s)                 \
+        : "rax", "rdx", "r8"                                         \
+    );
+
+#endif /* AMD64 */
+
+#if defined(__aarch64__)
+
+#define MULADDC_X1_INIT             \
+    asm(
+
+#define MULADDC_X1_CORE             \
+        "ldr x4, [%2], #8   \n\t"   \
+        "ldr x5, [%1]       \n\t"   \
+        "mul x6, x4, %4     \n\t"   \
+        "umulh x7, x4, %4   \n\t"   \
+        "adds x5, x5, x6    \n\t"   \
+        "adc x7, x7, xzr    \n\t"   \
+        "adds x5, x5, %0    \n\t"   \
+        "adc %0, x7, xzr    \n\t"   \
+        "str x5, [%1], #8   \n\t"
+
+#define MULADDC_X1_STOP                                                 \
+         : "+r" (c),  "+r" (d), "+r" (s), "+m" (*(uint64_t (*)[16]) d)  \
+         : "r" (b), "m" (*(const uint64_t (*)[16]) s)                   \
+         : "x4", "x5", "x6", "x7", "cc"                                 \
+    );
+
+#endif /* Aarch64 */
+
+#if defined(__mc68020__) || defined(__mcpu32__)
+
+#define MULADDC_X1_INIT                 \
+    asm(                                \
+        "movl   %3, %%a2        \n\t"   \
+        "movl   %4, %%a3        \n\t"   \
+        "movl   %5, %%d3        \n\t"   \
+        "movl   %6, %%d2        \n\t"   \
+        "moveq  #0, %%d0        \n\t"
+
+#define MULADDC_X1_CORE                 \
+        "movel  %%a2@+, %%d1    \n\t"   \
+        "mulul  %%d2, %%d4:%%d1 \n\t"   \
+        "addl   %%d3, %%d1      \n\t"   \
+        "addxl  %%d0, %%d4      \n\t"   \
+        "moveq  #0,   %%d3      \n\t"   \
+        "addl   %%d1, %%a3@+    \n\t"   \
+        "addxl  %%d4, %%d3      \n\t"
+
+#define MULADDC_X1_STOP                 \
+        "movl   %%d3, %0        \n\t"   \
+        "movl   %%a3, %1        \n\t"   \
+        "movl   %%a2, %2        \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "d0", "d1", "d2", "d3", "d4", "a2", "a3"  \
+    );
+
+#define MULADDC_X8_INIT MULADDC_X1_INIT
+
+#define MULADDC_X8_CORE                     \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d4:%%d1  \n\t"   \
+        "addxl  %%d3,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d4       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d3:%%d1  \n\t"   \
+        "addxl  %%d4,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d4:%%d1  \n\t"   \
+        "addxl  %%d3,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d4       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d3:%%d1  \n\t"   \
+        "addxl  %%d4,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d4:%%d1  \n\t"   \
+        "addxl  %%d3,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d4       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d3:%%d1  \n\t"   \
+        "addxl  %%d4,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d4:%%d1  \n\t"   \
+        "addxl  %%d3,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d4       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "movel  %%a2@+,  %%d1       \n\t"   \
+        "mulul  %%d2,    %%d3:%%d1  \n\t"   \
+        "addxl  %%d4,    %%d1       \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"   \
+        "addl   %%d1,    %%a3@+     \n\t"   \
+        "addxl  %%d0,    %%d3       \n\t"
+
+#define MULADDC_X8_STOP MULADDC_X1_STOP
+
+#endif /* MC68000 */
+
+#if defined(__powerpc64__) || defined(__ppc64__)
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_X1_INIT                     \
+    asm(                                    \
+        "ld     r3, %3              \n\t"   \
+        "ld     r4, %4              \n\t"   \
+        "ld     r5, %5              \n\t"   \
+        "ld     r6, %6              \n\t"   \
+        "addi   r3, r3, -8          \n\t"   \
+        "addi   r4, r4, -8          \n\t"   \
+        "addic  r5, r5,  0          \n\t"
+
+#define MULADDC_X1_CORE                     \
+        "ldu    r7, 8(r3)           \n\t"   \
+        "mulld  r8, r7, r6          \n\t"   \
+        "mulhdu r9, r7, r6          \n\t"   \
+        "adde   r8, r8, r5          \n\t"   \
+        "ld     r7, 8(r4)           \n\t"   \
+        "addze  r5, r9              \n\t"   \
+        "addc   r8, r8, r7          \n\t"   \
+        "stdu   r8, 8(r4)           \n\t"
+
+#define MULADDC_X1_STOP                     \
+        "addze  r5, r5              \n\t"   \
+        "addi   r4, r4, 8           \n\t"   \
+        "addi   r3, r3, 8           \n\t"   \
+        "std    r5, %0              \n\t"   \
+        "std    r4, %1              \n\t"   \
+        "std    r3, %2              \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
+    );
+
+
+#else /* __MACH__ && __APPLE__ */
+
+#define MULADDC_X1_INIT                     \
+    asm(                                    \
+        "ld     %%r3, %3            \n\t"   \
+        "ld     %%r4, %4            \n\t"   \
+        "ld     %%r5, %5            \n\t"   \
+        "ld     %%r6, %6            \n\t"   \
+        "addi   %%r3, %%r3, -8      \n\t"   \
+        "addi   %%r4, %%r4, -8      \n\t"   \
+        "addic  %%r5, %%r5,  0      \n\t"
+
+#define MULADDC_X1_CORE                     \
+        "ldu    %%r7, 8(%%r3)       \n\t"   \
+        "mulld  %%r8, %%r7, %%r6    \n\t"   \
+        "mulhdu %%r9, %%r7, %%r6    \n\t"   \
+        "adde   %%r8, %%r8, %%r5    \n\t"   \
+        "ld     %%r7, 8(%%r4)       \n\t"   \
+        "addze  %%r5, %%r9          \n\t"   \
+        "addc   %%r8, %%r8, %%r7    \n\t"   \
+        "stdu   %%r8, 8(%%r4)       \n\t"
+
+#define MULADDC_X1_STOP                     \
+        "addze  %%r5, %%r5          \n\t"   \
+        "addi   %%r4, %%r4, 8       \n\t"   \
+        "addi   %%r3, %%r3, 8       \n\t"   \
+        "std    %%r5, %0            \n\t"   \
+        "std    %%r4, %1            \n\t"   \
+        "std    %%r3, %2            \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
+    );
+
+#endif /* __MACH__ && __APPLE__ */
+
+#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32  */
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_X1_INIT                 \
+    asm(                                \
+        "lwz    r3, %3          \n\t"   \
+        "lwz    r4, %4          \n\t"   \
+        "lwz    r5, %5          \n\t"   \
+        "lwz    r6, %6          \n\t"   \
+        "addi   r3, r3, -4      \n\t"   \
+        "addi   r4, r4, -4      \n\t"   \
+        "addic  r5, r5,  0      \n\t"
+
+#define MULADDC_X1_CORE                 \
+        "lwzu   r7, 4(r3)       \n\t"   \
+        "mullw  r8, r7, r6      \n\t"   \
+        "mulhwu r9, r7, r6      \n\t"   \
+        "adde   r8, r8, r5      \n\t"   \
+        "lwz    r7, 4(r4)       \n\t"   \
+        "addze  r5, r9          \n\t"   \
+        "addc   r8, r8, r7      \n\t"   \
+        "stwu   r8, 4(r4)       \n\t"
+
+#define MULADDC_X1_STOP                 \
+        "addze  r5, r5          \n\t"   \
+        "addi   r4, r4, 4       \n\t"   \
+        "addi   r3, r3, 4       \n\t"   \
+        "stw    r5, %0          \n\t"   \
+        "stw    r4, %1          \n\t"   \
+        "stw    r3, %2          \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
+    );
+
+#else /* __MACH__ && __APPLE__ */
+
+#define MULADDC_X1_INIT                     \
+    asm(                                    \
+        "lwz    %%r3, %3            \n\t"   \
+        "lwz    %%r4, %4            \n\t"   \
+        "lwz    %%r5, %5            \n\t"   \
+        "lwz    %%r6, %6            \n\t"   \
+        "addi   %%r3, %%r3, -4      \n\t"   \
+        "addi   %%r4, %%r4, -4      \n\t"   \
+        "addic  %%r5, %%r5,  0      \n\t"
+
+#define MULADDC_X1_CORE                     \
+        "lwzu   %%r7, 4(%%r3)       \n\t"   \
+        "mullw  %%r8, %%r7, %%r6    \n\t"   \
+        "mulhwu %%r9, %%r7, %%r6    \n\t"   \
+        "adde   %%r8, %%r8, %%r5    \n\t"   \
+        "lwz    %%r7, 4(%%r4)       \n\t"   \
+        "addze  %%r5, %%r9          \n\t"   \
+        "addc   %%r8, %%r8, %%r7    \n\t"   \
+        "stwu   %%r8, 4(%%r4)       \n\t"
+
+#define MULADDC_X1_STOP                     \
+        "addze  %%r5, %%r5          \n\t"   \
+        "addi   %%r4, %%r4, 4       \n\t"   \
+        "addi   %%r3, %%r3, 4       \n\t"   \
+        "stw    %%r5, %0            \n\t"   \
+        "stw    %%r4, %1            \n\t"   \
+        "stw    %%r3, %2            \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9"  \
+    );
+
+#endif /* __MACH__ && __APPLE__ */
+
+#endif /* PPC32 */
+
+/*
+ * The Sparc(64) assembly is reported to be broken.
+ * Disable it for now, until we're able to fix it.
+ */
+#if 0 && defined(__sparc__)
+#if defined(__sparc64__)
+
+#define MULADDC_X1_INIT                                 \
+    asm(                                                \
+                "ldx     %3, %%o0               \n\t"   \
+                "ldx     %4, %%o1               \n\t"   \
+                "ld      %5, %%o2               \n\t"   \
+                "ld      %6, %%o3               \n\t"
+
+#define MULADDC_X1_CORE                                 \
+                "ld      [%%o0], %%o4           \n\t"   \
+                "inc     4, %%o0                \n\t"   \
+                "ld      [%%o1], %%o5           \n\t"   \
+                "umul    %%o3, %%o4, %%o4       \n\t"   \
+                "addcc   %%o4, %%o2, %%o4       \n\t"   \
+                "rd      %%y, %%g1              \n\t"   \
+                "addx    %%g1, 0, %%g1          \n\t"   \
+                "addcc   %%o4, %%o5, %%o4       \n\t"   \
+                "st      %%o4, [%%o1]           \n\t"   \
+                "addx    %%g1, 0, %%o2          \n\t"   \
+                "inc     4, %%o1                \n\t"
+
+#define MULADDC_X1_STOP                                 \
+                "st      %%o2, %0               \n\t"   \
+                "stx     %%o1, %1               \n\t"   \
+                "stx     %%o0, %2               \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)          \
+        : "m" (s), "m" (d), "m" (c), "m" (b)    \
+        : "g1", "o0", "o1", "o2", "o3", "o4",   \
+          "o5"                                  \
+        );
+
+#else /* __sparc64__ */
+
+#define MULADDC_X1_INIT                                 \
+    asm(                                                \
+                "ld      %3, %%o0               \n\t"   \
+                "ld      %4, %%o1               \n\t"   \
+                "ld      %5, %%o2               \n\t"   \
+                "ld      %6, %%o3               \n\t"
+
+#define MULADDC_X1_CORE                                 \
+                "ld      [%%o0], %%o4           \n\t"   \
+                "inc     4, %%o0                \n\t"   \
+                "ld      [%%o1], %%o5           \n\t"   \
+                "umul    %%o3, %%o4, %%o4       \n\t"   \
+                "addcc   %%o4, %%o2, %%o4       \n\t"   \
+                "rd      %%y, %%g1              \n\t"   \
+                "addx    %%g1, 0, %%g1          \n\t"   \
+                "addcc   %%o4, %%o5, %%o4       \n\t"   \
+                "st      %%o4, [%%o1]           \n\t"   \
+                "addx    %%g1, 0, %%o2          \n\t"   \
+                "inc     4, %%o1                \n\t"
+
+#define MULADDC_X1_STOP                                 \
+                "st      %%o2, %0               \n\t"   \
+                "st      %%o1, %1               \n\t"   \
+                "st      %%o0, %2               \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)          \
+        : "m" (s), "m" (d), "m" (c), "m" (b)    \
+        : "g1", "o0", "o1", "o2", "o3", "o4",   \
+          "o5"                                  \
+        );
+
+#endif /* __sparc64__ */
+#endif /* __sparc__ */
+
+#if defined(__microblaze__) || defined(microblaze)
+
+#define MULADDC_X1_INIT                 \
+    asm(                                \
+        "lwi   r3,   %3         \n\t"   \
+        "lwi   r4,   %4         \n\t"   \
+        "lwi   r5,   %5         \n\t"   \
+        "lwi   r6,   %6         \n\t"   \
+        "andi  r7,   r6, 0xffff \n\t"   \
+        "bsrli r6,   r6, 16     \n\t"
+
+#if(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#define MULADDC_LHUI                    \
+        "lhui  r9,   r3,   0    \n\t"   \
+        "addi  r3,   r3,   2    \n\t"   \
+        "lhui  r8,   r3,   0    \n\t"
+#else
+#define MULADDC_LHUI                    \
+        "lhui  r8,   r3,   0    \n\t"   \
+        "addi  r3,   r3,   2    \n\t"   \
+        "lhui  r9,   r3,   0    \n\t"
+#endif
+
+#define MULADDC_X1_CORE                    \
+        MULADDC_LHUI                    \
+        "addi  r3,   r3,   2    \n\t"   \
+        "mul   r10,  r9,  r6    \n\t"   \
+        "mul   r11,  r8,  r7    \n\t"   \
+        "mul   r12,  r9,  r7    \n\t"   \
+        "mul   r13,  r8,  r6    \n\t"   \
+        "bsrli  r8, r10,  16    \n\t"   \
+        "bsrli  r9, r11,  16    \n\t"   \
+        "add   r13, r13,  r8    \n\t"   \
+        "add   r13, r13,  r9    \n\t"   \
+        "bslli r10, r10,  16    \n\t"   \
+        "bslli r11, r11,  16    \n\t"   \
+        "add   r12, r12, r10    \n\t"   \
+        "addc  r13, r13,  r0    \n\t"   \
+        "add   r12, r12, r11    \n\t"   \
+        "addc  r13, r13,  r0    \n\t"   \
+        "lwi   r10,  r4,   0    \n\t"   \
+        "add   r12, r12, r10    \n\t"   \
+        "addc  r13, r13,  r0    \n\t"   \
+        "add   r12, r12,  r5    \n\t"   \
+        "addc   r5, r13,  r0    \n\t"   \
+        "swi   r12,  r4,   0    \n\t"   \
+        "addi   r4,  r4,   4    \n\t"
+
+#define MULADDC_X1_STOP                 \
+        "swi   r5,   %0         \n\t"   \
+        "swi   r4,   %1         \n\t"   \
+        "swi   r3,   %2         \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "r3", "r4", "r5", "r6", "r7", "r8",       \
+          "r9", "r10", "r11", "r12", "r13"          \
+    );
+
+#endif /* MicroBlaze */
+
+#if defined(__tricore__)
+
+#define MULADDC_X1_INIT                         \
+    asm(                                        \
+        "ld.a   %%a2, %3                \n\t"   \
+        "ld.a   %%a3, %4                \n\t"   \
+        "ld.w   %%d4, %5                \n\t"   \
+        "ld.w   %%d1, %6                \n\t"   \
+        "xor    %%d5, %%d5              \n\t"
+
+#define MULADDC_X1_CORE                         \
+        "ld.w   %%d0,   [%%a2+]         \n\t"   \
+        "madd.u %%e2, %%e4, %%d0, %%d1  \n\t"   \
+        "ld.w   %%d0,   [%%a3]          \n\t"   \
+        "addx   %%d2,    %%d2,  %%d0    \n\t"   \
+        "addc   %%d3,    %%d3,    0     \n\t"   \
+        "mov    %%d4,    %%d3           \n\t"   \
+        "st.w  [%%a3+],  %%d2           \n\t"
+
+#define MULADDC_X1_STOP                         \
+        "st.w   %0, %%d4                \n\t"   \
+        "st.a   %1, %%a3                \n\t"   \
+        "st.a   %2, %%a2                \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)          \
+        : "m" (s), "m" (d), "m" (c), "m" (b)    \
+        : "d0", "d1", "e2", "d4", "a2", "a3"    \
+    );
+
+#endif /* TriCore */
+
+/*
+ * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about
+ * our use of r7 below, unless -fomit-frame-pointer is passed.
+ *
+ * On the other hand, -fomit-frame-pointer is implied by any -Ox options with
+ * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by
+ * clang and armcc5 under the same conditions).
+ *
+ * So, only use the optimized assembly below for optimized build, which avoids
+ * the build error and is pretty reasonable anyway.
+ */
+#if defined(__GNUC__) && !defined(__OPTIMIZE__)
+#define MULADDC_CANNOT_USE_R7
+#endif
+
+#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7)
+
+#if defined(__thumb__) && !defined(__thumb2__)
+
+#define MULADDC_X1_INIT                                 \
+    asm(                                                \
+            "ldr    r0, %3                      \n\t"   \
+            "ldr    r1, %4                      \n\t"   \
+            "ldr    r2, %5                      \n\t"   \
+            "ldr    r3, %6                      \n\t"   \
+            "lsr    r7, r3, #16                 \n\t"   \
+            "mov    r9, r7                      \n\t"   \
+            "lsl    r7, r3, #16                 \n\t"   \
+            "lsr    r7, r7, #16                 \n\t"   \
+            "mov    r8, r7                      \n\t"
+
+#define MULADDC_X1_CORE                                 \
+            "ldmia  r0!, {r6}                   \n\t"   \
+            "lsr    r7, r6, #16                 \n\t"   \
+            "lsl    r6, r6, #16                 \n\t"   \
+            "lsr    r6, r6, #16                 \n\t"   \
+            "mov    r4, r8                      \n\t"   \
+            "mul    r4, r6                      \n\t"   \
+            "mov    r3, r9                      \n\t"   \
+            "mul    r6, r3                      \n\t"   \
+            "mov    r5, r9                      \n\t"   \
+            "mul    r5, r7                      \n\t"   \
+            "mov    r3, r8                      \n\t"   \
+            "mul    r7, r3                      \n\t"   \
+            "lsr    r3, r6, #16                 \n\t"   \
+            "add    r5, r5, r3                  \n\t"   \
+            "lsr    r3, r7, #16                 \n\t"   \
+            "add    r5, r5, r3                  \n\t"   \
+            "add    r4, r4, r2                  \n\t"   \
+            "mov    r2, #0                      \n\t"   \
+            "adc    r5, r2                      \n\t"   \
+            "lsl    r3, r6, #16                 \n\t"   \
+            "add    r4, r4, r3                  \n\t"   \
+            "adc    r5, r2                      \n\t"   \
+            "lsl    r3, r7, #16                 \n\t"   \
+            "add    r4, r4, r3                  \n\t"   \
+            "adc    r5, r2                      \n\t"   \
+            "ldr    r3, [r1]                    \n\t"   \
+            "add    r4, r4, r3                  \n\t"   \
+            "adc    r2, r5                      \n\t"   \
+            "stmia  r1!, {r4}                   \n\t"
+
+#define MULADDC_X1_STOP                                 \
+            "str    r2, %0                      \n\t"   \
+            "str    r1, %1                      \n\t"   \
+            "str    r0, %2                      \n\t"   \
+         : "=m" (c),  "=m" (d), "=m" (s)        \
+         : "m" (s), "m" (d), "m" (c), "m" (b)   \
+         : "r0", "r1", "r2", "r3", "r4", "r5",  \
+           "r6", "r7", "r8", "r9", "cc"         \
+         );
+
+#elif (__ARM_ARCH >= 6) && \
+    defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)
+
+#define MULADDC_X1_INIT                            \
+    {                                              \
+        mbedtls_mpi_uint tmp_a, tmp_b;             \
+        asm volatile (
+
+#define MULADDC_X1_CORE                                         \
+           ".p2align  2                                 \n\t"   \
+            "ldr      %[a], [%[in]], #4                 \n\t"   \
+            "ldr      %[b], [%[acc]]                    \n\t"   \
+            "umaal    %[b], %[carry], %[scalar], %[a]   \n\t"   \
+            "str      %[b], [%[acc]], #4                \n\t"
+
+#define MULADDC_X1_STOP                                      \
+            : [a]      "=&r" (tmp_a),                        \
+              [b]      "=&r" (tmp_b),                        \
+              [in]     "+r"  (s),                            \
+              [acc]    "+r"  (d),                            \
+              [carry]  "+l"  (c)                             \
+            : [scalar] "r"   (b)                             \
+            : "memory"                                       \
+        );                                                   \
+    }
+
+#define MULADDC_X2_INIT                              \
+    {                                                \
+        mbedtls_mpi_uint tmp_a0, tmp_b0;             \
+        mbedtls_mpi_uint tmp_a1, tmp_b1;             \
+        asm volatile (
+
+            /* - Make sure loop is 4-byte aligned to avoid stalls
+             *   upon repeated non-word aligned instructions in
+             *   some microarchitectures.
+             * - Don't use ldm with post-increment or back-to-back
+             *   loads with post-increment and same address register
+             *   to avoid stalls on some microarchitectures.
+             * - Bunch loads and stores to reduce latency on some
+             *   microarchitectures. E.g., on Cortex-M4, the first
+             *   in a series of load/store operations has latency
+             *   2 cycles, while subsequent loads/stores are single-cycle. */
+#define MULADDC_X2_CORE                                           \
+           ".p2align  2                                   \n\t"   \
+            "ldr      %[a0], [%[in]],  #+8                \n\t"   \
+            "ldr      %[b0], [%[acc]], #+8                \n\t"   \
+            "ldr      %[a1], [%[in],  #-4]                \n\t"   \
+            "ldr      %[b1], [%[acc], #-4]                \n\t"   \
+            "umaal    %[b0], %[carry], %[scalar], %[a0]   \n\t"   \
+            "umaal    %[b1], %[carry], %[scalar], %[a1]   \n\t"   \
+            "str      %[b0], [%[acc], #-8]                \n\t"   \
+            "str      %[b1], [%[acc], #-4]                \n\t"
+
+#define MULADDC_X2_STOP                                      \
+            : [a0]     "=&r" (tmp_a0),                       \
+              [b0]     "=&r" (tmp_b0),                       \
+              [a1]     "=&r" (tmp_a1),                       \
+              [b1]     "=&r" (tmp_b1),                       \
+              [in]     "+r"  (s),                            \
+              [acc]    "+r"  (d),                            \
+              [carry]  "+l"  (c)                             \
+            : [scalar] "r"   (b)                             \
+            : "memory"                                       \
+        );                                                   \
+    }
+
+#else
+
+#define MULADDC_X1_INIT                                 \
+    asm(                                                \
+            "ldr    r0, %3                      \n\t"   \
+            "ldr    r1, %4                      \n\t"   \
+            "ldr    r2, %5                      \n\t"   \
+            "ldr    r3, %6                      \n\t"
+
+#define MULADDC_X1_CORE                                 \
+            "ldr    r4, [r0], #4                \n\t"   \
+            "mov    r5, #0                      \n\t"   \
+            "ldr    r6, [r1]                    \n\t"   \
+            "umlal  r2, r5, r3, r4              \n\t"   \
+            "adds   r7, r6, r2                  \n\t"   \
+            "adc    r2, r5, #0                  \n\t"   \
+            "str    r7, [r1], #4                \n\t"
+
+#define MULADDC_X1_STOP                                 \
+            "str    r2, %0                      \n\t"   \
+            "str    r1, %1                      \n\t"   \
+            "str    r0, %2                      \n\t"   \
+         : "=m" (c),  "=m" (d), "=m" (s)        \
+         : "m" (s), "m" (d), "m" (c), "m" (b)   \
+         : "r0", "r1", "r2", "r3", "r4", "r5",  \
+           "r6", "r7", "cc"                     \
+         );
+
+#endif /* Thumb */
+
+#endif /* ARMv3 */
+
+#if defined(__alpha__)
+
+#define MULADDC_X1_INIT                 \
+    asm(                                \
+        "ldq    $1, %3          \n\t"   \
+        "ldq    $2, %4          \n\t"   \
+        "ldq    $3, %5          \n\t"   \
+        "ldq    $4, %6          \n\t"
+
+#define MULADDC_X1_CORE                 \
+        "ldq    $6,  0($1)      \n\t"   \
+        "addq   $1,  8, $1      \n\t"   \
+        "mulq   $6, $4, $7      \n\t"   \
+        "umulh  $6, $4, $6      \n\t"   \
+        "addq   $7, $3, $7      \n\t"   \
+        "cmpult $7, $3, $3      \n\t"   \
+        "ldq    $5,  0($2)      \n\t"   \
+        "addq   $7, $5, $7      \n\t"   \
+        "cmpult $7, $5, $5      \n\t"   \
+        "stq    $7,  0($2)      \n\t"   \
+        "addq   $2,  8, $2      \n\t"   \
+        "addq   $6, $3, $3      \n\t"   \
+        "addq   $5, $3, $3      \n\t"
+
+#define MULADDC_X1_STOP                 \
+        "stq    $3, %0          \n\t"   \
+        "stq    $2, %1          \n\t"   \
+        "stq    $1, %2          \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)              \
+        : "m" (s), "m" (d), "m" (c), "m" (b)        \
+        : "$1", "$2", "$3", "$4", "$5", "$6", "$7"  \
+    );
+#endif /* Alpha */
+
+#if defined(__mips__) && !defined(__mips64)
+
+#define MULADDC_X1_INIT                 \
+    asm(                                \
+        "lw     $10, %3         \n\t"   \
+        "lw     $11, %4         \n\t"   \
+        "lw     $12, %5         \n\t"   \
+        "lw     $13, %6         \n\t"
+
+#define MULADDC_X1_CORE                 \
+        "lw     $14, 0($10)     \n\t"   \
+        "multu  $13, $14        \n\t"   \
+        "addi   $10, $10, 4     \n\t"   \
+        "mflo   $14             \n\t"   \
+        "mfhi   $9              \n\t"   \
+        "addu   $14, $12, $14   \n\t"   \
+        "lw     $15, 0($11)     \n\t"   \
+        "sltu   $12, $14, $12   \n\t"   \
+        "addu   $15, $14, $15   \n\t"   \
+        "sltu   $14, $15, $14   \n\t"   \
+        "addu   $12, $12, $9    \n\t"   \
+        "sw     $15, 0($11)     \n\t"   \
+        "addu   $12, $12, $14   \n\t"   \
+        "addi   $11, $11, 4     \n\t"
+
+#define MULADDC_X1_STOP                 \
+        "sw     $12, %0         \n\t"   \
+        "sw     $11, %1         \n\t"   \
+        "sw     $10, %2         \n\t"   \
+        : "=m" (c), "=m" (d), "=m" (s)                      \
+        : "m" (s), "m" (d), "m" (c), "m" (b)                \
+        : "$9", "$10", "$11", "$12", "$13", "$14", "$15", "lo", "hi" \
+    );
+
+#endif /* MIPS */
+#endif /* GNUC */
+
+#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
+
+#define MULADDC_X1_INIT                         \
+    __asm   mov     esi, s                      \
+    __asm   mov     edi, d                      \
+    __asm   mov     ecx, c                      \
+    __asm   mov     ebx, b
+
+#define MULADDC_X1_CORE                         \
+    __asm   lodsd                               \
+    __asm   mul     ebx                         \
+    __asm   add     eax, ecx                    \
+    __asm   adc     edx, 0                      \
+    __asm   add     eax, [edi]                  \
+    __asm   adc     edx, 0                      \
+    __asm   mov     ecx, edx                    \
+    __asm   stosd
+
+#define MULADDC_X1_STOP                         \
+    __asm   mov     c, ecx                      \
+    __asm   mov     d, edi                      \
+    __asm   mov     s, esi
+
+#if defined(MBEDTLS_HAVE_SSE2)
+
+#define EMIT __asm _emit
+
+#define MULADDC_X8_INIT MULADDC_X1_INIT
+
+#define MULADDC_X8_CORE                         \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0xC9             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0xC3             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x1F             \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x16             \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x04  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x08  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x7E  EMIT 0x0C  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xF8             \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x5F  EMIT 0x04  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xDC             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x08  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xEE             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x67  EMIT 0x0C  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xFC             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x0F             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x56  EMIT 0x10  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x14  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x18  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x04  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x5E  EMIT 0x1C  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xD8             \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCD             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x10  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xD5             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x08  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCF             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x14  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xE5             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x0C  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x18  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xF5             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x10  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCC             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x1C  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xDD             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x14  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCE             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x18  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x1C  \
+    EMIT 0x83  EMIT 0xC7  EMIT 0x20             \
+    EMIT 0x83  EMIT 0xC6  EMIT 0x20             \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0xC9
+
+#define MULADDC_X8_STOP                         \
+    EMIT 0x0F  EMIT 0x77                        \
+    __asm   mov     c, ecx                      \
+    __asm   mov     d, edi                      \
+    __asm   mov     s, esi
+
+#endif /* SSE2 */
+#endif /* MSVC */
+
+#endif /* MBEDTLS_HAVE_ASM */
+
+#if !defined(MULADDC_X1_CORE)
+#if defined(MBEDTLS_HAVE_UDBL)
+
+#define MULADDC_X1_INIT                 \
+{                                       \
+    mbedtls_t_udbl r;                           \
+    mbedtls_mpi_uint r0, r1;
+
+#define MULADDC_X1_CORE                 \
+    r   = *(s++) * (mbedtls_t_udbl) b;          \
+    r0  = (mbedtls_mpi_uint) r;                   \
+    r1  = (mbedtls_mpi_uint)( r >> biL );         \
+    r0 += c;  r1 += (r0 <  c);          \
+    r0 += *d; r1 += (r0 < *d);          \
+    c = r1; *(d++) = r0;
+
+#define MULADDC_X1_STOP                 \
+}
+
+#else /* MBEDTLS_HAVE_UDBL */
+
+#define MULADDC_X1_INIT                 \
+{                                       \
+    mbedtls_mpi_uint s0, s1, b0, b1;              \
+    mbedtls_mpi_uint r0, r1, rx, ry;              \
+    b0 = ( b << biH ) >> biH;           \
+    b1 = ( b >> biH );
+
+#define MULADDC_X1_CORE                 \
+    s0 = ( *s << biH ) >> biH;          \
+    s1 = ( *s >> biH ); s++;            \
+    rx = s0 * b1; r0 = s0 * b0;         \
+    ry = s1 * b0; r1 = s1 * b1;         \
+    r1 += ( rx >> biH );                \
+    r1 += ( ry >> biH );                \
+    rx <<= biH; ry <<= biH;             \
+    r0 += rx; r1 += (r0 < rx);          \
+    r0 += ry; r1 += (r0 < ry);          \
+    r0 +=  c; r1 += (r0 <  c);          \
+    r0 += *d; r1 += (r0 < *d);          \
+    c = r1; *(d++) = r0;
+
+#define MULADDC_X1_STOP                 \
+}
+
+#endif /* C (longlong) */
+#endif /* C (generic)  */
+
+#if !defined(MULADDC_X2_CORE)
+#define MULADDC_X2_INIT MULADDC_X1_INIT
+#define MULADDC_X2_STOP MULADDC_X1_STOP
+#define MULADDC_X2_CORE MULADDC_X1_CORE MULADDC_X1_CORE
+#endif /* MULADDC_X2_CORE */
+
+#if !defined(MULADDC_X4_CORE)
+#define MULADDC_X4_INIT MULADDC_X2_INIT
+#define MULADDC_X4_STOP MULADDC_X2_STOP
+#define MULADDC_X4_CORE MULADDC_X2_CORE MULADDC_X2_CORE
+#endif /* MULADDC_X4_CORE */
+
+#if !defined(MULADDC_X8_CORE)
+#define MULADDC_X8_INIT MULADDC_X4_INIT
+#define MULADDC_X8_STOP MULADDC_X4_STOP
+#define MULADDC_X8_CORE MULADDC_X4_CORE MULADDC_X4_CORE
+#endif /* MULADDC_X8_CORE */
+
+/* *INDENT-ON* */
+#endif /* bn_mul.h */
diff --git a/lib/libmbedtls/mbedtls/library/camellia.c b/lib/libmbedtls/mbedtls/library/camellia.c
index 29d730a..409727d 100644
--- a/lib/libmbedtls/mbedtls/library/camellia.c
+++ b/lib/libmbedtls/mbedtls/library/camellia.c
@@ -32,23 +32,10 @@
 
 #include <string.h>
 
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
 
 #if !defined(MBEDTLS_CAMELLIA_ALT)
 
-/* Parameter validation macros */
-#define CAMELLIA_VALIDATE_RET( cond )                                       \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA )
-#define CAMELLIA_VALIDATE( cond )                                           \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
-
 static const unsigned char SIGMA_CHARS[6][8] =
 {
     { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b },
@@ -63,109 +50,109 @@
 
 static const unsigned char FSb[256] =
 {
-    112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65,
-     35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189,
-    134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26,
-    166,225, 57,202,213, 71, 93, 61,217,  1, 90,214, 81, 86,108, 77,
-    139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153,
-    223, 76,203,194, 52,126,118,  5,109,183,169, 49,209, 23,  4,215,
-     20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34,
-    254, 68,207,178,195,181,122,145, 36,  8,232,168, 96,252,105, 80,
-    170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210,
-     16,196,  0, 72,163,247,117,219,138,  3,230,218,  9, 63,221,148,
-    135, 92,131,  2,205, 74,144, 51,115,103,246,243,157,127,191,226,
-     82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46,
-    233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89,
-    120,152,  6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250,
-    114,  7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164,
-     64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158
+    112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65,
+    35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189,
+    134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26,
+    166, 225, 57, 202, 213, 71, 93, 61, 217,  1, 90, 214, 81, 86, 108, 77,
+    139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153,
+    223, 76, 203, 194, 52, 126, 118,  5, 109, 183, 169, 49, 209, 23,  4, 215,
+    20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34,
+    254, 68, 207, 178, 195, 181, 122, 145, 36,  8, 232, 168, 96, 252, 105, 80,
+    170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210,
+    16, 196,  0, 72, 163, 247, 117, 219, 138,  3, 230, 218,  9, 63, 221, 148,
+    135, 92, 131,  2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226,
+    82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46,
+    233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89,
+    120, 152,  6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250,
+    114,  7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164,
+    64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158
 };
 
 #define SBOX1(n) FSb[(n)]
-#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff)
-#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff)
+#define SBOX2(n) (unsigned char) ((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff)
+#define SBOX3(n) (unsigned char) ((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff)
 #define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff]
 
 #else /* MBEDTLS_CAMELLIA_SMALL_MEMORY */
 
 static const unsigned char FSb[256] =
 {
- 112, 130,  44, 236, 179,  39, 192, 229, 228, 133,  87,  53, 234,  12, 174,  65,
-  35, 239, 107, 147,  69,  25, 165,  33, 237,  14,  79,  78,  29, 101, 146, 189,
- 134, 184, 175, 143, 124, 235,  31, 206,  62,  48, 220,  95,  94, 197,  11,  26,
- 166, 225,  57, 202, 213,  71,  93,  61, 217,   1,  90, 214,  81,  86, 108,  77,
- 139,  13, 154, 102, 251, 204, 176,  45, 116,  18,  43,  32, 240, 177, 132, 153,
- 223,  76, 203, 194,  52, 126, 118,   5, 109, 183, 169,  49, 209,  23,   4, 215,
-  20,  88,  58,  97, 222,  27,  17,  28,  50,  15, 156,  22,  83,  24, 242,  34,
- 254,  68, 207, 178, 195, 181, 122, 145,  36,   8, 232, 168,  96, 252, 105,  80,
- 170, 208, 160, 125, 161, 137,  98, 151,  84,  91,  30, 149, 224, 255, 100, 210,
-  16, 196,   0,  72, 163, 247, 117, 219, 138,   3, 230, 218,   9,  63, 221, 148,
- 135,  92, 131,   2, 205,  74, 144,  51, 115, 103, 246, 243, 157, 127, 191, 226,
-  82, 155, 216,  38, 200,  55, 198,  59, 129, 150, 111,  75,  19, 190,  99,  46,
- 233, 121, 167, 140, 159, 110, 188, 142,  41, 245, 249, 182,  47, 253, 180,  89,
- 120, 152,   6, 106, 231,  70, 113, 186, 212,  37, 171,  66, 136, 162, 141, 250,
- 114,   7, 185,  85, 248, 238, 172,  10,  54,  73,  42, 104,  60,  56, 241, 164,
- 64,  40, 211, 123, 187, 201,  67, 193,  21, 227, 173, 244, 119, 199, 128, 158
+    112, 130,  44, 236, 179,  39, 192, 229, 228, 133,  87,  53, 234,  12, 174,  65,
+    35, 239, 107, 147,  69,  25, 165,  33, 237,  14,  79,  78,  29, 101, 146, 189,
+    134, 184, 175, 143, 124, 235,  31, 206,  62,  48, 220,  95,  94, 197,  11,  26,
+    166, 225,  57, 202, 213,  71,  93,  61, 217,   1,  90, 214,  81,  86, 108,  77,
+    139,  13, 154, 102, 251, 204, 176,  45, 116,  18,  43,  32, 240, 177, 132, 153,
+    223,  76, 203, 194,  52, 126, 118,   5, 109, 183, 169,  49, 209,  23,   4, 215,
+    20,  88,  58,  97, 222,  27,  17,  28,  50,  15, 156,  22,  83,  24, 242,  34,
+    254,  68, 207, 178, 195, 181, 122, 145,  36,   8, 232, 168,  96, 252, 105,  80,
+    170, 208, 160, 125, 161, 137,  98, 151,  84,  91,  30, 149, 224, 255, 100, 210,
+    16, 196,   0,  72, 163, 247, 117, 219, 138,   3, 230, 218,   9,  63, 221, 148,
+    135,  92, 131,   2, 205,  74, 144,  51, 115, 103, 246, 243, 157, 127, 191, 226,
+    82, 155, 216,  38, 200,  55, 198,  59, 129, 150, 111,  75,  19, 190,  99,  46,
+    233, 121, 167, 140, 159, 110, 188, 142,  41, 245, 249, 182,  47, 253, 180,  89,
+    120, 152,   6, 106, 231,  70, 113, 186, 212,  37, 171,  66, 136, 162, 141, 250,
+    114,   7, 185,  85, 248, 238, 172,  10,  54,  73,  42, 104,  60,  56, 241, 164,
+    64,  40, 211, 123, 187, 201,  67, 193,  21, 227, 173, 244, 119, 199, 128, 158
 };
 
 static const unsigned char FSb2[256] =
 {
- 224,   5,  88, 217, 103,  78, 129, 203, 201,  11, 174, 106, 213,  24,  93, 130,
-  70, 223, 214,  39, 138,  50,  75,  66, 219,  28, 158, 156,  58, 202,  37, 123,
-  13, 113,  95,  31, 248, 215,  62, 157, 124,  96, 185, 190, 188, 139,  22,  52,
-  77, 195, 114, 149, 171, 142, 186, 122, 179,   2, 180, 173, 162, 172, 216, 154,
-  23,  26,  53, 204, 247, 153,  97,  90, 232,  36,  86,  64, 225,  99,   9,  51,
- 191, 152, 151, 133, 104, 252, 236,  10, 218, 111,  83,  98, 163,  46,   8, 175,
-  40, 176, 116, 194, 189,  54,  34,  56, 100,  30,  57,  44, 166,  48, 229,  68,
- 253, 136, 159, 101, 135, 107, 244,  35,  72,  16, 209,  81, 192, 249, 210, 160,
-  85, 161,  65, 250,  67,  19, 196,  47, 168, 182,  60,  43, 193, 255, 200, 165,
-  32, 137,   0, 144,  71, 239, 234, 183,  21,   6, 205, 181,  18, 126, 187,  41,
-  15, 184,   7,   4, 155, 148,  33, 102, 230, 206, 237, 231,  59, 254, 127, 197,
- 164,  55, 177,  76, 145, 110, 141, 118,   3,  45, 222, 150,  38, 125, 198,  92,
- 211, 242,  79,  25,  63, 220, 121,  29,  82, 235, 243, 109,  94, 251, 105, 178,
- 240,  49,  12, 212, 207, 140, 226, 117, 169,  74,  87, 132,  17,  69,  27, 245,
- 228,  14, 115, 170, 241, 221,  89,  20, 108, 146,  84, 208, 120, 112, 227,  73,
- 128,  80, 167, 246, 119, 147, 134, 131,  42, 199,  91, 233, 238, 143,   1,  61
+    224,   5,  88, 217, 103,  78, 129, 203, 201,  11, 174, 106, 213,  24,  93, 130,
+    70, 223, 214,  39, 138,  50,  75,  66, 219,  28, 158, 156,  58, 202,  37, 123,
+    13, 113,  95,  31, 248, 215,  62, 157, 124,  96, 185, 190, 188, 139,  22,  52,
+    77, 195, 114, 149, 171, 142, 186, 122, 179,   2, 180, 173, 162, 172, 216, 154,
+    23,  26,  53, 204, 247, 153,  97,  90, 232,  36,  86,  64, 225,  99,   9,  51,
+    191, 152, 151, 133, 104, 252, 236,  10, 218, 111,  83,  98, 163,  46,   8, 175,
+    40, 176, 116, 194, 189,  54,  34,  56, 100,  30,  57,  44, 166,  48, 229,  68,
+    253, 136, 159, 101, 135, 107, 244,  35,  72,  16, 209,  81, 192, 249, 210, 160,
+    85, 161,  65, 250,  67,  19, 196,  47, 168, 182,  60,  43, 193, 255, 200, 165,
+    32, 137,   0, 144,  71, 239, 234, 183,  21,   6, 205, 181,  18, 126, 187,  41,
+    15, 184,   7,   4, 155, 148,  33, 102, 230, 206, 237, 231,  59, 254, 127, 197,
+    164,  55, 177,  76, 145, 110, 141, 118,   3,  45, 222, 150,  38, 125, 198,  92,
+    211, 242,  79,  25,  63, 220, 121,  29,  82, 235, 243, 109,  94, 251, 105, 178,
+    240,  49,  12, 212, 207, 140, 226, 117, 169,  74,  87, 132,  17,  69,  27, 245,
+    228,  14, 115, 170, 241, 221,  89,  20, 108, 146,  84, 208, 120, 112, 227,  73,
+    128,  80, 167, 246, 119, 147, 134, 131,  42, 199,  91, 233, 238, 143,   1,  61
 };
 
 static const unsigned char FSb3[256] =
 {
-  56,  65,  22, 118, 217, 147,  96, 242, 114, 194, 171, 154, 117,   6,  87, 160,
- 145, 247, 181, 201, 162, 140, 210, 144, 246,   7, 167,  39, 142, 178,  73, 222,
-  67,  92, 215, 199,  62, 245, 143, 103,  31,  24, 110, 175,  47, 226, 133,  13,
-  83, 240, 156, 101, 234, 163, 174, 158, 236, 128,  45, 107, 168,  43,  54, 166,
- 197, 134,  77,  51, 253, 102,  88, 150,  58,   9, 149,  16, 120, 216,  66, 204,
- 239,  38, 229,  97,  26,  63,  59, 130, 182, 219, 212, 152, 232, 139,   2, 235,
-  10,  44,  29, 176, 111, 141, 136,  14,  25, 135,  78,  11, 169,  12, 121,  17,
- 127,  34, 231,  89, 225, 218,  61, 200,  18,   4, 116,  84,  48, 126, 180,  40,
-  85, 104,  80, 190, 208, 196,  49, 203,  42, 173,  15, 202, 112, 255,  50, 105,
-   8,  98,   0,  36, 209, 251, 186, 237,  69, 129, 115, 109, 132, 159, 238,  74,
- 195,  46, 193,   1, 230,  37,  72, 153, 185, 179, 123, 249, 206, 191, 223, 113,
-  41, 205, 108,  19, 100, 155,  99, 157, 192,  75, 183, 165, 137,  95, 177,  23,
- 244, 188, 211,  70, 207,  55,  94,  71, 148, 250, 252,  91, 151, 254,  90, 172,
-  60,  76,   3,  53, 243,  35, 184,  93, 106, 146, 213,  33,  68,  81, 198, 125,
-  57, 131, 220, 170, 124, 119,  86,   5,  27, 164,  21,  52,  30,  28, 248,  82,
-  32,  20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227,  64,  79
+    56,  65,  22, 118, 217, 147,  96, 242, 114, 194, 171, 154, 117,   6,  87, 160,
+    145, 247, 181, 201, 162, 140, 210, 144, 246,   7, 167,  39, 142, 178,  73, 222,
+    67,  92, 215, 199,  62, 245, 143, 103,  31,  24, 110, 175,  47, 226, 133,  13,
+    83, 240, 156, 101, 234, 163, 174, 158, 236, 128,  45, 107, 168,  43,  54, 166,
+    197, 134,  77,  51, 253, 102,  88, 150,  58,   9, 149,  16, 120, 216,  66, 204,
+    239,  38, 229,  97,  26,  63,  59, 130, 182, 219, 212, 152, 232, 139,   2, 235,
+    10,  44,  29, 176, 111, 141, 136,  14,  25, 135,  78,  11, 169,  12, 121,  17,
+    127,  34, 231,  89, 225, 218,  61, 200,  18,   4, 116,  84,  48, 126, 180,  40,
+    85, 104,  80, 190, 208, 196,  49, 203,  42, 173,  15, 202, 112, 255,  50, 105,
+    8,  98,   0,  36, 209, 251, 186, 237,  69, 129, 115, 109, 132, 159, 238,  74,
+    195,  46, 193,   1, 230,  37,  72, 153, 185, 179, 123, 249, 206, 191, 223, 113,
+    41, 205, 108,  19, 100, 155,  99, 157, 192,  75, 183, 165, 137,  95, 177,  23,
+    244, 188, 211,  70, 207,  55,  94,  71, 148, 250, 252,  91, 151, 254,  90, 172,
+    60,  76,   3,  53, 243,  35, 184,  93, 106, 146, 213,  33,  68,  81, 198, 125,
+    57, 131, 220, 170, 124, 119,  86,   5,  27, 164,  21,  52,  30,  28, 248,  82,
+    32,  20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227,  64,  79
 };
 
 static const unsigned char FSb4[256] =
 {
- 112,  44, 179, 192, 228,  87, 234, 174,  35, 107,  69, 165, 237,  79,  29, 146,
- 134, 175, 124,  31,  62, 220,  94,  11, 166,  57, 213,  93, 217,  90,  81, 108,
- 139, 154, 251, 176, 116,  43, 240, 132, 223, 203,  52, 118, 109, 169, 209,   4,
-  20,  58, 222,  17,  50, 156,  83, 242, 254, 207, 195, 122,  36, 232,  96, 105,
- 170, 160, 161,  98,  84,  30, 224, 100,  16,   0, 163, 117, 138, 230,   9, 221,
- 135, 131, 205, 144, 115, 246, 157, 191,  82, 216, 200, 198, 129, 111,  19,  99,
- 233, 167, 159, 188,  41, 249,  47, 180, 120,   6, 231, 113, 212, 171, 136, 141,
- 114, 185, 248, 172,  54,  42,  60, 241,  64, 211, 187,  67,  21, 173, 119, 128,
- 130, 236,  39, 229, 133,  53,  12,  65, 239, 147,  25,  33,  14,  78, 101, 189,
- 184, 143, 235, 206,  48,  95, 197,  26, 225, 202,  71,  61,   1, 214,  86,  77,
-  13, 102, 204,  45,  18,  32, 177, 153,  76, 194, 126,   5, 183,  49,  23, 215,
-  88,  97,  27,  28,  15,  22,  24,  34,  68, 178, 181, 145,   8, 168, 252,  80,
- 208, 125, 137, 151,  91, 149, 255, 210, 196,  72, 247, 219,   3, 218,  63, 148,
-  92,   2,  74,  51, 103, 243, 127, 226, 155,  38,  55,  59, 150,  75, 190,  46,
- 121, 140, 110, 142, 245, 182, 253,  89, 152, 106,  70, 186,  37,  66, 162, 250,
-  7,  85, 238,  10,  73, 104,  56, 164,  40, 123, 201, 193, 227, 244, 199, 158
+    112,  44, 179, 192, 228,  87, 234, 174,  35, 107,  69, 165, 237,  79,  29, 146,
+    134, 175, 124,  31,  62, 220,  94,  11, 166,  57, 213,  93, 217,  90,  81, 108,
+    139, 154, 251, 176, 116,  43, 240, 132, 223, 203,  52, 118, 109, 169, 209,   4,
+    20,  58, 222,  17,  50, 156,  83, 242, 254, 207, 195, 122,  36, 232,  96, 105,
+    170, 160, 161,  98,  84,  30, 224, 100,  16,   0, 163, 117, 138, 230,   9, 221,
+    135, 131, 205, 144, 115, 246, 157, 191,  82, 216, 200, 198, 129, 111,  19,  99,
+    233, 167, 159, 188,  41, 249,  47, 180, 120,   6, 231, 113, 212, 171, 136, 141,
+    114, 185, 248, 172,  54,  42,  60, 241,  64, 211, 187,  67,  21, 173, 119, 128,
+    130, 236,  39, 229, 133,  53,  12,  65, 239, 147,  25,  33,  14,  78, 101, 189,
+    184, 143, 235, 206,  48,  95, 197,  26, 225, 202,  71,  61,   1, 214,  86,  77,
+    13, 102, 204,  45,  18,  32, 177, 153,  76, 194, 126,   5, 183,  49,  23, 215,
+    88,  97,  27,  28,  15,  22,  24,  34,  68, 178, 181, 145,   8, 168, 252,  80,
+    208, 125, 137, 151,  91, 149, 255, 210, 196,  72, 247, 219,   3, 218,  63, 148,
+    92,   2,  74,  51, 103, 243, 127, 226, 155,  38,  55,  59, 150,  75, 190,  46,
+    121, 140, 110, 142, 245, 182, 253,  89, 152, 106,  70, 186,  37,  66, 162, 250,
+    7,  85, 238,  10,  73, 104,  56, 164,  40, 123, 201, 193, 227, 244, 199, 158
 };
 
 #define SBOX1(n) FSb[(n)]
@@ -195,23 +182,23 @@
 {
     {
         {  0,  1,  2,  3,  8,  9, 10, 11, 38, 39,
-          36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */
+           36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */
         { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
           -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */
         {  4,  5,  6,  7, 12, 13, 14, 15, 16, 17,
-          18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */
+           18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */
         { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
           -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }  /* KB -> RK */
     },
     {
         {  0,  1,  2,  3, 61, 62, 63, 60, -1, -1,
-          -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */
+           -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */
         { -1, -1, -1, -1,  8,  9, 10, 11, 16, 17,
           18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */
         { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59,
           56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */
         {  4,  5,  6,  7, 65, 66, 67, 64, 20, 21,
-          22, 23, -1, -1, -1, -1, 43, 40, 41, 42 }  /* KB -> RK */
+           22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */
     }
 };
 
@@ -235,57 +222,57 @@
 
 /* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */
 #define ROTL(DEST, SRC, SHIFT)                                      \
-{                                                                   \
-    (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT));   \
-    (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT));   \
-    (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT));   \
-    (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT));   \
-}
+    {                                                                   \
+        (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT));   \
+        (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT));   \
+        (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT));   \
+        (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT));   \
+    }
 
 #define FL(XL, XR, KL, KR)                                          \
-{                                                                   \
-    (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR);   \
-    (XL) = ((XR) | (KR)) ^ (XL);                                    \
-}
+    {                                                                   \
+        (XR) = ((((XL) &(KL)) << 1) | (((XL) &(KL)) >> 31)) ^ (XR);   \
+        (XL) = ((XR) | (KR)) ^ (XL);                                    \
+    }
 
 #define FLInv(YL, YR, KL, KR)                                       \
-{                                                                   \
-    (YL) = ((YR) | (KR)) ^ (YL);                                    \
-    (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR);   \
-}
+    {                                                                   \
+        (YL) = ((YR) | (KR)) ^ (YL);                                    \
+        (YR) = ((((YL) &(KL)) << 1) | (((YL) &(KL)) >> 31)) ^ (YR);   \
+    }
 
 #define SHIFT_AND_PLACE(INDEX, OFFSET)                      \
-{                                                           \
-    TK[0] = KC[(OFFSET) * 4 + 0];                           \
-    TK[1] = KC[(OFFSET) * 4 + 1];                           \
-    TK[2] = KC[(OFFSET) * 4 + 2];                           \
-    TK[3] = KC[(OFFSET) * 4 + 3];                           \
+    {                                                           \
+        TK[0] = KC[(OFFSET) * 4 + 0];                           \
+        TK[1] = KC[(OFFSET) * 4 + 1];                           \
+        TK[2] = KC[(OFFSET) * 4 + 2];                           \
+        TK[3] = KC[(OFFSET) * 4 + 3];                           \
                                                             \
-    for( i = 1; i <= 4; i++ )                               \
-        if( shifts[(INDEX)][(OFFSET)][i -1] )               \
-            ROTL(TK + i * 4, TK, ( 15 * i ) % 32);          \
+        for (i = 1; i <= 4; i++)                               \
+        if (shifts[(INDEX)][(OFFSET)][i -1])               \
+        ROTL(TK + i * 4, TK, (15 * i) % 32);          \
                                                             \
-    for( i = 0; i < 20; i++ )                               \
-        if( indexes[(INDEX)][(OFFSET)][i] != -1 ) {         \
-            RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ];    \
+        for (i = 0; i < 20; i++)                               \
+        if (indexes[(INDEX)][(OFFSET)][i] != -1) {         \
+            RK[indexes[(INDEX)][(OFFSET)][i]] = TK[i];    \
         }                                                   \
-}
+    }
 
-static void camellia_feistel( const uint32_t x[2], const uint32_t k[2],
-                              uint32_t z[2])
+static void camellia_feistel(const uint32_t x[2], const uint32_t k[2],
+                             uint32_t z[2])
 {
     uint32_t I0, I1;
     I0 = x[0] ^ k[0];
     I1 = x[1] ^ k[1];
 
-    I0 = ((uint32_t) SBOX1( MBEDTLS_BYTE_3( I0 )) << 24) |
-         ((uint32_t) SBOX2( MBEDTLS_BYTE_2( I0 )) << 16) |
-         ((uint32_t) SBOX3( MBEDTLS_BYTE_1( I0 )) <<  8) |
-         ((uint32_t) SBOX4( MBEDTLS_BYTE_0( I0 ))      );
-    I1 = ((uint32_t) SBOX2( MBEDTLS_BYTE_3( I1 )) << 24) |
-         ((uint32_t) SBOX3( MBEDTLS_BYTE_2( I1 )) << 16) |
-         ((uint32_t) SBOX4( MBEDTLS_BYTE_1( I1 )) <<  8) |
-         ((uint32_t) SBOX1( MBEDTLS_BYTE_0( I1 ))      );
+    I0 = ((uint32_t) SBOX1(MBEDTLS_BYTE_3(I0)) << 24) |
+         ((uint32_t) SBOX2(MBEDTLS_BYTE_2(I0)) << 16) |
+         ((uint32_t) SBOX3(MBEDTLS_BYTE_1(I0)) <<  8) |
+         ((uint32_t) SBOX4(MBEDTLS_BYTE_0(I0)));
+    I1 = ((uint32_t) SBOX2(MBEDTLS_BYTE_3(I1)) << 24) |
+         ((uint32_t) SBOX3(MBEDTLS_BYTE_2(I1)) << 16) |
+         ((uint32_t) SBOX4(MBEDTLS_BYTE_1(I1)) <<  8) |
+         ((uint32_t) SBOX1(MBEDTLS_BYTE_0(I1)));
 
     I0 ^= (I1 << 8) | (I1 >> 24);
     I1 ^= (I0 << 16) | (I0 >> 16);
@@ -296,26 +283,26 @@
     z[1] ^= I0;
 }
 
-void mbedtls_camellia_init( mbedtls_camellia_context *ctx )
+void mbedtls_camellia_init(mbedtls_camellia_context *ctx)
 {
-    CAMELLIA_VALIDATE( ctx != NULL );
-    memset( ctx, 0, sizeof( mbedtls_camellia_context ) );
+    memset(ctx, 0, sizeof(mbedtls_camellia_context));
 }
 
-void mbedtls_camellia_free( mbedtls_camellia_context *ctx )
+void mbedtls_camellia_free(mbedtls_camellia_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_camellia_context ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_camellia_context));
 }
 
 /*
  * Camellia key schedule (encryption)
  */
-int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx,
-                                 const unsigned char *key,
-                                 unsigned int keybits )
+int mbedtls_camellia_setkey_enc(mbedtls_camellia_context *ctx,
+                                const unsigned char *key,
+                                unsigned int keybits)
 {
     int idx;
     size_t i;
@@ -325,68 +312,70 @@
     uint32_t KC[16];
     uint32_t TK[20];
 
-    CAMELLIA_VALIDATE_RET( ctx != NULL );
-    CAMELLIA_VALIDATE_RET( key != NULL );
-
     RK = ctx->rk;
 
-    memset( t, 0, 64 );
-    memset( RK, 0, sizeof(ctx->rk) );
+    memset(t, 0, 64);
+    memset(RK, 0, sizeof(ctx->rk));
 
-    switch( keybits )
-    {
+    switch (keybits) {
         case 128: ctx->nr = 3; idx = 0; break;
         case 192:
         case 256: ctx->nr = 4; idx = 1; break;
-        default : return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA );
+        default: return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA;
     }
 
-    for( i = 0; i < keybits / 8; ++i )
+    for (i = 0; i < keybits / 8; ++i) {
         t[i] = key[i];
+    }
 
-    if( keybits == 192 ) {
-        for( i = 0; i < 8; i++ )
+    if (keybits == 192) {
+        for (i = 0; i < 8; i++) {
             t[24 + i] = ~t[16 + i];
+        }
     }
 
     /*
      * Prepare SIGMA values
      */
-    for( i = 0; i < 6; i++ ) {
-        SIGMA[i][0] = MBEDTLS_GET_UINT32_BE( SIGMA_CHARS[i], 0 );
-        SIGMA[i][1] = MBEDTLS_GET_UINT32_BE( SIGMA_CHARS[i], 4 );
+    for (i = 0; i < 6; i++) {
+        SIGMA[i][0] = MBEDTLS_GET_UINT32_BE(SIGMA_CHARS[i], 0);
+        SIGMA[i][1] = MBEDTLS_GET_UINT32_BE(SIGMA_CHARS[i], 4);
     }
 
     /*
      * Key storage in KC
      * Order: KL, KR, KA, KB
      */
-    memset( KC, 0, sizeof(KC) );
+    memset(KC, 0, sizeof(KC));
 
     /* Store KL, KR */
-    for( i = 0; i < 8; i++ )
-        KC[i] = MBEDTLS_GET_UINT32_BE( t, i * 4 );
+    for (i = 0; i < 8; i++) {
+        KC[i] = MBEDTLS_GET_UINT32_BE(t, i * 4);
+    }
 
     /* Generate KA */
-    for( i = 0; i < 4; ++i )
+    for (i = 0; i < 4; ++i) {
         KC[8 + i] = KC[i] ^ KC[4 + i];
+    }
 
-    camellia_feistel( KC + 8, SIGMA[0], KC + 10 );
-    camellia_feistel( KC + 10, SIGMA[1], KC + 8 );
+    camellia_feistel(KC + 8, SIGMA[0], KC + 10);
+    camellia_feistel(KC + 10, SIGMA[1], KC + 8);
 
-    for( i = 0; i < 4; ++i )
+    for (i = 0; i < 4; ++i) {
         KC[8 + i] ^= KC[i];
+    }
 
-    camellia_feistel( KC + 8, SIGMA[2], KC + 10 );
-    camellia_feistel( KC + 10, SIGMA[3], KC + 8 );
+    camellia_feistel(KC + 8, SIGMA[2], KC + 10);
+    camellia_feistel(KC + 10, SIGMA[3], KC + 8);
 
-    if( keybits > 128 ) {
+    if (keybits > 128) {
         /* Generate KB */
-        for( i = 0; i < 4; ++i )
+        for (i = 0; i < 4; ++i) {
             KC[12 + i] = KC[4 + i] ^ KC[8 + i];
+        }
 
-        camellia_feistel( KC + 12, SIGMA[4], KC + 14 );
-        camellia_feistel( KC + 14, SIGMA[5], KC + 12 );
+        camellia_feistel(KC + 12, SIGMA[4], KC + 14);
+        camellia_feistel(KC + 14, SIGMA[5], KC + 12);
     }
 
     /*
@@ -394,54 +383,53 @@
      */
 
     /* Manipulating KL */
-    SHIFT_AND_PLACE( idx, 0 );
+    SHIFT_AND_PLACE(idx, 0);
 
     /* Manipulating KR */
-    if( keybits > 128 ) {
-        SHIFT_AND_PLACE( idx, 1 );
+    if (keybits > 128) {
+        SHIFT_AND_PLACE(idx, 1);
     }
 
     /* Manipulating KA */
-    SHIFT_AND_PLACE( idx, 2 );
+    SHIFT_AND_PLACE(idx, 2);
 
     /* Manipulating KB */
-    if( keybits > 128 ) {
-        SHIFT_AND_PLACE( idx, 3 );
+    if (keybits > 128) {
+        SHIFT_AND_PLACE(idx, 3);
     }
 
     /* Do transpositions */
-    for( i = 0; i < 20; i++ ) {
-        if( transposes[idx][i] != -1 ) {
+    for (i = 0; i < 20; i++) {
+        if (transposes[idx][i] != -1) {
             RK[32 + 12 * idx + i] = RK[transposes[idx][i]];
         }
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Camellia key schedule (decryption)
  */
-int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx,
-                                 const unsigned char *key,
-                                 unsigned int keybits )
+int mbedtls_camellia_setkey_dec(mbedtls_camellia_context *ctx,
+                                const unsigned char *key,
+                                unsigned int keybits)
 {
     int idx, ret;
     size_t i;
     mbedtls_camellia_context cty;
     uint32_t *RK;
     uint32_t *SK;
-    CAMELLIA_VALIDATE_RET( ctx != NULL );
-    CAMELLIA_VALIDATE_RET( key != NULL );
 
-    mbedtls_camellia_init( &cty );
+    mbedtls_camellia_init(&cty);
 
     /* Also checks keybits */
-    if( ( ret = mbedtls_camellia_setkey_enc( &cty, key, keybits ) ) != 0 )
+    if ((ret = mbedtls_camellia_setkey_enc(&cty, key, keybits)) != 0) {
         goto exit;
+    }
 
     ctx->nr = cty.nr;
-    idx = ( ctx->nr == 4 );
+    idx = (ctx->nr == 4);
 
     RK = ctx->rk;
     SK = cty.rk + 24 * 2 + 8 * idx * 2;
@@ -451,8 +439,7 @@
     *RK++ = *SK++;
     *RK++ = *SK++;
 
-    for( i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4 )
-    {
+    for (i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4) {
         *RK++ = *SK++;
         *RK++ = *SK++;
     }
@@ -465,58 +452,56 @@
     *RK++ = *SK++;
 
 exit:
-    mbedtls_camellia_free( &cty );
+    mbedtls_camellia_free(&cty);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Camellia-ECB block encryption/decryption
  */
-int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx,
-                    int mode,
-                    const unsigned char input[16],
-                    unsigned char output[16] )
+int mbedtls_camellia_crypt_ecb(mbedtls_camellia_context *ctx,
+                               int mode,
+                               const unsigned char input[16],
+                               unsigned char output[16])
 {
     int NR;
     uint32_t *RK, X[4];
-    CAMELLIA_VALIDATE_RET( ctx != NULL );
-    CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT ||
-                           mode == MBEDTLS_CAMELLIA_DECRYPT );
-    CAMELLIA_VALIDATE_RET( input  != NULL );
-    CAMELLIA_VALIDATE_RET( output != NULL );
+    if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) {
+        return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA;
+    }
 
-    ( (void) mode );
+    ((void) mode);
 
     NR = ctx->nr;
     RK = ctx->rk;
 
-    X[0] = MBEDTLS_GET_UINT32_BE( input,  0 );
-    X[1] = MBEDTLS_GET_UINT32_BE( input,  4 );
-    X[2] = MBEDTLS_GET_UINT32_BE( input,  8 );
-    X[3] = MBEDTLS_GET_UINT32_BE( input, 12 );
+    X[0] = MBEDTLS_GET_UINT32_BE(input,  0);
+    X[1] = MBEDTLS_GET_UINT32_BE(input,  4);
+    X[2] = MBEDTLS_GET_UINT32_BE(input,  8);
+    X[3] = MBEDTLS_GET_UINT32_BE(input, 12);
 
     X[0] ^= *RK++;
     X[1] ^= *RK++;
     X[2] ^= *RK++;
     X[3] ^= *RK++;
 
-    while( NR ) {
+    while (NR) {
         --NR;
-        camellia_feistel( X, RK, X + 2 );
+        camellia_feistel(X, RK, X + 2);
         RK += 2;
-        camellia_feistel( X + 2, RK, X );
+        camellia_feistel(X + 2, RK, X);
         RK += 2;
-        camellia_feistel( X, RK, X + 2 );
+        camellia_feistel(X, RK, X + 2);
         RK += 2;
-        camellia_feistel( X + 2, RK, X );
+        camellia_feistel(X + 2, RK, X);
         RK += 2;
-        camellia_feistel( X, RK, X + 2 );
+        camellia_feistel(X, RK, X + 2);
         RK += 2;
-        camellia_feistel( X + 2, RK, X );
+        camellia_feistel(X + 2, RK, X);
         RK += 2;
 
-        if( NR ) {
+        if (NR) {
             FL(X[0], X[1], RK[0], RK[1]);
             RK += 2;
             FLInv(X[2], X[3], RK[0], RK[1]);
@@ -529,63 +514,53 @@
     X[0] ^= *RK++;
     X[1] ^= *RK++;
 
-    MBEDTLS_PUT_UINT32_BE( X[2], output,  0 );
-    MBEDTLS_PUT_UINT32_BE( X[3], output,  4 );
-    MBEDTLS_PUT_UINT32_BE( X[0], output,  8 );
-    MBEDTLS_PUT_UINT32_BE( X[1], output, 12 );
+    MBEDTLS_PUT_UINT32_BE(X[2], output,  0);
+    MBEDTLS_PUT_UINT32_BE(X[3], output,  4);
+    MBEDTLS_PUT_UINT32_BE(X[0], output,  8);
+    MBEDTLS_PUT_UINT32_BE(X[1], output, 12);
 
-    return( 0 );
+    return 0;
 }
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
 /*
  * Camellia-CBC buffer encryption/decryption
  */
-int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx,
-                                int mode,
-                                size_t length,
-                                unsigned char iv[16],
-                                const unsigned char *input,
-                                unsigned char *output )
+int mbedtls_camellia_crypt_cbc(mbedtls_camellia_context *ctx,
+                               int mode,
+                               size_t length,
+                               unsigned char iv[16],
+                               const unsigned char *input,
+                               unsigned char *output)
 {
-    int i;
     unsigned char temp[16];
-    CAMELLIA_VALIDATE_RET( ctx != NULL );
-    CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT ||
-                           mode == MBEDTLS_CAMELLIA_DECRYPT );
-    CAMELLIA_VALIDATE_RET( iv != NULL );
-    CAMELLIA_VALIDATE_RET( length == 0 || input  != NULL );
-    CAMELLIA_VALIDATE_RET( length == 0 || output != NULL );
+    if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) {
+        return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA;
+    }
 
-    if( length % 16 )
-        return( MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH );
+    if (length % 16) {
+        return MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH;
+    }
 
-    if( mode == MBEDTLS_CAMELLIA_DECRYPT )
-    {
-        while( length > 0 )
-        {
-            memcpy( temp, input, 16 );
-            mbedtls_camellia_crypt_ecb( ctx, mode, input, output );
+    if (mode == MBEDTLS_CAMELLIA_DECRYPT) {
+        while (length > 0) {
+            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 );
+            memcpy(iv, temp, 16);
 
             input  += 16;
             output += 16;
             length -= 16;
         }
-    }
-    else
-    {
-        while( length > 0 )
-        {
-            for( i = 0; i < 16; i++ )
-                output[i] = (unsigned char)( input[i] ^ iv[i] );
+    } else {
+        while (length > 0) {
+            mbedtls_xor(output, input, iv, 16);
 
-            mbedtls_camellia_crypt_ecb( ctx, mode, output, output );
-            memcpy( iv, output, 16 );
+            mbedtls_camellia_crypt_ecb(ctx, mode, output, output);
+            memcpy(iv, output, 16);
 
             input  += 16;
             output += 16;
@@ -593,7 +568,7 @@
         }
     }
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
@@ -601,58 +576,52 @@
 /*
  * Camellia-CFB128 buffer encryption/decryption
  */
-int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx,
-                       int mode,
-                       size_t length,
-                       size_t *iv_off,
-                       unsigned char iv[16],
-                       const unsigned char *input,
-                       unsigned char *output )
+int mbedtls_camellia_crypt_cfb128(mbedtls_camellia_context *ctx,
+                                  int mode,
+                                  size_t length,
+                                  size_t *iv_off,
+                                  unsigned char iv[16],
+                                  const unsigned char *input,
+                                  unsigned char *output)
 {
     int c;
     size_t n;
-    CAMELLIA_VALIDATE_RET( ctx != NULL );
-    CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT ||
-                           mode == MBEDTLS_CAMELLIA_DECRYPT );
-    CAMELLIA_VALIDATE_RET( iv     != NULL );
-    CAMELLIA_VALIDATE_RET( iv_off != NULL );
-    CAMELLIA_VALIDATE_RET( length == 0 || input  != NULL );
-    CAMELLIA_VALIDATE_RET( length == 0 || output != NULL );
+    if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) {
+        return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA;
+    }
 
     n = *iv_off;
-    if( n >= 16 )
-        return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA );
+    if (n >= 16) {
+        return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA;
+    }
 
-    if( mode == MBEDTLS_CAMELLIA_DECRYPT )
-    {
-        while( length-- )
-        {
-            if( n == 0 )
-                mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv );
+    if (mode == MBEDTLS_CAMELLIA_DECRYPT) {
+        while (length--) {
+            if (n == 0) {
+                mbedtls_camellia_crypt_ecb(ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv);
+            }
 
             c = *input++;
-            *output++ = (unsigned char)( c ^ iv[n] );
+            *output++ = (unsigned char) (c ^ iv[n]);
             iv[n] = (unsigned char) c;
 
-            n = ( n + 1 ) & 0x0F;
+            n = (n + 1) & 0x0F;
         }
-    }
-    else
-    {
-        while( length-- )
-        {
-            if( n == 0 )
-                mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv );
+    } else {
+        while (length--) {
+            if (n == 0) {
+                mbedtls_camellia_crypt_ecb(ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv);
+            }
 
-            iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+            iv[n] = *output++ = (unsigned char) (iv[n] ^ *input++);
 
-            n = ( n + 1 ) & 0x0F;
+            n = (n + 1) & 0x0F;
         }
     }
 
     *iv_off = n;
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
@@ -660,46 +629,42 @@
 /*
  * Camellia-CTR buffer encryption/decryption
  */
-int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx,
-                       size_t length,
-                       size_t *nc_off,
-                       unsigned char nonce_counter[16],
-                       unsigned char stream_block[16],
-                       const unsigned char *input,
-                       unsigned char *output )
+int mbedtls_camellia_crypt_ctr(mbedtls_camellia_context *ctx,
+                               size_t length,
+                               size_t *nc_off,
+                               unsigned char nonce_counter[16],
+                               unsigned char stream_block[16],
+                               const unsigned char *input,
+                               unsigned char *output)
 {
     int c, i;
     size_t n;
-    CAMELLIA_VALIDATE_RET( ctx != NULL );
-    CAMELLIA_VALIDATE_RET( nonce_counter != NULL );
-    CAMELLIA_VALIDATE_RET( stream_block  != NULL );
-    CAMELLIA_VALIDATE_RET( nc_off != NULL );
-    CAMELLIA_VALIDATE_RET( length == 0 || input  != NULL );
-    CAMELLIA_VALIDATE_RET( length == 0 || output != NULL );
 
     n = *nc_off;
-    if( n >= 16 )
-        return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA );
+    if (n >= 16) {
+        return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA;
+    }
 
-    while( length-- )
-    {
-        if( n == 0 ) {
-            mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, nonce_counter,
-                                stream_block );
+    while (length--) {
+        if (n == 0) {
+            mbedtls_camellia_crypt_ecb(ctx, MBEDTLS_CAMELLIA_ENCRYPT, nonce_counter,
+                                       stream_block);
 
-            for( i = 16; i > 0; i-- )
-                if( ++nonce_counter[i - 1] != 0 )
+            for (i = 16; i > 0; i--) {
+                if (++nonce_counter[i - 1] != 0) {
                     break;
+                }
+            }
         }
         c = *input++;
-        *output++ = (unsigned char)( c ^ stream_block[n] );
+        *output++ = (unsigned char) (c ^ stream_block[n]);
 
-        n = ( n + 1 ) & 0x0F;
+        n = (n + 1) & 0x0F;
     }
 
     *nc_off = n;
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 #endif /* !MBEDTLS_CAMELLIA_ALT */
@@ -779,23 +744,23 @@
 
 static const unsigned char camellia_test_cbc_key[3][32] =
 {
-        { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
-          0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
+    { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+      0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }
     ,
-        { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
-          0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
-          0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }
+    { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+      0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+      0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }
     ,
-        { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
-          0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
-          0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
-          0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+    { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+      0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+      0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+      0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
 };
 
 static const unsigned char camellia_test_cbc_iv[16] =
 
-    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }
+{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+  0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }
 ;
 
 static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] =
@@ -898,13 +863,13 @@
 };
 
 static const int camellia_test_ctr_len[3] =
-    { 16, 32, 36 };
+{ 16, 32, 36 };
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
 /*
  * Checkup routine
  */
-int mbedtls_camellia_self_test( int verbose )
+int mbedtls_camellia_self_test(int verbose)
 {
     int i, j, u, v;
     unsigned char key[32];
@@ -923,163 +888,167 @@
 
     mbedtls_camellia_context ctx;
 
-    mbedtls_camellia_init( &ctx );
-    memset( key, 0, 32 );
+    mbedtls_camellia_init(&ctx);
+    memset(key, 0, 32);
 
-    for( j = 0; j < 6; j++ ) {
+    for (j = 0; j < 6; j++) {
         u = j >> 1;
-    v = j & 1;
+        v = j & 1;
 
-    if( verbose != 0 )
-        mbedtls_printf( "  CAMELLIA-ECB-%3d (%s): ", 128 + u * 64,
-                         (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc");
-
-    for( i = 0; i < CAMELLIA_TESTS_ECB; i++ ) {
-        memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u );
-
-        if( v == MBEDTLS_CAMELLIA_DECRYPT ) {
-            mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 );
-            memcpy( src, camellia_test_ecb_cipher[u][i], 16 );
-            memcpy( dst, camellia_test_ecb_plain[i], 16 );
-        } else { /* MBEDTLS_CAMELLIA_ENCRYPT */
-            mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 );
-            memcpy( src, camellia_test_ecb_plain[i], 16 );
-            memcpy( dst, camellia_test_ecb_cipher[u][i], 16 );
+        if (verbose != 0) {
+            mbedtls_printf("  CAMELLIA-ECB-%3d (%s): ", 128 + u * 64,
+                           (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc");
         }
 
-        mbedtls_camellia_crypt_ecb( &ctx, v, src, buf );
+        for (i = 0; i < CAMELLIA_TESTS_ECB; i++) {
+            memcpy(key, camellia_test_ecb_key[u][i], 16 + 8 * u);
 
-        if( memcmp( buf, dst, 16 ) != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "failed\n" );
-            goto exit;
+            if (v == MBEDTLS_CAMELLIA_DECRYPT) {
+                mbedtls_camellia_setkey_dec(&ctx, key, 128 + u * 64);
+                memcpy(src, camellia_test_ecb_cipher[u][i], 16);
+                memcpy(dst, camellia_test_ecb_plain[i], 16);
+            } else { /* MBEDTLS_CAMELLIA_ENCRYPT */
+                mbedtls_camellia_setkey_enc(&ctx, key, 128 + u * 64);
+                memcpy(src, camellia_test_ecb_plain[i], 16);
+                memcpy(dst, camellia_test_ecb_cipher[u][i], 16);
+            }
+
+            mbedtls_camellia_crypt_ecb(&ctx, v, src, buf);
+
+            if (memcmp(buf, dst, 16) != 0) {
+                if (verbose != 0) {
+                    mbedtls_printf("failed\n");
+                }
+                goto exit;
+            }
+        }
+
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
         }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
-
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     /*
      * CBC mode
      */
-    for( j = 0; j < 6; j++ )
-    {
+    for (j = 0; j < 6; j++) {
         u = j >> 1;
         v = j  & 1;
 
-        if( verbose != 0 )
-            mbedtls_printf( "  CAMELLIA-CBC-%3d (%s): ", 128 + u * 64,
-                             ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" );
-
-        memcpy( src, camellia_test_cbc_iv, 16 );
-        memcpy( dst, camellia_test_cbc_iv, 16 );
-        memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u );
-
-        if( v == MBEDTLS_CAMELLIA_DECRYPT ) {
-            mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 );
-        } else {
-            mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 );
+        if (verbose != 0) {
+            mbedtls_printf("  CAMELLIA-CBC-%3d (%s): ", 128 + u * 64,
+                           (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc");
         }
 
-        for( i = 0; i < CAMELLIA_TESTS_CBC; i++ ) {
+        memcpy(src, camellia_test_cbc_iv, 16);
+        memcpy(dst, camellia_test_cbc_iv, 16);
+        memcpy(key, camellia_test_cbc_key[u], 16 + 8 * u);
 
-            if( v == MBEDTLS_CAMELLIA_DECRYPT ) {
-                memcpy( iv , src, 16 );
-                memcpy( src, camellia_test_cbc_cipher[u][i], 16 );
-                memcpy( dst, camellia_test_cbc_plain[i], 16 );
+        if (v == MBEDTLS_CAMELLIA_DECRYPT) {
+            mbedtls_camellia_setkey_dec(&ctx, key, 128 + u * 64);
+        } else {
+            mbedtls_camellia_setkey_enc(&ctx, key, 128 + u * 64);
+        }
+
+        for (i = 0; i < CAMELLIA_TESTS_CBC; i++) {
+
+            if (v == MBEDTLS_CAMELLIA_DECRYPT) {
+                memcpy(iv, src, 16);
+                memcpy(src, camellia_test_cbc_cipher[u][i], 16);
+                memcpy(dst, camellia_test_cbc_plain[i], 16);
             } else { /* MBEDTLS_CAMELLIA_ENCRYPT */
-                memcpy( iv , dst, 16 );
-                memcpy( src, camellia_test_cbc_plain[i], 16 );
-                memcpy( dst, camellia_test_cbc_cipher[u][i], 16 );
+                memcpy(iv, dst, 16);
+                memcpy(src, camellia_test_cbc_plain[i], 16);
+                memcpy(dst, camellia_test_cbc_cipher[u][i], 16);
             }
 
-            mbedtls_camellia_crypt_cbc( &ctx, v, 16, iv, src, buf );
+            mbedtls_camellia_crypt_cbc(&ctx, v, 16, iv, src, buf);
 
-            if( memcmp( buf, dst, 16 ) != 0 )
-            {
-                if( verbose != 0 )
-                    mbedtls_printf( "failed\n" );
+            if (memcmp(buf, dst, 16) != 0) {
+                if (verbose != 0) {
+                    mbedtls_printf("failed\n");
+                }
                 goto exit;
             }
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     /*
      * CTR mode
      */
-    for( i = 0; i < 6; i++ )
-    {
+    for (i = 0; i < 6; i++) {
         u = i >> 1;
         v = i  & 1;
 
-        if( verbose != 0 )
-            mbedtls_printf( "  CAMELLIA-CTR-128 (%s): ",
-                             ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" );
+        if (verbose != 0) {
+            mbedtls_printf("  CAMELLIA-CTR-128 (%s): ",
+                           (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc");
+        }
 
-        memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 );
-        memcpy( key, camellia_test_ctr_key[u], 16 );
+        memcpy(nonce_counter, camellia_test_ctr_nonce_counter[u], 16);
+        memcpy(key, camellia_test_ctr_key[u], 16);
 
         offset = 0;
-        mbedtls_camellia_setkey_enc( &ctx, key, 128 );
+        mbedtls_camellia_setkey_enc(&ctx, key, 128);
 
-        if( v == MBEDTLS_CAMELLIA_DECRYPT )
-        {
+        if (v == MBEDTLS_CAMELLIA_DECRYPT) {
             len = camellia_test_ctr_len[u];
-            memcpy( buf, camellia_test_ctr_ct[u], len );
+            memcpy(buf, camellia_test_ctr_ct[u], len);
 
-            mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
-                                buf, buf );
+            mbedtls_camellia_crypt_ctr(&ctx, len, &offset, nonce_counter, stream_block,
+                                       buf, buf);
 
-            if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 )
-            {
-                if( verbose != 0 )
-                    mbedtls_printf( "failed\n" );
+            if (memcmp(buf, camellia_test_ctr_pt[u], len) != 0) {
+                if (verbose != 0) {
+                    mbedtls_printf("failed\n");
+                }
                 goto exit;
             }
-        }
-        else
-        {
+        } else {
             len = camellia_test_ctr_len[u];
-            memcpy( buf, camellia_test_ctr_pt[u], len );
+            memcpy(buf, camellia_test_ctr_pt[u], len);
 
-            mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
-                                buf, buf );
+            mbedtls_camellia_crypt_ctr(&ctx, len, &offset, nonce_counter, stream_block,
+                                       buf, buf);
 
-            if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 )
-            {
-                if( verbose != 0 )
-                    mbedtls_printf( "failed\n" );
+            if (memcmp(buf, camellia_test_ctr_ct[u], len) != 0) {
+                if (verbose != 0) {
+                    mbedtls_printf("failed\n");
+                }
                 goto exit;
             }
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
     ret = 0;
 
 exit:
-    mbedtls_camellia_free( &ctx );
-    return( ret );
+    mbedtls_camellia_free(&ctx);
+    return ret;
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/lib/libmbedtls/mbedtls/library/ccm.c b/lib/libmbedtls/mbedtls/library/ccm.c
index a21a37f..36c999e 100644
--- a/lib/libmbedtls/mbedtls/library/ccm.c
+++ b/lib/libmbedtls/mbedtls/library/ccm.c
@@ -36,154 +36,137 @@
 
 #include <string.h>
 
-#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
 #if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
 #else
+#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
 #include <stdio.h>
 #define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_CCM_ALT)
 
-#define CCM_VALIDATE_RET( cond ) \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CCM_BAD_INPUT )
-#define CCM_VALIDATE( cond ) \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
-
-#define CCM_ENCRYPT 0
-#define CCM_DECRYPT 1
 
 /*
  * Initialize context
  */
-void mbedtls_ccm_init( mbedtls_ccm_context *ctx )
+void mbedtls_ccm_init(mbedtls_ccm_context *ctx)
 {
-    CCM_VALIDATE( ctx != NULL );
-    memset( ctx, 0, sizeof( mbedtls_ccm_context ) );
+    memset(ctx, 0, sizeof(mbedtls_ccm_context));
 }
 
-int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
-                        mbedtls_cipher_id_t cipher,
-                        const unsigned char *key,
-                        unsigned int keybits )
+int mbedtls_ccm_setkey(mbedtls_ccm_context *ctx,
+                       mbedtls_cipher_id_t cipher,
+                       const unsigned char *key,
+                       unsigned int keybits)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const mbedtls_cipher_info_t *cipher_info;
 
-    CCM_VALIDATE_RET( ctx != NULL );
-    CCM_VALIDATE_RET( key != NULL );
-
-    cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
-                                                   MBEDTLS_MODE_ECB );
-    if( cipher_info == NULL )
-        return( MBEDTLS_ERR_CCM_BAD_INPUT );
-
-    if( cipher_info->block_size != 16 )
-        return( MBEDTLS_ERR_CCM_BAD_INPUT );
-
-    mbedtls_cipher_free( &ctx->cipher_ctx );
-
-    if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
-        return( ret );
-
-    if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
-                               MBEDTLS_ENCRYPT ) ) != 0 )
-    {
-        return( ret );
+    cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
+                                                  MBEDTLS_MODE_ECB);
+    if (cipher_info == NULL) {
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
     }
 
-    return( 0 );
+    if (cipher_info->block_size != 16) {
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
+    }
+
+    mbedtls_cipher_free(&ctx->cipher_ctx);
+
+    if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
+        return ret;
+    }
+
+    if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
+                                     MBEDTLS_ENCRYPT)) != 0) {
+        return ret;
+    }
+
+    return 0;
 }
 
 /*
  * Free context
  */
-void mbedtls_ccm_free( mbedtls_ccm_context *ctx )
+void mbedtls_ccm_free(mbedtls_ccm_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
-    mbedtls_cipher_free( &ctx->cipher_ctx );
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) );
+    }
+    mbedtls_cipher_free(&ctx->cipher_ctx);
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ccm_context));
 }
 
-/*
- * Macros for common operations.
- * Results in smaller compiled code than static inline functions.
- */
-
-/*
- * Update the CBC-MAC state in y using a block in b
- * (Always using b as the source helps the compiler optimise a bit better.)
- */
-#define UPDATE_CBC_MAC                                                      \
-    for( i = 0; i < 16; i++ )                                               \
-        y[i] ^= b[i];                                                       \
-                                                                            \
-    if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \
-        return( ret );
+#define CCM_STATE__CLEAR                0
+#define CCM_STATE__STARTED              (1 << 0)
+#define CCM_STATE__LENGTHS_SET          (1 << 1)
+#define CCM_STATE__AUTH_DATA_STARTED    (1 << 2)
+#define CCM_STATE__AUTH_DATA_FINISHED   (1 << 3)
+#define CCM_STATE__ERROR                (1 << 4)
 
 /*
  * Encrypt or decrypt a partial block with CTR
- * Warning: using b for temporary storage! src and dst must not be b!
- * This avoids allocating one more 16 bytes buffer while allowing src == dst.
  */
-#define CTR_CRYPT( dst, src, len  )                                            \
-    do                                                                  \
-    {                                                                   \
-        if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr,       \
-                                           16, b, &olen ) ) != 0 )      \
-        {                                                               \
-            return( ret );                                              \
-        }                                                               \
-                                                                        \
-        for( i = 0; i < (len); i++ )                                    \
-            (dst)[i] = (src)[i] ^ b[i];                                 \
-    } while( 0 )
+static int mbedtls_ccm_crypt(mbedtls_ccm_context *ctx,
+                             size_t offset, size_t use_len,
+                             const unsigned char *input,
+                             unsigned char *output)
+{
+    size_t olen = 0;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char tmp_buf[16] = { 0 };
 
-/*
- * Authenticated encryption or decryption
- */
-static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
-                           const unsigned char *iv, size_t iv_len,
-                           const unsigned char *add, size_t add_len,
-                           const unsigned char *input, unsigned char *output,
-                           unsigned char *tag, size_t tag_len )
+    if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->ctr, 16, tmp_buf,
+                                     &olen)) != 0) {
+        ctx->state |= CCM_STATE__ERROR;
+        mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf));
+        return ret;
+    }
+
+    mbedtls_xor(output, input, tmp_buf + offset, use_len);
+
+    mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf));
+    return ret;
+}
+
+static void mbedtls_ccm_clear_state(mbedtls_ccm_context *ctx)
+{
+    ctx->state = CCM_STATE__CLEAR;
+    memset(ctx->y, 0, 16);
+    memset(ctx->ctr, 0, 16);
+}
+
+static int ccm_calculate_first_block_if_ready(mbedtls_ccm_context *ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char i;
-    unsigned char q;
     size_t len_left, olen;
-    unsigned char b[16];
-    unsigned char y[16];
-    unsigned char ctr[16];
-    const unsigned char *src;
-    unsigned char *dst;
 
-    /*
-     * Check length requirements: SP800-38C A.1
-     * Additional requirement: a < 2^16 - 2^8 to simplify the code.
-     * 'length' checked later (when writing it to the first block)
-     *
-     * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4).
+    /* length calculation can be done only after both
+     * mbedtls_ccm_starts() and mbedtls_ccm_set_lengths() have been executed
      */
-    if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 )
-        return( MBEDTLS_ERR_CCM_BAD_INPUT );
+    if (!(ctx->state & CCM_STATE__STARTED) || !(ctx->state & CCM_STATE__LENGTHS_SET)) {
+        return 0;
+    }
 
-    /* Also implies q is within bounds */
-    if( iv_len < 7 || iv_len > 13 )
-        return( MBEDTLS_ERR_CCM_BAD_INPUT );
-
-    if( add_len >= 0xFF00 )
-        return( MBEDTLS_ERR_CCM_BAD_INPUT );
-
-    q = 16 - 1 - (unsigned char) iv_len;
+    /* CCM expects non-empty tag.
+     * CCM* allows empty tag. For CCM* without tag, ignore plaintext length.
+     */
+    if (ctx->tag_len == 0) {
+        if (ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT || ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) {
+            ctx->plaintext_len = 0;
+        } else {
+            return MBEDTLS_ERR_CCM_BAD_INPUT;
+        }
+    }
 
     /*
-     * First block B_0:
+     * First block:
      * 0        .. 0        flags
-     * 1        .. iv_len   nonce (aka iv)
+     * 1        .. iv_len   nonce (aka iv)  - set by: mbedtls_ccm_starts()
      * iv_len+1 .. 15       length
      *
      * With flags as (bits):
@@ -192,57 +175,41 @@
      * 5 .. 3   (t - 2) / 2
      * 2 .. 0   q - 1
      */
-    b[0] = 0;
-    b[0] |= ( add_len > 0 ) << 6;
-    b[0] |= ( ( tag_len - 2 ) / 2 ) << 3;
-    b[0] |= q - 1;
+    ctx->y[0] |= (ctx->add_len > 0) << 6;
+    ctx->y[0] |= ((ctx->tag_len - 2) / 2) << 3;
+    ctx->y[0] |= ctx->q - 1;
 
-    memcpy( b + 1, iv, iv_len );
-
-    for( i = 0, len_left = length; i < q; i++, len_left >>= 8 )
-        b[15-i] = MBEDTLS_BYTE_0( len_left );
-
-    if( len_left > 0 )
-        return( MBEDTLS_ERR_CCM_BAD_INPUT );
-
-
-    /* Start CBC-MAC with first block */
-    memset( y, 0, 16 );
-    UPDATE_CBC_MAC;
-
-    /*
-     * If there is additional data, update CBC-MAC with
-     * add_len, add, 0 (padding to a block boundary)
-     */
-    if( add_len > 0 )
-    {
-        size_t use_len;
-        len_left = add_len;
-        src = add;
-
-        memset( b, 0, 16 );
-        MBEDTLS_PUT_UINT16_BE( add_len, b, 0 );
-
-        use_len = len_left < 16 - 2 ? len_left : 16 - 2;
-        memcpy( b + 2, src, use_len );
-        len_left -= use_len;
-        src += use_len;
-
-        UPDATE_CBC_MAC;
-
-        while( len_left > 0 )
-        {
-            use_len = len_left > 16 ? 16 : len_left;
-
-            memset( b, 0, 16 );
-            memcpy( b, src, use_len );
-            UPDATE_CBC_MAC;
-
-            len_left -= use_len;
-            src += use_len;
-        }
+    for (i = 0, len_left = ctx->plaintext_len; i < ctx->q; i++, len_left >>= 8) {
+        ctx->y[15-i] = MBEDTLS_BYTE_0(len_left);
     }
 
+    if (len_left > 0) {
+        ctx->state |= CCM_STATE__ERROR;
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
+    }
+
+    /* Start CBC-MAC with first block*/
+    if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen)) != 0) {
+        ctx->state |= CCM_STATE__ERROR;
+        return ret;
+    }
+
+    return 0;
+}
+
+int mbedtls_ccm_starts(mbedtls_ccm_context *ctx,
+                       int mode,
+                       const unsigned char *iv,
+                       size_t iv_len)
+{
+    /* Also implies q is within bounds */
+    if (iv_len < 7 || iv_len > 13) {
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
+    }
+
+    ctx->mode = mode;
+    ctx->q = 16 - 1 - (unsigned char) iv_len;
+
     /*
      * Prepare counter block for encryption:
      * 0        .. 0        flags
@@ -253,163 +220,377 @@
      * 7 .. 3   0
      * 2 .. 0   q - 1
      */
-    ctr[0] = q - 1;
-    memcpy( ctr + 1, iv, iv_len );
-    memset( ctr + 1 + iv_len, 0, q );
-    ctr[15] = 1;
+    memset(ctx->ctr, 0, 16);
+    ctx->ctr[0] = ctx->q - 1;
+    memcpy(ctx->ctr + 1, iv, iv_len);
+    memset(ctx->ctr + 1 + iv_len, 0, ctx->q);
+    ctx->ctr[15] = 1;
 
     /*
-     * Authenticate and {en,de}crypt the message.
-     *
-     * The only difference between encryption and decryption is
-     * the respective order of authentication and {en,de}cryption.
+     * See ccm_calculate_first_block_if_ready() for block layout description
      */
-    len_left = length;
-    src = input;
-    dst = output;
+    memcpy(ctx->y + 1, iv, iv_len);
 
-    while( len_left > 0 )
-    {
-        size_t use_len = len_left > 16 ? 16 : len_left;
+    ctx->state |= CCM_STATE__STARTED;
+    return ccm_calculate_first_block_if_ready(ctx);
+}
 
-        if( mode == CCM_ENCRYPT )
-        {
-            memset( b, 0, 16 );
-            memcpy( b, src, use_len );
-            UPDATE_CBC_MAC;
+int mbedtls_ccm_set_lengths(mbedtls_ccm_context *ctx,
+                            size_t total_ad_len,
+                            size_t plaintext_len,
+                            size_t tag_len)
+{
+    /*
+     * Check length requirements: SP800-38C A.1
+     * Additional requirement: a < 2^16 - 2^8 to simplify the code.
+     * 'length' checked later (when writing it to the first block)
+     *
+     * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4).
+     */
+    if (tag_len == 2 || tag_len > 16 || tag_len % 2 != 0) {
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
+    }
+
+    if (total_ad_len >= 0xFF00) {
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
+    }
+
+    ctx->plaintext_len = plaintext_len;
+    ctx->add_len = total_ad_len;
+    ctx->tag_len = tag_len;
+    ctx->processed = 0;
+
+    ctx->state |= CCM_STATE__LENGTHS_SET;
+    return ccm_calculate_first_block_if_ready(ctx);
+}
+
+int mbedtls_ccm_update_ad(mbedtls_ccm_context *ctx,
+                          const unsigned char *add,
+                          size_t add_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t olen, use_len, offset;
+
+    if (ctx->state & CCM_STATE__ERROR) {
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
+    }
+
+    if (add_len > 0) {
+        if (ctx->state & CCM_STATE__AUTH_DATA_FINISHED) {
+            return MBEDTLS_ERR_CCM_BAD_INPUT;
         }
 
-        CTR_CRYPT( dst, src, use_len );
+        if (!(ctx->state & CCM_STATE__AUTH_DATA_STARTED)) {
+            if (add_len > ctx->add_len) {
+                return MBEDTLS_ERR_CCM_BAD_INPUT;
+            }
 
-        if( mode == CCM_DECRYPT )
-        {
-            memset( b, 0, 16 );
-            memcpy( b, dst, use_len );
-            UPDATE_CBC_MAC;
+            ctx->y[0] ^= (unsigned char) ((ctx->add_len >> 8) & 0xFF);
+            ctx->y[1] ^= (unsigned char) ((ctx->add_len) & 0xFF);
+
+            ctx->state |= CCM_STATE__AUTH_DATA_STARTED;
+        } else if (ctx->processed + add_len > ctx->add_len) {
+            return MBEDTLS_ERR_CCM_BAD_INPUT;
         }
 
-        dst += use_len;
-        src += use_len;
-        len_left -= use_len;
+        while (add_len > 0) {
+            offset = (ctx->processed + 2) % 16; /* account for y[0] and y[1]
+                                                 * holding total auth data length */
+            use_len = 16 - offset;
 
-        /*
-         * Increment counter.
-         * No need to check for overflow thanks to the length check above.
-         */
-        for( i = 0; i < q; i++ )
-            if( ++ctr[15-i] != 0 )
-                break;
+            if (use_len > add_len) {
+                use_len = add_len;
+            }
+
+            mbedtls_xor(ctx->y + offset, ctx->y + offset, add, use_len);
+
+            ctx->processed += use_len;
+            add_len -= use_len;
+            add += use_len;
+
+            if (use_len + offset == 16 || ctx->processed == ctx->add_len) {
+                if ((ret =
+                         mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen)) != 0) {
+                    ctx->state |= CCM_STATE__ERROR;
+                    return ret;
+                }
+            }
+        }
+
+        if (ctx->processed == ctx->add_len) {
+            ctx->state |= CCM_STATE__AUTH_DATA_FINISHED;
+            ctx->processed = 0; // prepare for mbedtls_ccm_update()
+        }
+    }
+
+    return 0;
+}
+
+int mbedtls_ccm_update(mbedtls_ccm_context *ctx,
+                       const unsigned char *input, size_t input_len,
+                       unsigned char *output, size_t output_size,
+                       size_t *output_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char i;
+    size_t use_len, offset, olen;
+
+    unsigned char local_output[16];
+
+    if (ctx->state & CCM_STATE__ERROR) {
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
+    }
+
+    /* Check against plaintext length only if performing operation with
+     * authentication
+     */
+    if (ctx->tag_len != 0 && ctx->processed + input_len > ctx->plaintext_len) {
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
+    }
+
+    if (output_size < input_len) {
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
+    }
+    *output_len = input_len;
+
+    ret = 0;
+
+    while (input_len > 0) {
+        offset = ctx->processed % 16;
+
+        use_len = 16 - offset;
+
+        if (use_len > input_len) {
+            use_len = input_len;
+        }
+
+        ctx->processed += use_len;
+
+        if (ctx->mode == MBEDTLS_CCM_ENCRYPT || \
+            ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT) {
+            mbedtls_xor(ctx->y + offset, ctx->y + offset, input, use_len);
+
+            if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) {
+                if ((ret =
+                         mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen)) != 0) {
+                    ctx->state |= CCM_STATE__ERROR;
+                    goto exit;
+                }
+            }
+
+            ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, output);
+            if (ret != 0) {
+                goto exit;
+            }
+        }
+
+        if (ctx->mode == MBEDTLS_CCM_DECRYPT || \
+            ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) {
+            /* Since output may be in shared memory, we cannot be sure that
+             * it will contain what we wrote to it. Therefore, we should avoid using
+             * it as input to any operations.
+             * Write decrypted data to local_output to avoid using output variable as
+             * input in the XOR operation for Y.
+             */
+            ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, local_output);
+            if (ret != 0) {
+                goto exit;
+            }
+
+            mbedtls_xor(ctx->y + offset, ctx->y + offset, local_output, use_len);
+
+            memcpy(output, local_output, use_len);
+            mbedtls_platform_zeroize(local_output, 16);
+
+            if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) {
+                if ((ret =
+                         mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen)) != 0) {
+                    ctx->state |= CCM_STATE__ERROR;
+                    goto exit;
+                }
+            }
+        }
+
+        if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) {
+            for (i = 0; i < ctx->q; i++) {
+                if (++(ctx->ctr)[15-i] != 0) {
+                    break;
+                }
+            }
+        }
+
+        input_len -= use_len;
+        input += use_len;
+        output += use_len;
+    }
+
+exit:
+    mbedtls_platform_zeroize(local_output, 16);
+
+    return ret;
+}
+
+int mbedtls_ccm_finish(mbedtls_ccm_context *ctx,
+                       unsigned char *tag, size_t tag_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char i;
+
+    if (ctx->state & CCM_STATE__ERROR) {
+        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    }
+
+    if (ctx->add_len > 0 && !(ctx->state & CCM_STATE__AUTH_DATA_FINISHED)) {
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
+    }
+
+    if (ctx->plaintext_len > 0 && ctx->processed != ctx->plaintext_len) {
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
     }
 
     /*
      * Authentication: reset counter and crypt/mask internal tag
      */
-    for( i = 0; i < q; i++ )
-        ctr[15-i] = 0;
+    for (i = 0; i < ctx->q; i++) {
+        ctx->ctr[15-i] = 0;
+    }
 
-    CTR_CRYPT( y, y, 16 );
-    memcpy( tag, y, tag_len );
+    ret = mbedtls_ccm_crypt(ctx, 0, 16, ctx->y, ctx->y);
+    if (ret != 0) {
+        return ret;
+    }
+    if (tag != NULL) {
+        memcpy(tag, ctx->y, tag_len);
+    }
+    mbedtls_ccm_clear_state(ctx);
 
-    return( 0 );
+    return 0;
+}
+
+/*
+ * Authenticated encryption or decryption
+ */
+static int ccm_auth_crypt(mbedtls_ccm_context *ctx, int mode, size_t length,
+                          const unsigned char *iv, size_t iv_len,
+                          const unsigned char *add, size_t add_len,
+                          const unsigned char *input, unsigned char *output,
+                          unsigned char *tag, size_t tag_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t olen;
+
+    if ((ret = mbedtls_ccm_starts(ctx, mode, iv, iv_len)) != 0) {
+        return ret;
+    }
+
+    if ((ret = mbedtls_ccm_set_lengths(ctx, add_len, length, tag_len)) != 0) {
+        return ret;
+    }
+
+    if ((ret = mbedtls_ccm_update_ad(ctx, add, add_len)) != 0) {
+        return ret;
+    }
+
+    if ((ret = mbedtls_ccm_update(ctx, input, length,
+                                  output, length, &olen)) != 0) {
+        return ret;
+    }
+
+    if ((ret = mbedtls_ccm_finish(ctx, tag, tag_len)) != 0) {
+        return ret;
+    }
+
+    return 0;
 }
 
 /*
  * Authenticated encryption
  */
-int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
-                         const unsigned char *iv, size_t iv_len,
-                         const unsigned char *add, size_t add_len,
-                         const unsigned char *input, unsigned char *output,
-                         unsigned char *tag, size_t tag_len )
+int mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length,
+                                     const unsigned char *iv, size_t iv_len,
+                                     const unsigned char *add, size_t add_len,
+                                     const unsigned char *input, unsigned char *output,
+                                     unsigned char *tag, size_t tag_len)
 {
-    CCM_VALIDATE_RET( ctx != NULL );
-    CCM_VALIDATE_RET( iv != NULL );
-    CCM_VALIDATE_RET( add_len == 0 || add != NULL );
-    CCM_VALIDATE_RET( length == 0 || input != NULL );
-    CCM_VALIDATE_RET( length == 0 || output != NULL );
-    CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
-    return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len,
-                            add, add_len, input, output, tag, tag_len ) );
+    return ccm_auth_crypt(ctx, MBEDTLS_CCM_STAR_ENCRYPT, length, iv, iv_len,
+                          add, add_len, input, output, tag, tag_len);
 }
 
-int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
-                         const unsigned char *iv, size_t iv_len,
-                         const unsigned char *add, size_t add_len,
-                         const unsigned char *input, unsigned char *output,
-                         unsigned char *tag, size_t tag_len )
+int mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length,
+                                const unsigned char *iv, size_t iv_len,
+                                const unsigned char *add, size_t add_len,
+                                const unsigned char *input, unsigned char *output,
+                                unsigned char *tag, size_t tag_len)
 {
-    CCM_VALIDATE_RET( ctx != NULL );
-    CCM_VALIDATE_RET( iv != NULL );
-    CCM_VALIDATE_RET( add_len == 0 || add != NULL );
-    CCM_VALIDATE_RET( length == 0 || input != NULL );
-    CCM_VALIDATE_RET( length == 0 || output != NULL );
-    CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
-    if( tag_len == 0 )
-        return( MBEDTLS_ERR_CCM_BAD_INPUT );
-
-    return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add,
-                add_len, input, output, tag, tag_len ) );
+    return ccm_auth_crypt(ctx, MBEDTLS_CCM_ENCRYPT, length, iv, iv_len,
+                          add, add_len, input, output, tag, tag_len);
 }
 
 /*
  * Authenticated decryption
  */
-int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
-                      const unsigned char *iv, size_t iv_len,
-                      const unsigned char *add, size_t add_len,
-                      const unsigned char *input, unsigned char *output,
-                      const unsigned char *tag, size_t tag_len )
+static int mbedtls_ccm_compare_tags(const unsigned char *tag1,
+                                    const unsigned char *tag2,
+                                    size_t tag_len)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char check_tag[16];
     unsigned char i;
     int diff;
 
-    CCM_VALIDATE_RET( ctx != NULL );
-    CCM_VALIDATE_RET( iv != NULL );
-    CCM_VALIDATE_RET( add_len == 0 || add != NULL );
-    CCM_VALIDATE_RET( length == 0 || input != NULL );
-    CCM_VALIDATE_RET( length == 0 || output != NULL );
-    CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
-
-    if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length,
-                                iv, iv_len, add, add_len,
-                                input, output, check_tag, tag_len ) ) != 0 )
-    {
-        return( ret );
-    }
-
     /* Check tag in "constant-time" */
-    for( diff = 0, i = 0; i < tag_len; i++ )
-        diff |= tag[i] ^ check_tag[i];
-
-    if( diff != 0 )
-    {
-        mbedtls_platform_zeroize( output, length );
-        return( MBEDTLS_ERR_CCM_AUTH_FAILED );
+    for (diff = 0, i = 0; i < tag_len; i++) {
+        diff |= tag1[i] ^ tag2[i];
     }
 
-    return( 0 );
+    if (diff != 0) {
+        return MBEDTLS_ERR_CCM_AUTH_FAILED;
+    }
+
+    return 0;
 }
 
-int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
-                      const unsigned char *iv, size_t iv_len,
-                      const unsigned char *add, size_t add_len,
-                      const unsigned char *input, unsigned char *output,
-                      const unsigned char *tag, size_t tag_len )
+static int ccm_auth_decrypt(mbedtls_ccm_context *ctx, int mode, size_t length,
+                            const unsigned char *iv, size_t iv_len,
+                            const unsigned char *add, size_t add_len,
+                            const unsigned char *input, unsigned char *output,
+                            const unsigned char *tag, size_t tag_len)
 {
-    CCM_VALIDATE_RET( ctx != NULL );
-    CCM_VALIDATE_RET( iv != NULL );
-    CCM_VALIDATE_RET( add_len == 0 || add != NULL );
-    CCM_VALIDATE_RET( length == 0 || input != NULL );
-    CCM_VALIDATE_RET( length == 0 || output != NULL );
-    CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char check_tag[16];
 
-    if( tag_len == 0 )
-        return( MBEDTLS_ERR_CCM_BAD_INPUT );
+    if ((ret = ccm_auth_crypt(ctx, mode, length,
+                              iv, iv_len, add, add_len,
+                              input, output, check_tag, tag_len)) != 0) {
+        return ret;
+    }
 
-    return( mbedtls_ccm_star_auth_decrypt( ctx, length, iv, iv_len, add,
-                add_len, input, output, tag, tag_len ) );
+    if ((ret = mbedtls_ccm_compare_tags(tag, check_tag, tag_len)) != 0) {
+        mbedtls_platform_zeroize(output, length);
+        return ret;
+    }
+
+    return 0;
+}
+
+int mbedtls_ccm_star_auth_decrypt(mbedtls_ccm_context *ctx, size_t length,
+                                  const unsigned char *iv, size_t iv_len,
+                                  const unsigned char *add, size_t add_len,
+                                  const unsigned char *input, unsigned char *output,
+                                  const unsigned char *tag, size_t tag_len)
+{
+    return ccm_auth_decrypt(ctx, MBEDTLS_CCM_STAR_DECRYPT, length,
+                            iv, iv_len, add, add_len,
+                            input, output, tag, tag_len);
+}
+
+int mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length,
+                             const unsigned char *iv, size_t iv_len,
+                             const unsigned char *add, size_t add_len,
+                             const unsigned char *input, unsigned char *output,
+                             const unsigned char *tag, size_t tag_len)
+{
+    return ccm_auth_decrypt(ctx, MBEDTLS_CCM_DECRYPT, length,
+                            iv, iv_len, add, add_len,
+                            input, output, tag, tag_len);
 }
 #endif /* !MBEDTLS_CCM_ALT */
 
@@ -446,7 +627,7 @@
     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
 };
 
-static const size_t iv_len_test_data [NB_TESTS] = { 7, 8,  12 };
+static const size_t iv_len_test_data[NB_TESTS] = { 7, 8,  12 };
 static const size_t add_len_test_data[NB_TESTS] = { 8, 16, 20 };
 static const size_t msg_len_test_data[NB_TESTS] = { 4, 16, 24 };
 static const size_t tag_len_test_data[NB_TESTS] = { 4, 6,  8  };
@@ -462,7 +643,7 @@
         0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 }
 };
 
-int mbedtls_ccm_self_test( int verbose )
+int mbedtls_ccm_self_test(int verbose)
 {
     mbedtls_ccm_context ctx;
     /*
@@ -475,70 +656,72 @@
     size_t i;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    mbedtls_ccm_init( &ctx );
+    mbedtls_ccm_init(&ctx);
 
-    if( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key_test_data,
-                            8 * sizeof key_test_data ) != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "  CCM: setup failed" );
-
-        return( 1 );
-    }
-
-    for( i = 0; i < NB_TESTS; i++ )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "  CCM-AES #%u: ", (unsigned int) i + 1 );
-
-        memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN );
-        memset( ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN );
-        memcpy( plaintext, msg_test_data, msg_len_test_data[i] );
-
-        ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len_test_data[i],
-                                           iv_test_data, iv_len_test_data[i],
-                                           ad_test_data, add_len_test_data[i],
-                                           plaintext, ciphertext,
-                                           ciphertext + msg_len_test_data[i],
-                                           tag_len_test_data[i] );
-
-        if( ret != 0 ||
-            memcmp( ciphertext, res_test_data[i],
-                    msg_len_test_data[i] + tag_len_test_data[i] ) != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "failed\n" );
-
-            return( 1 );
-        }
-        memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN );
-
-        ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len_test_data[i],
-                                        iv_test_data, iv_len_test_data[i],
-                                        ad_test_data, add_len_test_data[i],
-                                        ciphertext, plaintext,
-                                        ciphertext + msg_len_test_data[i],
-                                        tag_len_test_data[i] );
-
-        if( ret != 0 ||
-            memcmp( plaintext, msg_test_data, msg_len_test_data[i] ) != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "failed\n" );
-
-            return( 1 );
+    if (mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key_test_data,
+                           8 * sizeof(key_test_data)) != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("  CCM: setup failed");
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        return 1;
     }
 
-    mbedtls_ccm_free( &ctx );
+    for (i = 0; i < NB_TESTS; i++) {
+        if (verbose != 0) {
+            mbedtls_printf("  CCM-AES #%u: ", (unsigned int) i + 1);
+        }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+        memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN);
+        memset(ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN);
+        memcpy(plaintext, msg_test_data, msg_len_test_data[i]);
 
-    return( 0 );
+        ret = mbedtls_ccm_encrypt_and_tag(&ctx, msg_len_test_data[i],
+                                          iv_test_data, iv_len_test_data[i],
+                                          ad_test_data, add_len_test_data[i],
+                                          plaintext, ciphertext,
+                                          ciphertext + msg_len_test_data[i],
+                                          tag_len_test_data[i]);
+
+        if (ret != 0 ||
+            memcmp(ciphertext, res_test_data[i],
+                   msg_len_test_data[i] + tag_len_test_data[i]) != 0) {
+            if (verbose != 0) {
+                mbedtls_printf("failed\n");
+            }
+
+            return 1;
+        }
+        memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN);
+
+        ret = mbedtls_ccm_auth_decrypt(&ctx, msg_len_test_data[i],
+                                       iv_test_data, iv_len_test_data[i],
+                                       ad_test_data, add_len_test_data[i],
+                                       ciphertext, plaintext,
+                                       ciphertext + msg_len_test_data[i],
+                                       tag_len_test_data[i]);
+
+        if (ret != 0 ||
+            memcmp(plaintext, msg_test_data, msg_len_test_data[i]) != 0) {
+            if (verbose != 0) {
+                mbedtls_printf("failed\n");
+            }
+
+            return 1;
+        }
+
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
+    }
+
+    mbedtls_ccm_free(&ctx);
+
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
+
+    return 0;
 }
 
 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
diff --git a/lib/libmbedtls/mbedtls/library/certs.c b/lib/libmbedtls/mbedtls/library/certs.c
deleted file mode 100644
index a5695e3..0000000
--- a/lib/libmbedtls/mbedtls/library/certs.c
+++ /dev/null
@@ -1,1746 +0,0 @@
-/*
- *  X.509 test certificates
- *
- *  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.
- */
-
-#include "common.h"
-
-#include "mbedtls/certs.h"
-
-#if defined(MBEDTLS_CERTS_C)
-
-/*
- * Test CA Certificates
- *
- * We define test CA certificates for each choice of the following parameters:
- * - PEM or DER encoding
- * - SHA-1 or SHA-256 hash
- * - RSA or EC key
- *
- * Things to add:
- * - multiple EC curve types
- *
- */
-
-/* This is taken from tests/data_files/test-ca2.crt */
-/* BEGIN FILE string macro TEST_CA_CRT_EC_PEM tests/data_files/test-ca2.crt */
-#define TEST_CA_CRT_EC_PEM                                                 \
-    "-----BEGIN CERTIFICATE-----\r\n"                                      \
-    "MIICBDCCAYigAwIBAgIJAMFD4n5iQ8zoMAwGCCqGSM49BAMCBQAwPjELMAkGA1UE\r\n" \
-    "BhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRwwGgYDVQQDDBNQb2xhcnNzbCBUZXN0\r\n" \
-    "IEVDIENBMB4XDTE5MDIxMDE0NDQwMFoXDTI5MDIxMDE0NDQwMFowPjELMAkGA1UE\r\n" \
-    "BhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRwwGgYDVQQDDBNQb2xhcnNzbCBUZXN0\r\n" \
-    "IEVDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEw9orNEE3WC+HVv78ibopQ0tO\r\n" \
-    "4G7DDldTMzlY1FK0kZU5CyPfXxckYkj8GpUpziwth8KIUoCv1mqrId240xxuWLjK\r\n" \
-    "6LJpjvNBrSnDtF91p0dv1RkpVWmaUzsgtGYWYDMeo1AwTjAMBgNVHRMEBTADAQH/\r\n" \
-    "MB0GA1UdDgQWBBSdbSAkSQE/K8t4tRm8fiTJ2/s2fDAfBgNVHSMEGDAWgBSdbSAk\r\n" \
-    "SQE/K8t4tRm8fiTJ2/s2fDAMBggqhkjOPQQDAgUAA2gAMGUCMFHKrjAPpHB0BN1a\r\n" \
-    "LH8TwcJ3vh0AxeKZj30mRdOKBmg/jLS3rU3g8VQBHpn8sOTTBwIxANxPO5AerimZ\r\n" \
-    "hCjMe0d4CTHf1gFZMF70+IqEP+o5VHsIp2Cqvflb0VGWFC5l9a4cQg==\r\n"         \
-    "-----END CERTIFICATE-----\r\n"
-/* END FILE */
-
-/* This is generated from tests/data_files/test-ca2.crt.der using `xxd -i`. */
-/* BEGIN FILE binary macro TEST_CA_CRT_EC_DER tests/data_files/test-ca2.crt.der */
-#define TEST_CA_CRT_EC_DER {                                                 \
-  0x30, 0x82, 0x02, 0x04, 0x30, 0x82, 0x01, 0x88, 0xa0, 0x03, 0x02, 0x01,    \
-  0x02, 0x02, 0x09, 0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8,    \
-  0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,    \
-  0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,    \
-  0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,    \
-  0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c,    \
-  0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x50,    \
-  0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74,    \
-  0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39,    \
-  0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, 0x5a, 0x17,    \
-  0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30,    \
-  0x30, 0x5a, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,    \
-  0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,    \
-  0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c,    \
-  0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x50,    \
-  0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74,    \
-  0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07,    \
-  0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04,    \
-  0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xc3, 0xda, 0x2b, 0x34, 0x41, 0x37,    \
-  0x58, 0x2f, 0x87, 0x56, 0xfe, 0xfc, 0x89, 0xba, 0x29, 0x43, 0x4b, 0x4e,    \
-  0xe0, 0x6e, 0xc3, 0x0e, 0x57, 0x53, 0x33, 0x39, 0x58, 0xd4, 0x52, 0xb4,    \
-  0x91, 0x95, 0x39, 0x0b, 0x23, 0xdf, 0x5f, 0x17, 0x24, 0x62, 0x48, 0xfc,    \
-  0x1a, 0x95, 0x29, 0xce, 0x2c, 0x2d, 0x87, 0xc2, 0x88, 0x52, 0x80, 0xaf,    \
-  0xd6, 0x6a, 0xab, 0x21, 0xdd, 0xb8, 0xd3, 0x1c, 0x6e, 0x58, 0xb8, 0xca,    \
-  0xe8, 0xb2, 0x69, 0x8e, 0xf3, 0x41, 0xad, 0x29, 0xc3, 0xb4, 0x5f, 0x75,    \
-  0xa7, 0x47, 0x6f, 0xd5, 0x19, 0x29, 0x55, 0x69, 0x9a, 0x53, 0x3b, 0x20,    \
-  0xb4, 0x66, 0x16, 0x60, 0x33, 0x1e, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x0c,    \
-  0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff,    \
-  0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x9d,    \
-  0x6d, 0x20, 0x24, 0x49, 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc,    \
-  0x7e, 0x24, 0xc9, 0xdb, 0xfb, 0x36, 0x7c, 0x30, 0x1f, 0x06, 0x03, 0x55,    \
-  0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24,    \
-  0x49, 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9,    \
-  0xdb, 0xfb, 0x36, 0x7c, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,    \
-  0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02,    \
-  0x30, 0x51, 0xca, 0xae, 0x30, 0x0f, 0xa4, 0x70, 0x74, 0x04, 0xdd, 0x5a,    \
-  0x2c, 0x7f, 0x13, 0xc1, 0xc2, 0x77, 0xbe, 0x1d, 0x00, 0xc5, 0xe2, 0x99,    \
-  0x8f, 0x7d, 0x26, 0x45, 0xd3, 0x8a, 0x06, 0x68, 0x3f, 0x8c, 0xb4, 0xb7,    \
-  0xad, 0x4d, 0xe0, 0xf1, 0x54, 0x01, 0x1e, 0x99, 0xfc, 0xb0, 0xe4, 0xd3,    \
-  0x07, 0x02, 0x31, 0x00, 0xdc, 0x4f, 0x3b, 0x90, 0x1e, 0xae, 0x29, 0x99,    \
-  0x84, 0x28, 0xcc, 0x7b, 0x47, 0x78, 0x09, 0x31, 0xdf, 0xd6, 0x01, 0x59,    \
-  0x30, 0x5e, 0xf4, 0xf8, 0x8a, 0x84, 0x3f, 0xea, 0x39, 0x54, 0x7b, 0x08,    \
-  0xa7, 0x60, 0xaa, 0xbd, 0xf9, 0x5b, 0xd1, 0x51, 0x96, 0x14, 0x2e, 0x65,    \
-  0xf5, 0xae, 0x1c, 0x42                                                     \
-}
-/* END FILE */
-
-/* This is taken from tests/data_files/test-ca2.key.enc */
-/* BEGIN FILE string macro TEST_CA_KEY_EC_PEM tests/data_files/test-ca2.key.enc */
-#define TEST_CA_KEY_EC_PEM                                                 \
-    "-----BEGIN EC PRIVATE KEY-----\r\n"                                   \
-    "Proc-Type: 4,ENCRYPTED\r\n"                                           \
-    "DEK-Info: DES-EDE3-CBC,307EAB469933D64E\r\n"                          \
-    "\r\n"                                                                 \
-    "IxbrRmKcAzctJqPdTQLA4SWyBYYGYJVkYEna+F7Pa5t5Yg/gKADrFKcm6B72e7DG\r\n" \
-    "ihExtZI648s0zdYw6qSJ74vrPSuWDe5qm93BqsfVH9svtCzWHW0pm1p0KTBCFfUq\r\n" \
-    "UsuWTITwJImcnlAs1gaRZ3sAWm7cOUidL0fo2G0fYUFNcYoCSLffCFTEHBuPnagb\r\n" \
-    "a77x/sY1Bvii8S9/XhDTb6pTMx06wzrm\r\n"                                 \
-    "-----END EC PRIVATE KEY-----\r\n"
-/* END FILE */
-
-#define TEST_CA_PWD_EC_PEM "PolarSSLTest"
-
-/* This is generated from tests/data_files/test-ca2.key.der using `xxd -i`. */
-/* BEGIN FILE binary macro TEST_CA_KEY_EC_DER tests/data_files/test-ca2.key.der */
-#define TEST_CA_KEY_EC_DER {                                                 \
-    0x30, 0x81, 0xa4, 0x02, 0x01, 0x01, 0x04, 0x30, 0x83, 0xd9, 0x15, 0x0e,  \
-    0xa0, 0x71, 0xf0, 0x57, 0x10, 0x33, 0xa3, 0x38, 0xb8, 0x86, 0xc1, 0xa6,  \
-    0x11, 0x5d, 0x6d, 0xb4, 0x03, 0xe1, 0x29, 0x76, 0x45, 0xd7, 0x87, 0x6f,  \
-    0x23, 0xab, 0x44, 0x20, 0xea, 0x64, 0x7b, 0x85, 0xb1, 0x76, 0xe7, 0x85,  \
-    0x95, 0xaa, 0x74, 0xd6, 0xd1, 0xa4, 0x5e, 0xea, 0xa0, 0x07, 0x06, 0x05,  \
-    0x2b, 0x81, 0x04, 0x00, 0x22, 0xa1, 0x64, 0x03, 0x62, 0x00, 0x04, 0xc3,  \
-    0xda, 0x2b, 0x34, 0x41, 0x37, 0x58, 0x2f, 0x87, 0x56, 0xfe, 0xfc, 0x89,  \
-    0xba, 0x29, 0x43, 0x4b, 0x4e, 0xe0, 0x6e, 0xc3, 0x0e, 0x57, 0x53, 0x33,  \
-    0x39, 0x58, 0xd4, 0x52, 0xb4, 0x91, 0x95, 0x39, 0x0b, 0x23, 0xdf, 0x5f,  \
-    0x17, 0x24, 0x62, 0x48, 0xfc, 0x1a, 0x95, 0x29, 0xce, 0x2c, 0x2d, 0x87,  \
-    0xc2, 0x88, 0x52, 0x80, 0xaf, 0xd6, 0x6a, 0xab, 0x21, 0xdd, 0xb8, 0xd3,  \
-    0x1c, 0x6e, 0x58, 0xb8, 0xca, 0xe8, 0xb2, 0x69, 0x8e, 0xf3, 0x41, 0xad,  \
-    0x29, 0xc3, 0xb4, 0x5f, 0x75, 0xa7, 0x47, 0x6f, 0xd5, 0x19, 0x29, 0x55,  \
-    0x69, 0x9a, 0x53, 0x3b, 0x20, 0xb4, 0x66, 0x16, 0x60, 0x33, 0x1e         \
-}
-/* END FILE */
-
-/* This is taken from tests/data_files/test-ca-sha256.crt. */
-/* BEGIN FILE string macro TEST_CA_CRT_RSA_SHA256_PEM tests/data_files/test-ca-sha256.crt */
-#define TEST_CA_CRT_RSA_SHA256_PEM                                         \
-    "-----BEGIN CERTIFICATE-----\r\n"                                      \
-    "MIIDQTCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \
-    "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \
-    "MTkwMjEwMTQ0NDAwWhcNMjkwMjEwMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \
-    "A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \
-    "CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \
-    "mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \
-    "50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \
-    "YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \
-    "R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \
-    "KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \
-    "UDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/\r\n" \
-    "MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEBCwUA\r\n" \
-    "A4IBAQA4qFSCth2q22uJIdE4KGHJsJjVEfw2/xn+MkTvCMfxVrvmRvqCtjE4tKDl\r\n" \
-    "oK4MxFOek07oDZwvtAT9ijn1hHftTNS7RH9zd/fxNpfcHnMZXVC4w4DNA1fSANtW\r\n" \
-    "5sY1JB5Je9jScrsLSS+mAjyv0Ow3Hb2Bix8wu7xNNrV5fIf7Ubm+wt6SqEBxu3Kb\r\n" \
-    "+EfObAT4huf3czznhH3C17ed6NSbXwoXfby7stWUDeRJv08RaFOykf/Aae7bY5PL\r\n" \
-    "yTVrkAnikMntJ9YI+hNNYt3inqq11A5cN0+rVTst8UKCxzQ4GpvroSwPKTFkbMw4\r\n" \
-    "/anT1dVxr/BtwJfiESoK3/4CeXR1\r\n"                                     \
-    "-----END CERTIFICATE-----\r\n"
-/* END FILE */
-
-/* This is generated from tests/data_files/test-ca-sha256.crt.der
- * using `xxd -i`. */
-/* BEGIN FILE binary macro TEST_CA_CRT_RSA_SHA256_DER tests/data_files/test-ca-sha256.crt.der */
-#define TEST_CA_CRT_RSA_SHA256_DER {                                         \
-  0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xa0, 0x03, 0x02, 0x01,    \
-  0x02, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,    \
-  0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30,    \
-  0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11,    \
-  0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c,    \
-  0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55,    \
-  0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c,    \
-  0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d,    \
-  0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30,    \
-  0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34,    \
-  0x34, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,    \
-  0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06,    \
-  0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53,    \
-  0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,    \
-  0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x54, 0x65,    \
-  0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06,    \
-  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,    \
-  0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01,    \
-  0x01, 0x00, 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f,    \
-  0x86, 0xde, 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1,    \
-  0x99, 0xd4, 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec,    \
-  0x9b, 0xc5, 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b,    \
-  0xc0, 0x8d, 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9,    \
-  0x93, 0xe8, 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2,    \
-  0xe7, 0x40, 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40,    \
-  0xf9, 0x3e, 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8,    \
-  0x29, 0x00, 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1,    \
-  0xbd, 0x83, 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27,    \
-  0x60, 0xc3, 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84,    \
-  0x32, 0xbe, 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5,    \
-  0xfb, 0xf5, 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e,    \
-  0xee, 0xe2, 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb,    \
-  0x47, 0xb1, 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab,    \
-  0xf1, 0x79, 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62,    \
-  0x6f, 0x27, 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37,    \
-  0xa1, 0x30, 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e,    \
-  0x28, 0xd1, 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64,    \
-  0x09, 0xea, 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b,    \
-  0xc9, 0xab, 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32,    \
-  0x9e, 0x99, 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3,    \
-  0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,    \
-  0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,    \
-  0x04, 0x16, 0x04, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52,    \
-  0xf6, 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff,    \
-  0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,    \
-  0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5,    \
-  0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06,    \
-  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00,    \
-  0x03, 0x82, 0x01, 0x01, 0x00, 0x38, 0xa8, 0x54, 0x82, 0xb6, 0x1d, 0xaa,    \
-  0xdb, 0x6b, 0x89, 0x21, 0xd1, 0x38, 0x28, 0x61, 0xc9, 0xb0, 0x98, 0xd5,    \
-  0x11, 0xfc, 0x36, 0xff, 0x19, 0xfe, 0x32, 0x44, 0xef, 0x08, 0xc7, 0xf1,    \
-  0x56, 0xbb, 0xe6, 0x46, 0xfa, 0x82, 0xb6, 0x31, 0x38, 0xb4, 0xa0, 0xe5,    \
-  0xa0, 0xae, 0x0c, 0xc4, 0x53, 0x9e, 0x93, 0x4e, 0xe8, 0x0d, 0x9c, 0x2f,    \
-  0xb4, 0x04, 0xfd, 0x8a, 0x39, 0xf5, 0x84, 0x77, 0xed, 0x4c, 0xd4, 0xbb,    \
-  0x44, 0x7f, 0x73, 0x77, 0xf7, 0xf1, 0x36, 0x97, 0xdc, 0x1e, 0x73, 0x19,    \
-  0x5d, 0x50, 0xb8, 0xc3, 0x80, 0xcd, 0x03, 0x57, 0xd2, 0x00, 0xdb, 0x56,    \
-  0xe6, 0xc6, 0x35, 0x24, 0x1e, 0x49, 0x7b, 0xd8, 0xd2, 0x72, 0xbb, 0x0b,    \
-  0x49, 0x2f, 0xa6, 0x02, 0x3c, 0xaf, 0xd0, 0xec, 0x37, 0x1d, 0xbd, 0x81,    \
-  0x8b, 0x1f, 0x30, 0xbb, 0xbc, 0x4d, 0x36, 0xb5, 0x79, 0x7c, 0x87, 0xfb,    \
-  0x51, 0xb9, 0xbe, 0xc2, 0xde, 0x92, 0xa8, 0x40, 0x71, 0xbb, 0x72, 0x9b,    \
-  0xf8, 0x47, 0xce, 0x6c, 0x04, 0xf8, 0x86, 0xe7, 0xf7, 0x73, 0x3c, 0xe7,    \
-  0x84, 0x7d, 0xc2, 0xd7, 0xb7, 0x9d, 0xe8, 0xd4, 0x9b, 0x5f, 0x0a, 0x17,    \
-  0x7d, 0xbc, 0xbb, 0xb2, 0xd5, 0x94, 0x0d, 0xe4, 0x49, 0xbf, 0x4f, 0x11,    \
-  0x68, 0x53, 0xb2, 0x91, 0xff, 0xc0, 0x69, 0xee, 0xdb, 0x63, 0x93, 0xcb,    \
-  0xc9, 0x35, 0x6b, 0x90, 0x09, 0xe2, 0x90, 0xc9, 0xed, 0x27, 0xd6, 0x08,    \
-  0xfa, 0x13, 0x4d, 0x62, 0xdd, 0xe2, 0x9e, 0xaa, 0xb5, 0xd4, 0x0e, 0x5c,    \
-  0x37, 0x4f, 0xab, 0x55, 0x3b, 0x2d, 0xf1, 0x42, 0x82, 0xc7, 0x34, 0x38,    \
-  0x1a, 0x9b, 0xeb, 0xa1, 0x2c, 0x0f, 0x29, 0x31, 0x64, 0x6c, 0xcc, 0x38,    \
-  0xfd, 0xa9, 0xd3, 0xd5, 0xd5, 0x71, 0xaf, 0xf0, 0x6d, 0xc0, 0x97, 0xe2,    \
-  0x11, 0x2a, 0x0a, 0xdf, 0xfe, 0x02, 0x79, 0x74, 0x75                       \
-}
-/* END FILE */
-
-/* This is taken from tests/data_files/test-ca-sha1.crt. */
-/* BEGIN FILE string macro TEST_CA_CRT_RSA_SHA1_PEM tests/data_files/test-ca-sha1.crt */
-#define TEST_CA_CRT_RSA_SHA1_PEM                                           \
-    "-----BEGIN CERTIFICATE-----\r\n"                                      \
-    "MIIDQTCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \
-    "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \
-    "MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \
-    "A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \
-    "CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \
-    "mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \
-    "50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \
-    "YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \
-    "R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \
-    "KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \
-    "UDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/\r\n" \
-    "MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEBBQUA\r\n" \
-    "A4IBAQABE3OEPfEd/bcJW5ZdU3/VgPNS4tMzh8gnJP/V2FcvFtGylMpQq6YnEBYI\r\n" \
-    "yBHAL4DRvlMY5rnXGBp3ODR8MpqHC6AquRTCLzjS57iYff//4QFQqW9n92zctspv\r\n" \
-    "czkaPKgjqo1No3Uq0Xaz10rcxyTUPrf5wNVRZ2V0KvllvAAVSzbI4mpdUXztjhST\r\n" \
-    "S5A2BeWQAAOr0zq1F7TSRVJpJs7jmB2ai/igkh1IAjcuwV6VwlP+sbw0gjQ0NpGM\r\n" \
-    "iHpnlzRAi/tIbtOvMIGOBU2TIfax/5jq1agUx5aPmT5TWAiJPOOP6l5xXnDwxeYS\r\n" \
-    "NWqiX9GyusBZjezaCaHabjDLU0qQ\r\n"                                     \
-    "-----END CERTIFICATE-----\r\n"
-/* END FILE */
-
-/* This is taken from tests/data_files/test-ca-sha1.crt.der. */
-/* BEGIN FILE binary macro TEST_CA_CRT_RSA_SHA1_DER tests/data_files/test-ca-sha1.crt.der */
-#define TEST_CA_CRT_RSA_SHA1_DER {                                           \
-    0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xa0, 0x03, 0x02, 0x01,  \
-    0x02, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,  \
-    0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30,  \
-    0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11,  \
-    0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c,  \
-    0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55,  \
-    0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c,  \
-    0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d,  \
-    0x31, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30,  \
-    0x5a, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34,  \
-    0x34, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,  \
-    0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06,  \
-    0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53,  \
-    0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,  \
-    0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x54, 0x65,  \
-    0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06,  \
-    0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,  \
-    0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01,  \
-    0x01, 0x00, 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f,  \
-    0x86, 0xde, 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1,  \
-    0x99, 0xd4, 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec,  \
-    0x9b, 0xc5, 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b,  \
-    0xc0, 0x8d, 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9,  \
-    0x93, 0xe8, 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2,  \
-    0xe7, 0x40, 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40,  \
-    0xf9, 0x3e, 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8,  \
-    0x29, 0x00, 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1,  \
-    0xbd, 0x83, 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27,  \
-    0x60, 0xc3, 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84,  \
-    0x32, 0xbe, 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5,  \
-    0xfb, 0xf5, 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e,  \
-    0xee, 0xe2, 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb,  \
-    0x47, 0xb1, 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab,  \
-    0xf1, 0x79, 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62,  \
-    0x6f, 0x27, 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37,  \
-    0xa1, 0x30, 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e,  \
-    0x28, 0xd1, 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64,  \
-    0x09, 0xea, 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b,  \
-    0xc9, 0xab, 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32,  \
-    0x9e, 0x99, 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3,  \
-    0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05,  \
-    0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,  \
-    0x04, 0x16, 0x04, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52,  \
-    0xf6, 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff,  \
-    0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,  \
-    0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5,  \
-    0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06,  \
-    0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,  \
-    0x03, 0x82, 0x01, 0x01, 0x00, 0x01, 0x13, 0x73, 0x84, 0x3d, 0xf1, 0x1d,  \
-    0xfd, 0xb7, 0x09, 0x5b, 0x96, 0x5d, 0x53, 0x7f, 0xd5, 0x80, 0xf3, 0x52,  \
-    0xe2, 0xd3, 0x33, 0x87, 0xc8, 0x27, 0x24, 0xff, 0xd5, 0xd8, 0x57, 0x2f,  \
-    0x16, 0xd1, 0xb2, 0x94, 0xca, 0x50, 0xab, 0xa6, 0x27, 0x10, 0x16, 0x08,  \
-    0xc8, 0x11, 0xc0, 0x2f, 0x80, 0xd1, 0xbe, 0x53, 0x18, 0xe6, 0xb9, 0xd7,  \
-    0x18, 0x1a, 0x77, 0x38, 0x34, 0x7c, 0x32, 0x9a, 0x87, 0x0b, 0xa0, 0x2a,  \
-    0xb9, 0x14, 0xc2, 0x2f, 0x38, 0xd2, 0xe7, 0xb8, 0x98, 0x7d, 0xff, 0xff,  \
-    0xe1, 0x01, 0x50, 0xa9, 0x6f, 0x67, 0xf7, 0x6c, 0xdc, 0xb6, 0xca, 0x6f,  \
-    0x73, 0x39, 0x1a, 0x3c, 0xa8, 0x23, 0xaa, 0x8d, 0x4d, 0xa3, 0x75, 0x2a,  \
-    0xd1, 0x76, 0xb3, 0xd7, 0x4a, 0xdc, 0xc7, 0x24, 0xd4, 0x3e, 0xb7, 0xf9,  \
-    0xc0, 0xd5, 0x51, 0x67, 0x65, 0x74, 0x2a, 0xf9, 0x65, 0xbc, 0x00, 0x15,  \
-    0x4b, 0x36, 0xc8, 0xe2, 0x6a, 0x5d, 0x51, 0x7c, 0xed, 0x8e, 0x14, 0x93,  \
-    0x4b, 0x90, 0x36, 0x05, 0xe5, 0x90, 0x00, 0x03, 0xab, 0xd3, 0x3a, 0xb5,  \
-    0x17, 0xb4, 0xd2, 0x45, 0x52, 0x69, 0x26, 0xce, 0xe3, 0x98, 0x1d, 0x9a,  \
-    0x8b, 0xf8, 0xa0, 0x92, 0x1d, 0x48, 0x02, 0x37, 0x2e, 0xc1, 0x5e, 0x95,  \
-    0xc2, 0x53, 0xfe, 0xb1, 0xbc, 0x34, 0x82, 0x34, 0x34, 0x36, 0x91, 0x8c,  \
-    0x88, 0x7a, 0x67, 0x97, 0x34, 0x40, 0x8b, 0xfb, 0x48, 0x6e, 0xd3, 0xaf,  \
-    0x30, 0x81, 0x8e, 0x05, 0x4d, 0x93, 0x21, 0xf6, 0xb1, 0xff, 0x98, 0xea,  \
-    0xd5, 0xa8, 0x14, 0xc7, 0x96, 0x8f, 0x99, 0x3e, 0x53, 0x58, 0x08, 0x89,  \
-    0x3c, 0xe3, 0x8f, 0xea, 0x5e, 0x71, 0x5e, 0x70, 0xf0, 0xc5, 0xe6, 0x12,  \
-    0x35, 0x6a, 0xa2, 0x5f, 0xd1, 0xb2, 0xba, 0xc0, 0x59, 0x8d, 0xec, 0xda,  \
-    0x09, 0xa1, 0xda, 0x6e, 0x30, 0xcb, 0x53, 0x4a, 0x90                     \
-}
-/* END FILE */
-
-/* This is taken from tests/data_files/test-ca.key */
-/* BEGIN FILE string macro TEST_CA_KEY_RSA_PEM tests/data_files/test-ca.key */
-#define TEST_CA_KEY_RSA_PEM                                                \
-    "-----BEGIN RSA PRIVATE KEY-----\r\n"                                  \
-    "Proc-Type: 4,ENCRYPTED\r\n"                                           \
-    "DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n"                          \
-    "\r\n"                                                                 \
-    "9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n" \
-    "7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n" \
-    "Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n" \
-    "PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n" \
-    "GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n" \
-    "gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n" \
-    "QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n" \
-    "PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n" \
-    "vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n" \
-    "WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n" \
-    "JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n" \
-    "KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n" \
-    "Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n" \
-    "9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n" \
-    "iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n" \
-    "tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n" \
-    "P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n" \
-    "1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n" \
-    "nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n" \
-    "X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n" \
-    "rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n" \
-    "L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n" \
-    "I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n" \
-    "wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n" \
-    "P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n" \
-    "-----END RSA PRIVATE KEY-----\r\n"
-/* END FILE */
-
-#define TEST_CA_PWD_RSA_PEM "PolarSSLTest"
-
-/* This was generated from test-ca.key.der using `xxd -i`. */
-/* BEGIN FILE binary macro TEST_CA_KEY_RSA_DER tests/data_files/test-ca.key.der */
-#define TEST_CA_KEY_RSA_DER {                                                \
-    0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,  \
-    0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, 0x86, 0xde,  \
-    0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, 0x99, 0xd4,  \
-    0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, 0x9b, 0xc5,  \
-    0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, 0xc0, 0x8d,  \
-    0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, 0x93, 0xe8,  \
-    0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, 0xe7, 0x40,  \
-    0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, 0xf9, 0x3e,  \
-    0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, 0x29, 0x00,  \
-    0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, 0xbd, 0x83,  \
-    0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, 0x60, 0xc3,  \
-    0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, 0x32, 0xbe,  \
-    0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, 0xfb, 0xf5,  \
-    0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, 0xee, 0xe2,  \
-    0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, 0x47, 0xb1,  \
-    0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, 0xf1, 0x79,  \
-    0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, 0x6f, 0x27,  \
-    0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, 0xa1, 0x30,  \
-    0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, 0x28, 0xd1,  \
-    0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, 0x09, 0xea,  \
-    0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, 0xc9, 0xab,  \
-    0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, 0x9e, 0x99,  \
-    0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01,  \
-    0x00, 0x3f, 0xf7, 0x07, 0xd3, 0x34, 0x6f, 0xdb, 0xc9, 0x37, 0xb7, 0x84,  \
-    0xdc, 0x37, 0x45, 0xe1, 0x63, 0xad, 0xb8, 0xb6, 0x75, 0xb1, 0xc7, 0x35,  \
-    0xb4, 0x77, 0x2a, 0x5b, 0x77, 0xf9, 0x7e, 0xe0, 0xc1, 0xa3, 0xd1, 0xb7,  \
-    0xcb, 0xa9, 0x5a, 0xc1, 0x87, 0xda, 0x5a, 0xfa, 0x17, 0xe4, 0xd5, 0x38,  \
-    0x03, 0xde, 0x68, 0x98, 0x81, 0xec, 0xb5, 0xf2, 0x2a, 0x8d, 0xe9, 0x2c,  \
-    0xf3, 0xa6, 0xe5, 0x32, 0x17, 0x7f, 0x33, 0x81, 0xe8, 0x38, 0x72, 0xd5,  \
-    0x9c, 0xfa, 0x4e, 0xfb, 0x26, 0xf5, 0x15, 0x0b, 0xaf, 0x84, 0x66, 0xab,  \
-    0x02, 0xe0, 0x18, 0xd5, 0x91, 0x7c, 0xd6, 0x8f, 0xc9, 0x4b, 0x76, 0x08,  \
-    0x2b, 0x1d, 0x81, 0x68, 0x30, 0xe1, 0xfa, 0x70, 0x6c, 0x13, 0x4e, 0x10,  \
-    0x03, 0x35, 0x3e, 0xc5, 0xca, 0x58, 0x20, 0x8a, 0x21, 0x18, 0x38, 0xa0,  \
-    0x0f, 0xed, 0xc4, 0xbb, 0x45, 0x6f, 0xf5, 0x84, 0x5b, 0xb0, 0xcf, 0x4e,  \
-    0x9d, 0x58, 0x13, 0x6b, 0x35, 0x35, 0x69, 0xa1, 0xd2, 0xc4, 0xf2, 0xc1,  \
-    0x48, 0x04, 0x20, 0x51, 0xb9, 0x6b, 0xa4, 0x5d, 0xa5, 0x4b, 0x84, 0x88,  \
-    0x43, 0x48, 0x99, 0x2c, 0xbb, 0xa4, 0x97, 0xd6, 0xd6, 0x18, 0xf6, 0xec,  \
-    0x5c, 0xd1, 0x31, 0x49, 0xc9, 0xf2, 0x8f, 0x0b, 0x4d, 0xef, 0x09, 0x02,  \
-    0xfe, 0x7d, 0xfd, 0xbb, 0xaf, 0x2b, 0x83, 0x94, 0x22, 0xc4, 0xa7, 0x3e,  \
-    0x66, 0xf5, 0xe0, 0x57, 0xdc, 0xf2, 0xed, 0x2c, 0x3e, 0x81, 0x74, 0x76,  \
-    0x1e, 0x96, 0x6f, 0x74, 0x1e, 0x32, 0x0e, 0x14, 0x31, 0xd0, 0x74, 0xf0,  \
-    0xf4, 0x07, 0xbd, 0xc3, 0xd1, 0x22, 0xc2, 0xa8, 0x95, 0x92, 0x06, 0x7f,  \
-    0x43, 0x02, 0x91, 0xbc, 0xdd, 0x23, 0x01, 0x89, 0x94, 0x20, 0x44, 0x64,  \
-    0xf5, 0x1d, 0x67, 0xd2, 0x8f, 0xe8, 0x69, 0xa5, 0x29, 0x25, 0xe6, 0x50,  \
-    0x9c, 0xe3, 0xe9, 0xcb, 0x75, 0x02, 0x81, 0x81, 0x00, 0xe2, 0x29, 0x3e,  \
-    0xaa, 0x6b, 0xd5, 0x59, 0x1e, 0x9c, 0xe6, 0x47, 0xd5, 0xb6, 0xd7, 0xe3,  \
-    0xf1, 0x8e, 0x9e, 0xe9, 0x83, 0x5f, 0x10, 0x9f, 0x63, 0xec, 0x04, 0x44,  \
-    0xcc, 0x3f, 0xf8, 0xd9, 0x3a, 0x17, 0xe0, 0x4f, 0xfe, 0xd8, 0x4d, 0xcd,  \
-    0x46, 0x54, 0x74, 0xbf, 0x0a, 0xc4, 0x67, 0x9c, 0xa7, 0xd8, 0x89, 0x65,  \
-    0x4c, 0xfd, 0x58, 0x2a, 0x47, 0x0f, 0xf4, 0x37, 0xb6, 0x55, 0xb0, 0x1d,  \
-    0xed, 0xa7, 0x39, 0xfc, 0x4f, 0xa3, 0xc4, 0x75, 0x3a, 0xa3, 0x98, 0xa7,  \
-    0x45, 0xf5, 0x66, 0xcb, 0x7c, 0x65, 0xfb, 0x80, 0x23, 0xe6, 0xff, 0xfd,  \
-    0x99, 0x1f, 0x8e, 0x6b, 0xff, 0x5e, 0x93, 0x66, 0xdf, 0x6c, 0x6f, 0xc3,  \
-    0xf6, 0x38, 0x2e, 0xff, 0x69, 0xb5, 0xac, 0xae, 0xbb, 0xc6, 0x71, 0x16,  \
-    0x6b, 0xd0, 0xf8, 0x22, 0xd9, 0xf8, 0xa2, 0x72, 0x20, 0xd2, 0xe2, 0x3a,  \
-    0x70, 0x4b, 0xde, 0xab, 0x2f, 0x02, 0x81, 0x81, 0x00, 0xda, 0x51, 0x9b,  \
-    0xb8, 0xb2, 0x2a, 0x14, 0x75, 0x58, 0x40, 0x8d, 0x27, 0x70, 0xfa, 0x31,  \
-    0x48, 0xb0, 0x20, 0x21, 0x34, 0xfa, 0x4c, 0x57, 0xa8, 0x11, 0x88, 0xf3,  \
-    0xa7, 0xae, 0x21, 0xe9, 0xb6, 0x2b, 0xd1, 0xcd, 0xa7, 0xf8, 0xd8, 0x0c,  \
-    0x8a, 0x76, 0x22, 0x35, 0x44, 0xce, 0x3f, 0x25, 0x29, 0x83, 0x7d, 0x79,  \
-    0xa7, 0x31, 0xd6, 0xec, 0xb2, 0xbf, 0xda, 0x34, 0xb6, 0xf6, 0xb2, 0x3b,  \
-    0xf3, 0x78, 0x5a, 0x04, 0x83, 0x33, 0x3e, 0xa2, 0xe2, 0x81, 0x82, 0x13,  \
-    0xd4, 0x35, 0x17, 0x63, 0x9b, 0x9e, 0xc4, 0x8d, 0x91, 0x4c, 0x03, 0x77,  \
-    0xc7, 0x71, 0x5b, 0xee, 0x83, 0x6d, 0xd5, 0x78, 0x88, 0xf6, 0x2c, 0x79,  \
-    0xc2, 0x4a, 0xb4, 0x79, 0x90, 0x70, 0xbf, 0xdf, 0x34, 0x56, 0x96, 0x71,  \
-    0xe3, 0x0e, 0x68, 0x91, 0xbc, 0xea, 0xcb, 0x33, 0xc0, 0xbe, 0x45, 0xd7,  \
-    0xfc, 0x30, 0xfd, 0x01, 0x3b, 0x02, 0x81, 0x81, 0x00, 0xd2, 0x9f, 0x2a,  \
-    0xb7, 0x38, 0x19, 0xc7, 0x17, 0x95, 0x73, 0x78, 0xae, 0xf5, 0xcb, 0x75,  \
-    0x83, 0x7f, 0x19, 0x4b, 0xcb, 0x86, 0xfb, 0x4a, 0x15, 0x9a, 0xb6, 0x17,  \
-    0x04, 0x49, 0x07, 0x8d, 0xf6, 0x66, 0x4a, 0x06, 0xf6, 0x05, 0xa7, 0xdf,  \
-    0x66, 0x82, 0x3c, 0xff, 0xb6, 0x1d, 0x57, 0x89, 0x33, 0x5f, 0x9c, 0x05,  \
-    0x75, 0x7f, 0xf3, 0x5d, 0xdc, 0x34, 0x65, 0x72, 0x85, 0x22, 0xa4, 0x14,  \
-    0x1b, 0x41, 0xc3, 0xe4, 0xd0, 0x9e, 0x69, 0xd5, 0xeb, 0x38, 0x74, 0x70,  \
-    0x43, 0xdc, 0xd9, 0x50, 0xe4, 0x97, 0x6d, 0x73, 0xd6, 0xfb, 0xc8, 0xa7,  \
-    0xfa, 0xb4, 0xc2, 0xc4, 0x9d, 0x5d, 0x0c, 0xd5, 0x9f, 0x79, 0xb3, 0x54,  \
-    0xc2, 0xb7, 0x6c, 0x3d, 0x7d, 0xcb, 0x2d, 0xf8, 0xc4, 0xf3, 0x78, 0x5a,  \
-    0x33, 0x2a, 0xb8, 0x0c, 0x6d, 0x06, 0xfa, 0xf2, 0x62, 0xd3, 0x42, 0xd0,  \
-    0xbd, 0xc8, 0x4a, 0xa5, 0x0d, 0x02, 0x81, 0x81, 0x00, 0xd4, 0xa9, 0x90,  \
-    0x15, 0xde, 0xbf, 0x2c, 0xc4, 0x8d, 0x9d, 0xfb, 0xa1, 0xc2, 0xe4, 0x83,  \
-    0xe3, 0x79, 0x65, 0x22, 0xd3, 0xb7, 0x49, 0x6c, 0x4d, 0x94, 0x1f, 0x22,  \
-    0xb1, 0x60, 0xe7, 0x3a, 0x00, 0xb1, 0x38, 0xa2, 0xab, 0x0f, 0xb4, 0x6c,  \
-    0xaa, 0xe7, 0x9e, 0x34, 0xe3, 0x7c, 0x40, 0x78, 0x53, 0xb2, 0xf9, 0x23,  \
-    0xea, 0xa0, 0x9a, 0xea, 0x60, 0xc8, 0x8f, 0xa6, 0xaf, 0xdf, 0x29, 0x09,  \
-    0x4b, 0x06, 0x1e, 0x31, 0xad, 0x17, 0xda, 0xd8, 0xd1, 0xe9, 0x33, 0xab,  \
-    0x5b, 0x18, 0x08, 0x5b, 0x87, 0xf8, 0xa5, 0x1f, 0xfd, 0xbb, 0xdc, 0xd8,  \
-    0xed, 0x97, 0x57, 0xe4, 0xc3, 0x73, 0xd6, 0xf0, 0x9e, 0x01, 0xa6, 0x9b,  \
-    0x48, 0x8e, 0x7a, 0xb4, 0xbb, 0xe5, 0x88, 0x91, 0xc5, 0x2a, 0xdf, 0x4b,  \
-    0xba, 0xd0, 0x8b, 0x3e, 0x03, 0x97, 0x77, 0x2f, 0x47, 0x7e, 0x51, 0x0c,  \
-    0xae, 0x65, 0x8d, 0xde, 0x87, 0x02, 0x81, 0x80, 0x20, 0x24, 0x0f, 0xd2,  \
-    0xaf, 0xc2, 0x28, 0x3b, 0x97, 0x20, 0xb2, 0x92, 0x49, 0xeb, 0x09, 0x68,  \
-    0x40, 0xb2, 0xbe, 0xd1, 0xc3, 0x83, 0x94, 0x34, 0x38, 0xd6, 0xc9, 0xec,  \
-    0x34, 0x09, 0xf9, 0x41, 0x6d, 0x5c, 0x42, 0x94, 0xf7, 0x04, 0xfc, 0x32,  \
-    0x39, 0x69, 0xbc, 0x1c, 0xfb, 0x3e, 0x61, 0x98, 0xc0, 0x80, 0xd8, 0x36,  \
-    0x47, 0xc3, 0x6d, 0xc2, 0x2e, 0xe7, 0x81, 0x2a, 0x17, 0x34, 0x64, 0x30,  \
-    0x4e, 0x96, 0xbb, 0x26, 0x16, 0xb9, 0x41, 0x36, 0xfe, 0x8a, 0xd6, 0x53,  \
-    0x7c, 0xaa, 0xec, 0x39, 0x42, 0x50, 0xef, 0xe3, 0xb3, 0x01, 0x28, 0x32,  \
-    0xca, 0x6d, 0xf5, 0x9a, 0x1e, 0x9f, 0x37, 0xbe, 0xfe, 0x38, 0x20, 0x22,  \
-    0x91, 0x8c, 0xcd, 0x95, 0x02, 0xf2, 0x4d, 0x6f, 0x1a, 0xb4, 0x43, 0xf0,  \
-    0x19, 0xdf, 0x65, 0xc0, 0x92, 0xe7, 0x9d, 0x2f, 0x09, 0xe7, 0xec, 0x69,  \
-    0xa8, 0xc2, 0x8f, 0x0d                                                   \
-}
-/* END FILE */
-
-/*
- * Test server Certificates
- *
- * Test server certificates are defined for each choice
- * of the following parameters:
- * - PEM or DER encoding
- * - SHA-1 or SHA-256 hash
- * - RSA or EC key
- *
- * Things to add:
- * - multiple EC curve types
- */
-
-/* This is taken from tests/data_files/server5.crt. */
-/* BEGIN FILE string macro TEST_SRV_CRT_EC_PEM tests/data_files/server5.crt */
-#define TEST_SRV_CRT_EC_PEM                                                \
-    "-----BEGIN CERTIFICATE-----\r\n"                                      \
-    "MIICHzCCAaWgAwIBAgIBCTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" \
-    "A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" \
-    "MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \
-    "A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG\r\n" \
-    "CCqGSM49AwEHA0IABDfMVtl2CR5acj7HWS3/IG7ufPkGkXTQrRS192giWWKSTuUA\r\n" \
-    "2CMR/+ov0jRdXRa9iojCa3cNVc2KKg76Aci07f+jgZ0wgZowCQYDVR0TBAIwADAd\r\n" \
-    "BgNVHQ4EFgQUUGGlj9QH2deCAQzlZX+MY0anE74wbgYDVR0jBGcwZYAUnW0gJEkB\r\n" \
-    "PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xh\r\n" \
-    "clNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG\r\n" \
-    "CCqGSM49BAMCA2gAMGUCMQCaLFzXptui5WQN8LlO3ddh1hMxx6tzgLvT03MTVK2S\r\n" \
-    "C12r0Lz3ri/moSEpNZWqPjkCMCE2f53GXcYLqyfyJR078c/xNSUU5+Xxl7VZ414V\r\n" \
-    "fGa5kHvHARBPc8YAIVIqDvHH1Q==\r\n"                                     \
-    "-----END CERTIFICATE-----\r\n"
-/* END FILE */
-
-/* This is generated from tests/data_files/server5.crt.der using `xxd -i`. */
-/* BEGIN FILE binary macro TEST_SRV_CRT_EC_DER tests/data_files/server5.crt.der */
-#define TEST_SRV_CRT_EC_DER {                                                \
-    0x30, 0x82, 0x02, 0x1f, 0x30, 0x82, 0x01, 0xa5, 0xa0, 0x03, 0x02, 0x01,  \
-    0x02, 0x02, 0x01, 0x09, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,  \
-    0x3d, 0x04, 0x03, 0x02, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,  \
-    0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06,  \
-    0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53,  \
-    0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,  \
-    0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65,  \
-    0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d,  \
-    0x31, 0x33, 0x30, 0x39, 0x32, 0x34, 0x31, 0x35, 0x35, 0x32, 0x30, 0x34,  \
-    0x5a, 0x17, 0x0d, 0x32, 0x33, 0x30, 0x39, 0x32, 0x32, 0x31, 0x35, 0x35,  \
-    0x32, 0x30, 0x34, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,  \
-    0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06,  \
-    0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53,  \
-    0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,  \
-    0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x59,  \
-    0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,  \
-    0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00,  \
-    0x04, 0x37, 0xcc, 0x56, 0xd9, 0x76, 0x09, 0x1e, 0x5a, 0x72, 0x3e, 0xc7,  \
-    0x59, 0x2d, 0xff, 0x20, 0x6e, 0xee, 0x7c, 0xf9, 0x06, 0x91, 0x74, 0xd0,  \
-    0xad, 0x14, 0xb5, 0xf7, 0x68, 0x22, 0x59, 0x62, 0x92, 0x4e, 0xe5, 0x00,  \
-    0xd8, 0x23, 0x11, 0xff, 0xea, 0x2f, 0xd2, 0x34, 0x5d, 0x5d, 0x16, 0xbd,  \
-    0x8a, 0x88, 0xc2, 0x6b, 0x77, 0x0d, 0x55, 0xcd, 0x8a, 0x2a, 0x0e, 0xfa,  \
-    0x01, 0xc8, 0xb4, 0xed, 0xff, 0xa3, 0x81, 0x9d, 0x30, 0x81, 0x9a, 0x30,  \
-    0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d,  \
-    0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x50, 0x61, 0xa5,  \
-    0x8f, 0xd4, 0x07, 0xd9, 0xd7, 0x82, 0x01, 0x0c, 0xe5, 0x65, 0x7f, 0x8c,  \
-    0x63, 0x46, 0xa7, 0x13, 0xbe, 0x30, 0x6e, 0x06, 0x03, 0x55, 0x1d, 0x23,  \
-    0x04, 0x67, 0x30, 0x65, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, 0x01,  \
-    0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, 0xfb,  \
-    0x36, 0x7c, 0xa1, 0x42, 0xa4, 0x40, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09,  \
-    0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30,  \
-    0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61,  \
-    0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04,  \
-    0x03, 0x13, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20,  \
-    0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x82, 0x09,  \
-    0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8, 0x30, 0x0a, 0x06,  \
-    0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x68, 0x00,  \
-    0x30, 0x65, 0x02, 0x31, 0x00, 0x9a, 0x2c, 0x5c, 0xd7, 0xa6, 0xdb, 0xa2,  \
-    0xe5, 0x64, 0x0d, 0xf0, 0xb9, 0x4e, 0xdd, 0xd7, 0x61, 0xd6, 0x13, 0x31,  \
-    0xc7, 0xab, 0x73, 0x80, 0xbb, 0xd3, 0xd3, 0x73, 0x13, 0x54, 0xad, 0x92,  \
-    0x0b, 0x5d, 0xab, 0xd0, 0xbc, 0xf7, 0xae, 0x2f, 0xe6, 0xa1, 0x21, 0x29,  \
-    0x35, 0x95, 0xaa, 0x3e, 0x39, 0x02, 0x30, 0x21, 0x36, 0x7f, 0x9d, 0xc6,  \
-    0x5d, 0xc6, 0x0b, 0xab, 0x27, 0xf2, 0x25, 0x1d, 0x3b, 0xf1, 0xcf, 0xf1,  \
-    0x35, 0x25, 0x14, 0xe7, 0xe5, 0xf1, 0x97, 0xb5, 0x59, 0xe3, 0x5e, 0x15,  \
-    0x7c, 0x66, 0xb9, 0x90, 0x7b, 0xc7, 0x01, 0x10, 0x4f, 0x73, 0xc6, 0x00,  \
-    0x21, 0x52, 0x2a, 0x0e, 0xf1, 0xc7, 0xd5                                 \
-}
-/* END FILE */
-
-/* This is taken from tests/data_files/server5.key. */
-/* BEGIN FILE string macro TEST_SRV_KEY_EC_PEM tests/data_files/server5.key */
-#define TEST_SRV_KEY_EC_PEM                                                \
-    "-----BEGIN EC PRIVATE KEY-----\r\n"                                   \
-    "MHcCAQEEIPEqEyB2AnCoPL/9U/YDHvdqXYbIogTywwyp6/UfDw6noAoGCCqGSM49\r\n" \
-    "AwEHoUQDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/\r\n" \
-    "6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/w==\r\n"                             \
-    "-----END EC PRIVATE KEY-----\r\n"
-/* END FILE */
-
-/* This is generated from tests/data_files/server5.key.der using `xxd -i`. */
-/* BEGIN FILE binary macro TEST_SRV_KEY_EC_DER tests/data_files/server5.key.der */
-#define TEST_SRV_KEY_EC_DER {                                                \
-    0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf1, 0x2a, 0x13, 0x20, 0x76,  \
-    0x02, 0x70, 0xa8, 0x3c, 0xbf, 0xfd, 0x53, 0xf6, 0x03, 0x1e, 0xf7, 0x6a,  \
-    0x5d, 0x86, 0xc8, 0xa2, 0x04, 0xf2, 0xc3, 0x0c, 0xa9, 0xeb, 0xf5, 0x1f,  \
-    0x0f, 0x0e, 0xa7, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,  \
-    0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x37, 0xcc, 0x56,  \
-    0xd9, 0x76, 0x09, 0x1e, 0x5a, 0x72, 0x3e, 0xc7, 0x59, 0x2d, 0xff, 0x20,  \
-    0x6e, 0xee, 0x7c, 0xf9, 0x06, 0x91, 0x74, 0xd0, 0xad, 0x14, 0xb5, 0xf7,  \
-    0x68, 0x22, 0x59, 0x62, 0x92, 0x4e, 0xe5, 0x00, 0xd8, 0x23, 0x11, 0xff,  \
-    0xea, 0x2f, 0xd2, 0x34, 0x5d, 0x5d, 0x16, 0xbd, 0x8a, 0x88, 0xc2, 0x6b,  \
-    0x77, 0x0d, 0x55, 0xcd, 0x8a, 0x2a, 0x0e, 0xfa, 0x01, 0xc8, 0xb4, 0xed,  \
-    0xff                                                                     \
-}
-/* END FILE */
-
-/* This is taken from tests/data_files/server2-sha256.crt. */
-/* BEGIN FILE string macro TEST_SRV_CRT_RSA_SHA256_PEM tests/data_files/server2-sha256.crt */
-#define TEST_SRV_CRT_RSA_SHA256_PEM                                        \
-    "-----BEGIN CERTIFICATE-----\r\n"                                      \
-    "MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \
-    "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \
-    "MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \
-    "A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" \
-    "AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" \
-    "owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" \
-    "NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" \
-    "tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" \
-    "hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" \
-    "HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" \
-    "VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" \
-    "FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQELBQADggEBAC465FJh\r\n" \
-    "Pqel7zJngHIHJrqj/wVAxGAFOTF396XKATGAp+HRCqJ81Ry60CNK1jDzk8dv6M6U\r\n" \
-    "HoS7RIFiM/9rXQCbJfiPD5xMTejZp5n5UYHAmxsxDaazfA5FuBhkfokKK6jD4Eq9\r\n" \
-    "1C94xGKb6X4/VkaPF7cqoBBw/bHxawXc0UEPjqayiBpCYU/rJoVZgLqFVP7Px3sv\r\n" \
-    "a1nOrNx8rPPI1hJ+ZOg8maiPTxHZnBVLakSSLQy/sWeWyazO1RnrbxjrbgQtYKz0\r\n" \
-    "e3nwGpu1w13vfckFmUSBhHXH7AAS/HpKC4IH7G2GAk3+n8iSSN71sZzpxonQwVbo\r\n" \
-    "pMZqLmbBm/7WPLc=\r\n"                                                 \
-    "-----END CERTIFICATE-----\r\n"
-/* END FILE */
-
-/* This is taken from tests/data_files/server2-sha256.crt.der. */
-/* BEGIN FILE binary macro TEST_SRV_CRT_RSA_SHA256_DER tests/data_files/server2-sha256.crt.der */
-#define TEST_SRV_CRT_RSA_SHA256_DER {                                        \
-  0x30, 0x82, 0x03, 0x37, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01,    \
-  0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,    \
-  0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30,    \
-  0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11,    \
-  0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c,    \
-  0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55,    \
-  0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c,    \
-  0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d,    \
-  0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36,    \
-  0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34,    \
-  0x34, 0x30, 0x36, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,    \
-  0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06,    \
-  0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53,    \
-  0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,    \
-  0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82,    \
-  0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,    \
-  0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82,    \
-  0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc1, 0x4d, 0xa3, 0xdd, 0xe7,    \
-  0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, 0xb8, 0x99, 0xac, 0x0e, 0x78,    \
-  0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, 0x16, 0xd0, 0x5a, 0xe4, 0xcd,    \
-  0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, 0x96, 0xa7, 0x52, 0xb4, 0x90,    \
-  0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, 0xfc, 0xb6, 0x34, 0xac, 0x24,    \
-  0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, 0xb0, 0x28, 0x7d, 0xa1, 0xda,    \
-  0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, 0xfe, 0xc1, 0x04, 0x52, 0xb3,    \
-  0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, 0xd8, 0x90, 0xc1, 0x61, 0xb4,    \
-  0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, 0xab, 0x74, 0x5e, 0x07, 0x7d,    \
-  0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, 0xd9, 0x0d, 0x1c, 0x2d, 0x49,    \
-  0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, 0x0b, 0x8a, 0x4f, 0x69, 0x0c,    \
-  0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, 0x66, 0x7d, 0xae, 0x54, 0x2b,    \
-  0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, 0xc3, 0xcd, 0x40, 0x49, 0x08,    \
-  0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, 0x46, 0xbf, 0xd0, 0xb8, 0xaa,    \
-  0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, 0x1e, 0x44, 0x18, 0x0f, 0x0f,    \
-  0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, 0x18, 0xc6, 0x62, 0x2f, 0xc7,    \
-  0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, 0x27, 0x89, 0x29, 0x01, 0xc5,    \
-  0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, 0x4a, 0x0e, 0xef, 0xd6, 0xde,    \
-  0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, 0x7a, 0xc4, 0x02, 0x3c, 0x9a,    \
-  0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, 0xcb, 0x73, 0x4b, 0x52, 0x96,    \
-  0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, 0x39, 0x5a, 0xd3, 0x0f, 0xb0,    \
-  0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, 0x12, 0x01, 0x30, 0x97, 0x02,    \
-  0x03, 0x01, 0x00, 0x01, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03,    \
-  0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55,    \
-  0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa5, 0x05, 0xe8, 0x64, 0xb8, 0xdc,    \
-  0xdf, 0x60, 0x0f, 0x50, 0x12, 0x4d, 0x60, 0xa8, 0x64, 0xaf, 0x4d, 0x8b,    \
-  0x43, 0x93, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,    \
-  0x16, 0x80, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6,    \
-  0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30,    \
-  0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,    \
-  0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x2e, 0x3a, 0xe4, 0x52, 0x61,    \
-  0x3e, 0xa7, 0xa5, 0xef, 0x32, 0x67, 0x80, 0x72, 0x07, 0x26, 0xba, 0xa3,    \
-  0xff, 0x05, 0x40, 0xc4, 0x60, 0x05, 0x39, 0x31, 0x77, 0xf7, 0xa5, 0xca,    \
-  0x01, 0x31, 0x80, 0xa7, 0xe1, 0xd1, 0x0a, 0xa2, 0x7c, 0xd5, 0x1c, 0xba,    \
-  0xd0, 0x23, 0x4a, 0xd6, 0x30, 0xf3, 0x93, 0xc7, 0x6f, 0xe8, 0xce, 0x94,    \
-  0x1e, 0x84, 0xbb, 0x44, 0x81, 0x62, 0x33, 0xff, 0x6b, 0x5d, 0x00, 0x9b,    \
-  0x25, 0xf8, 0x8f, 0x0f, 0x9c, 0x4c, 0x4d, 0xe8, 0xd9, 0xa7, 0x99, 0xf9,    \
-  0x51, 0x81, 0xc0, 0x9b, 0x1b, 0x31, 0x0d, 0xa6, 0xb3, 0x7c, 0x0e, 0x45,    \
-  0xb8, 0x18, 0x64, 0x7e, 0x89, 0x0a, 0x2b, 0xa8, 0xc3, 0xe0, 0x4a, 0xbd,    \
-  0xd4, 0x2f, 0x78, 0xc4, 0x62, 0x9b, 0xe9, 0x7e, 0x3f, 0x56, 0x46, 0x8f,    \
-  0x17, 0xb7, 0x2a, 0xa0, 0x10, 0x70, 0xfd, 0xb1, 0xf1, 0x6b, 0x05, 0xdc,    \
-  0xd1, 0x41, 0x0f, 0x8e, 0xa6, 0xb2, 0x88, 0x1a, 0x42, 0x61, 0x4f, 0xeb,    \
-  0x26, 0x85, 0x59, 0x80, 0xba, 0x85, 0x54, 0xfe, 0xcf, 0xc7, 0x7b, 0x2f,    \
-  0x6b, 0x59, 0xce, 0xac, 0xdc, 0x7c, 0xac, 0xf3, 0xc8, 0xd6, 0x12, 0x7e,    \
-  0x64, 0xe8, 0x3c, 0x99, 0xa8, 0x8f, 0x4f, 0x11, 0xd9, 0x9c, 0x15, 0x4b,    \
-  0x6a, 0x44, 0x92, 0x2d, 0x0c, 0xbf, 0xb1, 0x67, 0x96, 0xc9, 0xac, 0xce,    \
-  0xd5, 0x19, 0xeb, 0x6f, 0x18, 0xeb, 0x6e, 0x04, 0x2d, 0x60, 0xac, 0xf4,    \
-  0x7b, 0x79, 0xf0, 0x1a, 0x9b, 0xb5, 0xc3, 0x5d, 0xef, 0x7d, 0xc9, 0x05,    \
-  0x99, 0x44, 0x81, 0x84, 0x75, 0xc7, 0xec, 0x00, 0x12, 0xfc, 0x7a, 0x4a,    \
-  0x0b, 0x82, 0x07, 0xec, 0x6d, 0x86, 0x02, 0x4d, 0xfe, 0x9f, 0xc8, 0x92,    \
-  0x48, 0xde, 0xf5, 0xb1, 0x9c, 0xe9, 0xc6, 0x89, 0xd0, 0xc1, 0x56, 0xe8,    \
-  0xa4, 0xc6, 0x6a, 0x2e, 0x66, 0xc1, 0x9b, 0xfe, 0xd6, 0x3c, 0xb7           \
-}
-/* END FILE */
-
-/* This is taken from tests/data_files/server2.crt. */
-/* BEGIN FILE string macro TEST_SRV_CRT_RSA_SHA1_PEM tests/data_files/server2.crt */
-#define TEST_SRV_CRT_RSA_SHA1_PEM                                       \
-"-----BEGIN CERTIFICATE-----\r\n"                                       \
-"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"  \
-"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"  \
-"MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n"  \
-"A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n"  \
-"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n"  \
-"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n"  \
-"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n"  \
-"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n"  \
-"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n"  \
-"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n"  \
-"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n"  \
-"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJklg3Q4\r\n"  \
-"cB7v7BzsxM/vLyKccO6op0/gZzM4ghuLq2Y32kl0sM6kSNUUmduuq3u/+GmUZN2A\r\n"  \
-"O/7c+Hw7hDFEIvZk98aBGjCLqn3DmgHIv8ToQ67nellQxx2Uj309PdgjNi/r9HOc\r\n"  \
-"KNAYPbBcg6MJGWWj2TI6vNaceios/DhOYx5V0j5nfqSJ/pnU0g9Ign2LAhgYpGJE\r\n"  \
-"iEM9wW7hEMkwmk0h/sqZsrJsGH5YsF/VThSq/JVO1e2mZH2vruyZKJVBq+8tDNYp\r\n"  \
-"HkK6tSyVYQhzIt3StMJWKMl/o5k2AYz6tSC164+1oG+ML3LWg8XrGKa91H4UOKap\r\n"  \
-"Awgk0+4m0T25cNs=\r\n"                                                  \
-"-----END CERTIFICATE-----\r\n"
-/* END FILE */
-
-/* This is taken from tests/data_files/server2.crt.der. */
-/* BEGIN FILE binary macro TEST_SRV_CRT_RSA_SHA1_DER tests/data_files/server2.crt.der */
-#define TEST_SRV_CRT_RSA_SHA1_DER {                                          \
-    0x30, 0x82, 0x03, 0x37, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01,  \
-    0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,  \
-    0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30,  \
-    0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11,  \
-    0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c,  \
-    0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55,  \
-    0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c,  \
-    0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d,  \
-    0x31, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36,  \
-    0x5a, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34,  \
-    0x34, 0x30, 0x36, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,  \
-    0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06,  \
-    0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53,  \
-    0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,  \
-    0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82,  \
-    0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,  \
-    0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82,  \
-    0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc1, 0x4d, 0xa3, 0xdd, 0xe7,  \
-    0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, 0xb8, 0x99, 0xac, 0x0e, 0x78,  \
-    0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, 0x16, 0xd0, 0x5a, 0xe4, 0xcd,  \
-    0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, 0x96, 0xa7, 0x52, 0xb4, 0x90,  \
-    0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, 0xfc, 0xb6, 0x34, 0xac, 0x24,  \
-    0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, 0xb0, 0x28, 0x7d, 0xa1, 0xda,  \
-    0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, 0xfe, 0xc1, 0x04, 0x52, 0xb3,  \
-    0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, 0xd8, 0x90, 0xc1, 0x61, 0xb4,  \
-    0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, 0xab, 0x74, 0x5e, 0x07, 0x7d,  \
-    0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, 0xd9, 0x0d, 0x1c, 0x2d, 0x49,  \
-    0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, 0x0b, 0x8a, 0x4f, 0x69, 0x0c,  \
-    0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, 0x66, 0x7d, 0xae, 0x54, 0x2b,  \
-    0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, 0xc3, 0xcd, 0x40, 0x49, 0x08,  \
-    0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, 0x46, 0xbf, 0xd0, 0xb8, 0xaa,  \
-    0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, 0x1e, 0x44, 0x18, 0x0f, 0x0f,  \
-    0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, 0x18, 0xc6, 0x62, 0x2f, 0xc7,  \
-    0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, 0x27, 0x89, 0x29, 0x01, 0xc5,  \
-    0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, 0x4a, 0x0e, 0xef, 0xd6, 0xde,  \
-    0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, 0x7a, 0xc4, 0x02, 0x3c, 0x9a,  \
-    0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, 0xcb, 0x73, 0x4b, 0x52, 0x96,  \
-    0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, 0x39, 0x5a, 0xd3, 0x0f, 0xb0,  \
-    0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, 0x12, 0x01, 0x30, 0x97, 0x02,  \
-    0x03, 0x01, 0x00, 0x01, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03,  \
-    0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55,  \
-    0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa5, 0x05, 0xe8, 0x64, 0xb8, 0xdc,  \
-    0xdf, 0x60, 0x0f, 0x50, 0x12, 0x4d, 0x60, 0xa8, 0x64, 0xaf, 0x4d, 0x8b,  \
-    0x43, 0x93, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,  \
-    0x16, 0x80, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6,  \
-    0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30,  \
-    0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,  \
-    0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x01, 0x73, 0x0b, 0x4a, 0xc5,  \
-    0xcb, 0xa0, 0xde, 0xf1, 0x63, 0x1c, 0x76, 0x04, 0x2b, 0x13, 0x0d, 0xc0,  \
-    0x84, 0x11, 0xc5, 0x8f, 0x3a, 0xa7, 0xc5, 0x9c, 0x35, 0x7a, 0x77, 0xb8,  \
-    0x20, 0x14, 0x82, 0xee, 0x54, 0xf0, 0xf2, 0xb0, 0x52, 0xcb, 0x78, 0xce,  \
-    0x59, 0x07, 0x4f, 0x51, 0x69, 0xfe, 0xd3, 0x2f, 0xe9, 0x09, 0xe7, 0x85,  \
-    0x92, 0xd8, 0xba, 0xb1, 0xeb, 0xc5, 0x76, 0x5d, 0x61, 0x2d, 0xe9, 0x86,  \
-    0xb5, 0xde, 0x2a, 0xf9, 0x3f, 0x53, 0x28, 0x42, 0x86, 0x83, 0x73, 0x43,  \
-    0xe0, 0x04, 0x5f, 0x07, 0x90, 0x14, 0x65, 0x9f, 0x6e, 0x10, 0x7a, 0xbc,  \
-    0x58, 0x19, 0x22, 0xc2, 0xeb, 0x39, 0x72, 0x51, 0x92, 0xd7, 0xb4, 0x1d,  \
-    0x75, 0x2f, 0xd3, 0x3a, 0x2b, 0x01, 0xe7, 0xdb, 0x50, 0xae, 0xe2, 0xf1,  \
-    0xd4, 0x4d, 0x5b, 0x3c, 0xbb, 0x41, 0x2b, 0x2a, 0xa4, 0xe2, 0x4a, 0x02,  \
-    0xe5, 0x60, 0x14, 0x2c, 0x9c, 0x1f, 0xa6, 0xcc, 0x06, 0x4b, 0x25, 0x89,  \
-    0x4e, 0x96, 0x30, 0x22, 0x9c, 0x5c, 0x58, 0x4d, 0xc3, 0xda, 0xd0, 0x6e,  \
-    0x50, 0x1e, 0x8c, 0x65, 0xf5, 0xd9, 0x17, 0x35, 0xa6, 0x58, 0x43, 0xb2,  \
-    0x29, 0xb7, 0xa8, 0x5e, 0x35, 0xde, 0xf0, 0x60, 0x42, 0x1a, 0x01, 0xcb,  \
-    0xcb, 0x0b, 0xd8, 0x0e, 0xc1, 0x90, 0xdf, 0xa1, 0xd2, 0x1a, 0xd1, 0x2c,  \
-    0x02, 0xf4, 0x76, 0x41, 0xa4, 0xcb, 0x4b, 0x15, 0x98, 0x71, 0xf9, 0x35,  \
-    0x7d, 0xb0, 0xe7, 0xe2, 0x34, 0x96, 0x91, 0xbe, 0x32, 0x67, 0x2d, 0x6b,  \
-    0xd3, 0x55, 0x04, 0x8a, 0x01, 0x50, 0xb4, 0xe3, 0x62, 0x78, 0x6c, 0x11,  \
-    0x15, 0xa5, 0x2a, 0x11, 0xc1, 0x49, 0x1c, 0x9b, 0xc4, 0x10, 0x65, 0x60,  \
-    0x87, 0xd9, 0x1e, 0x69, 0x59, 0x4e, 0x8f, 0x6b, 0xeb, 0xc1, 0xfe, 0x6b,  \
-    0xe2, 0x63, 0x78, 0x95, 0x6e, 0xe0, 0x2d, 0xd7, 0xa7, 0x37, 0xa8         \
-}
-/* END FILE */
-
-/* This is taken from tests/data_files/server2.key. */
-/* BEGIN FILE string macro TEST_SRV_KEY_RSA_PEM tests/data_files/server2.key */
-#define TEST_SRV_KEY_RSA_PEM                                               \
-    "-----BEGIN RSA PRIVATE KEY-----\r\n"                                  \
-    "MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n" \
-    "lqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\r\n" \
-    "2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\r\n" \
-    "Zn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\r\n" \
-    "GMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\r\n" \
-    "y3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\r\n" \
-    "++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\r\n" \
-    "Z0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\r\n" \
-    "/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\r\n" \
-    "WYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\r\n" \
-    "GTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\r\n" \
-    "TWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\r\n" \
-    "CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n" \
-    "nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n" \
-    "AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n" \
-    "sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n" \
-    "mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n" \
-    "BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n" \
-    "whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n" \
-    "vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n" \
-    "3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n" \
-    "3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n" \
-    "ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n" \
-    "4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n" \
-    "TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n"         \
-    "-----END RSA PRIVATE KEY-----\r\n"
-/* END FILE */
-
-/* This was generated from tests/data_files/server2.key.der using `xxd -i`. */
-/* BEGIN FILE binary macro TEST_SRV_KEY_RSA_DER tests/data_files/server2.key.der */
-#define TEST_SRV_KEY_RSA_DER {                                               \
-    0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,  \
-    0xc1, 0x4d, 0xa3, 0xdd, 0xe7, 0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72,  \
-    0xb8, 0x99, 0xac, 0x0e, 0x78, 0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13,  \
-    0x16, 0xd0, 0x5a, 0xe4, 0xcd, 0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b,  \
-    0x96, 0xa7, 0x52, 0xb4, 0x90, 0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a,  \
-    0xfc, 0xb6, 0x34, 0xac, 0x24, 0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c,  \
-    0xb0, 0x28, 0x7d, 0xa1, 0xda, 0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc,  \
-    0xfe, 0xc1, 0x04, 0x52, 0xb3, 0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76,  \
-    0xd8, 0x90, 0xc1, 0x61, 0xb4, 0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa,  \
-    0xab, 0x74, 0x5e, 0x07, 0x7d, 0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0,  \
-    0xd9, 0x0d, 0x1c, 0x2d, 0x49, 0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8,  \
-    0x0b, 0x8a, 0x4f, 0x69, 0x0c, 0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10,  \
-    0x66, 0x7d, 0xae, 0x54, 0x2b, 0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61,  \
-    0xc3, 0xcd, 0x40, 0x49, 0x08, 0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2,  \
-    0x46, 0xbf, 0xd0, 0xb8, 0xaa, 0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a,  \
-    0x1e, 0x44, 0x18, 0x0f, 0x0f, 0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2,  \
-    0x18, 0xc6, 0x62, 0x2f, 0xc7, 0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3,  \
-    0x27, 0x89, 0x29, 0x01, 0xc5, 0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8,  \
-    0x4a, 0x0e, 0xef, 0xd6, 0xde, 0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d,  \
-    0x7a, 0xc4, 0x02, 0x3c, 0x9a, 0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b,  \
-    0xcb, 0x73, 0x4b, 0x52, 0x96, 0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69,  \
-    0x39, 0x5a, 0xd3, 0x0f, 0xb0, 0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea,  \
-    0x12, 0x01, 0x30, 0x97, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01,  \
-    0x01, 0x00, 0x97, 0x47, 0x44, 0xbc, 0x10, 0x81, 0xc5, 0x18, 0xe4, 0x59,  \
-    0xfb, 0xe0, 0x2d, 0x3a, 0x0e, 0x9e, 0x10, 0xdc, 0x43, 0xfb, 0x15, 0x6c,  \
-    0xd1, 0xfd, 0x48, 0x78, 0x6c, 0xf9, 0xed, 0x38, 0xe8, 0xdd, 0x09, 0xd7,  \
-    0x5f, 0xb5, 0x41, 0x64, 0xd7, 0x63, 0xfa, 0x9d, 0x44, 0x0a, 0xf8, 0x42,  \
-    0x13, 0xf1, 0xbb, 0x5e, 0x79, 0x20, 0x53, 0x98, 0x4b, 0x65, 0x7f, 0x86,  \
-    0x67, 0x48, 0xe4, 0xcf, 0xfb, 0x6a, 0x24, 0xe2, 0x34, 0xbd, 0x14, 0x9d,  \
-    0x2c, 0x16, 0xe2, 0xa4, 0x79, 0xd6, 0xa2, 0xec, 0x81, 0x43, 0x87, 0xbf,  \
-    0x03, 0x5c, 0x88, 0x25, 0xd9, 0x41, 0xb6, 0xa5, 0xf1, 0x27, 0x52, 0x84,  \
-    0xfe, 0x2b, 0x6e, 0x1d, 0x16, 0xcd, 0x73, 0x88, 0xf8, 0x90, 0xbf, 0x19,  \
-    0xfe, 0xbe, 0xa9, 0xbf, 0x09, 0xd3, 0x23, 0x43, 0xd2, 0xc7, 0x61, 0x2a,  \
-    0xb3, 0x4e, 0x3c, 0x61, 0xd4, 0xbd, 0xd8, 0xb4, 0xfa, 0xa8, 0x0b, 0xf8,  \
-    0x7e, 0x56, 0xcd, 0x0f, 0x13, 0x27, 0xda, 0xe6, 0x3b, 0xb3, 0x8c, 0x9c,  \
-    0x4b, 0x84, 0x3c, 0xc3, 0x52, 0x57, 0x9c, 0x27, 0x9a, 0x02, 0x76, 0x26,  \
-    0x59, 0x82, 0x39, 0xc3, 0x13, 0xbe, 0x6e, 0xf4, 0x44, 0x2d, 0x1d, 0x8c,  \
-    0x73, 0x3e, 0x43, 0x99, 0x59, 0xcb, 0xf2, 0x34, 0x72, 0x9a, 0x5e, 0xa5,  \
-    0xeb, 0x9f, 0x36, 0x6d, 0x2b, 0xf9, 0xa2, 0xe7, 0xd1, 0x78, 0x52, 0x1b,  \
-    0xc8, 0xf6, 0x5b, 0x41, 0x69, 0x57, 0x81, 0x89, 0xe9, 0xbb, 0xa1, 0xde,  \
-    0x19, 0x37, 0x3b, 0x13, 0x5c, 0xca, 0x61, 0x01, 0x86, 0xff, 0xdf, 0x83,  \
-    0x41, 0x49, 0x7f, 0xd6, 0xf4, 0x2e, 0x08, 0xfa, 0x90, 0xc2, 0x7c, 0xb4,  \
-    0xb5, 0x0a, 0x17, 0xdb, 0x0e, 0x6d, 0x75, 0x8a, 0x5d, 0x31, 0xd5, 0x66,  \
-    0xfb, 0x39, 0x0b, 0xb5, 0xb6, 0xa3, 0xcd, 0xd4, 0xef, 0x88, 0x92, 0x5a,  \
-    0x4d, 0x6c, 0xcb, 0xea, 0x5b, 0x79, 0x02, 0x81, 0x81, 0x00, 0xdf, 0x3a,  \
-    0xf9, 0x25, 0x5e, 0x24, 0x37, 0x26, 0x40, 0x97, 0x2f, 0xe0, 0x4a, 0xba,  \
-    0x52, 0x1b, 0x51, 0xaf, 0x84, 0x06, 0x32, 0x24, 0x0c, 0xcf, 0x44, 0xa8,  \
-    0x77, 0xa7, 0xad, 0xb5, 0x8c, 0x58, 0xcc, 0xc8, 0x31, 0xb7, 0x0d, 0xbc,  \
-    0x08, 0x8a, 0xe0, 0xa6, 0x8c, 0xc2, 0x73, 0xe5, 0x1a, 0x64, 0x92, 0xe8,  \
-    0xed, 0x4c, 0x6f, 0x0b, 0xa6, 0xa7, 0xf3, 0x9a, 0xf5, 0x6f, 0x69, 0xca,  \
-    0x3c, 0x22, 0xd0, 0x15, 0xa8, 0x20, 0x27, 0x41, 0xf8, 0x43, 0x42, 0x7f,  \
-    0xb1, 0x93, 0xa1, 0x04, 0x85, 0xda, 0xa0, 0x1c, 0xd6, 0xc6, 0xf7, 0x8a,  \
-    0x9e, 0xea, 0x5c, 0x78, 0xa7, 0x55, 0xc4, 0x6b, 0x05, 0x8b, 0xc0, 0x83,  \
-    0xcb, 0xce, 0x83, 0x05, 0xf8, 0xb2, 0x16, 0x2b, 0xdf, 0x06, 0x3f, 0xb8,  \
-    0xec, 0x16, 0xda, 0x43, 0x33, 0xc1, 0x8f, 0xb0, 0xb8, 0xac, 0xae, 0xd4,  \
-    0x94, 0xb8, 0xda, 0x6f, 0x6a, 0xc3, 0x02, 0x81, 0x81, 0x00, 0xdd, 0xae,  \
-    0x00, 0xcd, 0xa0, 0x72, 0x1a, 0x05, 0x8a, 0xee, 0x2f, 0xd4, 0x71, 0x4b,  \
-    0xf0, 0x3e, 0xe5, 0xc1, 0xe1, 0x29, 0x8b, 0xa6, 0x67, 0x30, 0x98, 0xe7,  \
-    0x12, 0xef, 0xdd, 0x12, 0x01, 0x90, 0x24, 0x58, 0xf0, 0x76, 0x92, 0xe7,  \
-    0x3d, 0xbb, 0x23, 0xe1, 0xce, 0xf9, 0xa1, 0xd4, 0x38, 0x1b, 0x3f, 0x20,  \
-    0xb3, 0x0f, 0x65, 0x6a, 0x8f, 0x55, 0x57, 0x36, 0xee, 0xb2, 0x84, 0x44,  \
-    0xfc, 0x91, 0x88, 0xe1, 0xa4, 0xdd, 0x3b, 0x4a, 0x40, 0x4d, 0x7c, 0x86,  \
-    0xed, 0xe1, 0xb5, 0x42, 0xef, 0xb9, 0x61, 0xcd, 0x58, 0x19, 0x77, 0x02,  \
-    0xae, 0x58, 0x80, 0xdb, 0x13, 0x3d, 0xc7, 0x1f, 0x9d, 0xed, 0xff, 0xac,  \
-    0x98, 0xfc, 0xcd, 0xf9, 0x62, 0x04, 0x83, 0x91, 0x89, 0x0d, 0x86, 0x43,  \
-    0x8c, 0x0c, 0xc7, 0x1b, 0x90, 0x4d, 0xbe, 0x2f, 0xc5, 0x7c, 0xcd, 0x42,  \
-    0xf5, 0xd3, 0xad, 0x8e, 0xfd, 0x9d, 0x02, 0x81, 0x80, 0x17, 0x4b, 0x79,  \
-    0x2a, 0x6c, 0x1b, 0x8d, 0x61, 0xc1, 0x85, 0xc5, 0x6a, 0x3b, 0x82, 0x1c,  \
-    0x05, 0x5b, 0xcd, 0xdc, 0x12, 0x25, 0x73, 0x5b, 0x9e, 0xd9, 0x84, 0x57,  \
-    0x10, 0x39, 0x71, 0x63, 0x96, 0xf4, 0xaf, 0xc3, 0x78, 0x5d, 0xc7, 0x8c,  \
-    0x80, 0xa9, 0x96, 0xd7, 0xc3, 0x87, 0x02, 0x96, 0x71, 0x7e, 0x5f, 0x2e,  \
-    0x3c, 0x36, 0xae, 0x59, 0x92, 0xd7, 0x3a, 0x09, 0x78, 0xb9, 0xea, 0x6f,  \
-    0xc2, 0x16, 0x42, 0xdc, 0x4b, 0x96, 0xad, 0x2c, 0xb2, 0x20, 0x23, 0x61,  \
-    0x2d, 0x8d, 0xb5, 0x02, 0x1e, 0xe1, 0x6c, 0x81, 0x01, 0x3c, 0x5d, 0xcb,  \
-    0xdd, 0x9b, 0x0e, 0xc0, 0x2f, 0x94, 0x12, 0xb2, 0xfe, 0x75, 0x75, 0x8b,  \
-    0x74, 0x1e, 0x7a, 0x26, 0x0c, 0xb7, 0x81, 0x96, 0x81, 0x79, 0x6e, 0xdb,  \
-    0xbc, 0x3a, 0xc4, 0x9e, 0x87, 0x09, 0x6e, 0xa0, 0xa6, 0xec, 0x8b, 0xa4,  \
-    0x85, 0x71, 0xce, 0x04, 0xaf, 0x02, 0x81, 0x81, 0x00, 0xc2, 0xa7, 0x47,  \
-    0x07, 0x48, 0x6a, 0xc8, 0xd4, 0xb3, 0x20, 0xe1, 0x98, 0xee, 0xff, 0x5a,  \
-    0x6f, 0x30, 0x7a, 0xa5, 0x47, 0x40, 0xdc, 0x16, 0x62, 0x42, 0xf1, 0x2c,  \
-    0xdc, 0xb8, 0xc7, 0x55, 0xde, 0x07, 0x3c, 0x9d, 0xb1, 0xd0, 0xdf, 0x02,  \
-    0x82, 0xb0, 0x48, 0x58, 0xe1, 0x34, 0xab, 0xcf, 0xb4, 0x85, 0x23, 0x26,  \
-    0x78, 0x4f, 0x7a, 0x59, 0x6f, 0xfb, 0x8c, 0x3d, 0xdf, 0x3d, 0x6c, 0x02,  \
-    0x47, 0x9c, 0xe5, 0x5e, 0x49, 0xf1, 0x05, 0x0b, 0x1f, 0xbf, 0x48, 0x0f,  \
-    0xdc, 0x10, 0xb9, 0x3d, 0x1d, 0x10, 0x77, 0x2a, 0x73, 0xf9, 0xdf, 0xbd,  \
-    0xcd, 0xf3, 0x1f, 0xeb, 0x6e, 0x64, 0xca, 0x2b, 0x78, 0x4f, 0xf8, 0x73,  \
-    0xc2, 0x10, 0xef, 0x79, 0x95, 0x33, 0x1e, 0x79, 0x35, 0x09, 0xff, 0x88,  \
-    0x1b, 0xb4, 0x3e, 0x4c, 0xe1, 0x27, 0x2e, 0x75, 0x80, 0x58, 0x11, 0x03,  \
-    0x21, 0x23, 0x96, 0x9a, 0xb5, 0x02, 0x81, 0x80, 0x05, 0x12, 0x64, 0x71,  \
-    0x83, 0x00, 0x1c, 0xfe, 0xef, 0x83, 0xea, 0xdd, 0x2c, 0xc8, 0x2c, 0x00,  \
-    0x62, 0x1e, 0x8f, 0x3a, 0xdb, 0x1c, 0xab, 0xd6, 0x34, 0x8b, 0xd1, 0xb2,  \
-    0x5a, 0x4f, 0x3d, 0x37, 0x38, 0x02, 0xe0, 0xd7, 0x70, 0xc1, 0xb0, 0x47,  \
-    0xe0, 0x08, 0x1a, 0x84, 0xec, 0x48, 0xc5, 0x7c, 0x76, 0x83, 0x12, 0x67,  \
-    0xab, 0x7c, 0x9f, 0x90, 0x97, 0xc8, 0x8f, 0x07, 0xf4, 0xb3, 0x60, 0xf2,  \
-    0x3f, 0x49, 0x18, 0xdb, 0x2e, 0x94, 0x6b, 0x53, 0x9e, 0xa2, 0x63, 0xde,  \
-    0x63, 0xd9, 0xab, 0x21, 0x2e, 0x2d, 0x0a, 0xe0, 0xd0, 0xe8, 0xba, 0xc4,  \
-    0x4c, 0x1e, 0xa5, 0xf5, 0x51, 0xa8, 0xc4, 0x92, 0xf8, 0x7f, 0x21, 0xe7,  \
-    0x65, 0xbf, 0x0b, 0xe6, 0x01, 0xaf, 0x9c, 0x1d, 0x5b, 0x6c, 0x3f, 0x1c,  \
-    0x2f, 0xa6, 0x0f, 0x68, 0x38, 0x8e, 0x85, 0xc4, 0x6c, 0x78, 0x2f, 0x6f,  \
-    0x06, 0x21, 0x2e, 0x56                                                   \
-}
-/* END FILE */
-
-/*
- * Test client Certificates
- *
- * Test client certificates are defined for each choice
- * of the following parameters:
- * - PEM or DER encoding
- * - RSA or EC key
- *
- * Things to add:
- * - hash type
- * - multiple EC curve types
- */
-
-/* This is taken from tests/data_files/cli2.crt. */
-/* BEGIN FILE string macro TEST_CLI_CRT_EC_PEM tests/data_files/cli2.crt */
-#define TEST_CLI_CRT_EC_PEM                                                \
-    "-----BEGIN CERTIFICATE-----\r\n"                                      \
-    "MIIB3zCCAWOgAwIBAgIBDTAMBggqhkjOPQQDAgUAMD4xCzAJBgNVBAYTAk5MMREw\r\n" \
-    "DwYDVQQKDAhQb2xhclNTTDEcMBoGA1UEAwwTUG9sYXJTU0wgVGVzdCBFQyBDQTAe\r\n" \
-    "Fw0xOTAyMTAxNDQ0MDBaFw0yOTAyMTAxNDQ0MDBaMEExCzAJBgNVBAYTAk5MMREw\r\n" \
-    "DwYDVQQKDAhQb2xhclNTTDEfMB0GA1UEAwwWUG9sYXJTU0wgVGVzdCBDbGllbnQg\r\n" \
-    "MjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFflrrFz39Osu5O4gf8Sru7mU6zO\r\n" \
-    "VVP2NA7MLuNjJQvfmOLzXGA2lsDVGBRw5X+f1UtFGOWwbNVc+JaPh3Cj5MejTTBL\r\n" \
-    "MAkGA1UdEwQCMAAwHQYDVR0OBBYEFHoAX4Zk/OBd5REQO7LmO8QmP8/iMB8GA1Ud\r\n" \
-    "IwQYMBaAFJ1tICRJAT8ry3i1Gbx+JMnb+zZ8MAwGCCqGSM49BAMCBQADaAAwZQIx\r\n" \
-    "AMqme4DKMldUlplDET9Q6Eptre7uUWKhsLOF+zPkKDlfzpIkJYEFgcloDHGYw80u\r\n" \
-    "IgIwNftyPXsabTqMM7iEHgVpX/GRozKklY9yQI/5eoA6gGW7Y+imuGR/oao5ySOb\r\n" \
-    "a9Vk\r\n"       \
-    "-----END CERTIFICATE-----\r\n"
-/* END FILE */
-
-/* This is generated from tests/data_files/cli2.crt.der using `xxd -i`. */
-/* BEGIN FILE binary macro TEST_CLI_CRT_EC_DER tests/data_files/cli2.crt.der */
-#define TEST_CLI_CRT_EC_DER {                                                \
-    0x30, 0x82, 0x01, 0xdf, 0x30, 0x82, 0x01, 0x63, 0xa0, 0x03, 0x02, 0x01,  \
-    0x02, 0x02, 0x01, 0x0d, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,  \
-    0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09,  \
-    0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30,  \
-    0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61,  \
-    0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04,  \
-    0x03, 0x0c, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20,  \
-    0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e,  \
-    0x17, 0x0d, 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34,  \
-    0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31,  \
-    0x34, 0x34, 0x34, 0x30, 0x30, 0x5a, 0x30, 0x41, 0x31, 0x0b, 0x30, 0x09,  \
-    0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30,  \
-    0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61,  \
-    0x72, 0x53, 0x53, 0x4c, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04,  \
-    0x03, 0x0c, 0x16, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20,  \
-    0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20,  \
-    0x32, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,  \
-    0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,  \
-    0x03, 0x42, 0x00, 0x04, 0x57, 0xe5, 0xae, 0xb1, 0x73, 0xdf, 0xd3, 0xac,  \
-    0xbb, 0x93, 0xb8, 0x81, 0xff, 0x12, 0xae, 0xee, 0xe6, 0x53, 0xac, 0xce,  \
-    0x55, 0x53, 0xf6, 0x34, 0x0e, 0xcc, 0x2e, 0xe3, 0x63, 0x25, 0x0b, 0xdf,  \
-    0x98, 0xe2, 0xf3, 0x5c, 0x60, 0x36, 0x96, 0xc0, 0xd5, 0x18, 0x14, 0x70,  \
-    0xe5, 0x7f, 0x9f, 0xd5, 0x4b, 0x45, 0x18, 0xe5, 0xb0, 0x6c, 0xd5, 0x5c,  \
-    0xf8, 0x96, 0x8f, 0x87, 0x70, 0xa3, 0xe4, 0xc7, 0xa3, 0x4d, 0x30, 0x4b,  \
-    0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30,  \
-    0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x7a, 0x00,  \
-    0x5f, 0x86, 0x64, 0xfc, 0xe0, 0x5d, 0xe5, 0x11, 0x10, 0x3b, 0xb2, 0xe6,  \
-    0x3b, 0xc4, 0x26, 0x3f, 0xcf, 0xe2, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d,  \
-    0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49,  \
-    0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb,  \
-    0xfb, 0x36, 0x7c, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,  \
-    0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x31,  \
-    0x00, 0xca, 0xa6, 0x7b, 0x80, 0xca, 0x32, 0x57, 0x54, 0x96, 0x99, 0x43,  \
-    0x11, 0x3f, 0x50, 0xe8, 0x4a, 0x6d, 0xad, 0xee, 0xee, 0x51, 0x62, 0xa1,  \
-    0xb0, 0xb3, 0x85, 0xfb, 0x33, 0xe4, 0x28, 0x39, 0x5f, 0xce, 0x92, 0x24,  \
-    0x25, 0x81, 0x05, 0x81, 0xc9, 0x68, 0x0c, 0x71, 0x98, 0xc3, 0xcd, 0x2e,  \
-    0x22, 0x02, 0x30, 0x35, 0xfb, 0x72, 0x3d, 0x7b, 0x1a, 0x6d, 0x3a, 0x8c,  \
-    0x33, 0xb8, 0x84, 0x1e, 0x05, 0x69, 0x5f, 0xf1, 0x91, 0xa3, 0x32, 0xa4,  \
-    0x95, 0x8f, 0x72, 0x40, 0x8f, 0xf9, 0x7a, 0x80, 0x3a, 0x80, 0x65, 0xbb,  \
-    0x63, 0xe8, 0xa6, 0xb8, 0x64, 0x7f, 0xa1, 0xaa, 0x39, 0xc9, 0x23, 0x9b,  \
-    0x6b, 0xd5, 0x64                           \
-}
-/* END FILE */
-
-/* This is taken from tests/data_files/cli2.key. */
-/* BEGIN FILE string macro TEST_CLI_KEY_EC_PEM tests/data_files/cli2.key */
-#define TEST_CLI_KEY_EC_PEM                                                \
-    "-----BEGIN EC PRIVATE KEY-----\r\n"                                   \
-    "MHcCAQEEIPb3hmTxZ3/mZI3vyk7p3U3wBf+WIop6hDhkFzJhmLcqoAoGCCqGSM49\r\n" \
-    "AwEHoUQDQgAEV+WusXPf06y7k7iB/xKu7uZTrM5VU/Y0Dswu42MlC9+Y4vNcYDaW\r\n" \
-    "wNUYFHDlf5/VS0UY5bBs1Vz4lo+HcKPkxw==\r\n"                             \
-    "-----END EC PRIVATE KEY-----\r\n"
-/* END FILE */
-
-/* This is generated from tests/data_files/cli2.key.der using `xxd -i`. */
-/* BEGIN FILE binary macro TEST_CLI_KEY_EC_DER tests/data_files/cli2.key.der */
-#define TEST_CLI_KEY_EC_DER {                                                \
-    0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf6, 0xf7, 0x86, 0x64, 0xf1,  \
-    0x67, 0x7f, 0xe6, 0x64, 0x8d, 0xef, 0xca, 0x4e, 0xe9, 0xdd, 0x4d, 0xf0,  \
-    0x05, 0xff, 0x96, 0x22, 0x8a, 0x7a, 0x84, 0x38, 0x64, 0x17, 0x32, 0x61,  \
-    0x98, 0xb7, 0x2a, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,  \
-    0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x57, 0xe5, 0xae,  \
-    0xb1, 0x73, 0xdf, 0xd3, 0xac, 0xbb, 0x93, 0xb8, 0x81, 0xff, 0x12, 0xae,  \
-    0xee, 0xe6, 0x53, 0xac, 0xce, 0x55, 0x53, 0xf6, 0x34, 0x0e, 0xcc, 0x2e,  \
-    0xe3, 0x63, 0x25, 0x0b, 0xdf, 0x98, 0xe2, 0xf3, 0x5c, 0x60, 0x36, 0x96,  \
-    0xc0, 0xd5, 0x18, 0x14, 0x70, 0xe5, 0x7f, 0x9f, 0xd5, 0x4b, 0x45, 0x18,  \
-    0xe5, 0xb0, 0x6c, 0xd5, 0x5c, 0xf8, 0x96, 0x8f, 0x87, 0x70, 0xa3, 0xe4,  \
-    0xc7                                                                     \
-}
-/* END FILE */
-
-/* This is taken from tests/data_files/cli-rsa-sha256.crt. */
-/* BEGIN FILE string macro TEST_CLI_CRT_RSA_PEM tests/data_files/cli-rsa-sha256.crt */
-#define TEST_CLI_CRT_RSA_PEM                                               \
-    "-----BEGIN CERTIFICATE-----\r\n"                                      \
-    "MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \
-    "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \
-    "MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" \
-    "A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" \
-    "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n" \
-    "M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n" \
-    "1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n" \
-    "MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n" \
-    "4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n" \
-    "/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n" \
-    "o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n" \
-    "BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQsFAAOC\r\n" \
-    "AQEAXidv1d4pLlBiKWED95rMycBdgDcgyNqJxakFkRfRyA2y1mlyTn7uBXRkNLY5\r\n" \
-    "ZFzK82GCjk2Q2OD4RZSCPAJJqLpHHU34t71ciffvy2KK81YvrxczRhMAE64i+qna\r\n" \
-    "yP3Td2XuWJR05PVPoSemsNELs9gWttdnYy3ce+EY2Y0n7Rsi7982EeLIAA7H6ca4\r\n" \
-    "2Es/NUH//JZJT32OP0doMxeDRA+vplkKqTLLWf7dX26LIriBkBaRCgR5Yv9LBPFc\r\n" \
-    "NOtpzu/LbrY7QFXKJMI+JXDudCsOn8KCmiA4d6Emisqfh3V3485l7HEQNcvLTxlD\r\n" \
-    "6zDQyi0/ykYUYZkwQTK1N2Nvlw==\r\n"                                     \
-    "-----END CERTIFICATE-----\r\n"
-/* END FILE */
-
-/* This was generated from tests/data_files/cli-rsa-sha256.crt.der
-   using `xxd -i.` */
-/* BEGIN FILE binary macro TEST_CLI_CRT_RSA_DER tests/data_files/cli-rsa-sha256.crt.der */
-#define TEST_CLI_CRT_RSA_DER {                                               \
-  0x30, 0x82, 0x03, 0x3f, 0x30, 0x82, 0x02, 0x27, 0xa0, 0x03, 0x02, 0x01,   \
-  0x02, 0x02, 0x01, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,   \
-  0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30,   \
-  0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11,   \
-  0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c,   \
-  0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55,   \
-  0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c,   \
-  0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d,   \
-  0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36,   \
-  0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34,   \
-  0x34, 0x30, 0x36, 0x5a, 0x30, 0x3c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,   \
-  0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06,   \
-  0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53,   \
-  0x53, 0x4c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,   \
-  0x11, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x6c,   \
-  0x69, 0x65, 0x6e, 0x74, 0x20, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,   \
-  0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,   \
-  0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82,   \
-  0x01, 0x01, 0x00, 0xc8, 0x74, 0xc4, 0xcc, 0xb9, 0xf9, 0xb5, 0x79, 0xe9,   \
-  0x45, 0xd9, 0x14, 0x60, 0xb0, 0x7d, 0xbb, 0x93, 0xf2, 0x6b, 0x1e, 0x9f,   \
-  0x33, 0xad, 0x0d, 0x8f, 0x8a, 0x3c, 0x56, 0x65, 0xe5, 0xdc, 0x44, 0xd9,   \
-  0xcc, 0x66, 0x85, 0x07, 0xd5, 0xf8, 0x27, 0xb0, 0x4a, 0x35, 0xd0, 0x63,   \
-  0x9e, 0x0a, 0x6e, 0x1b, 0xb7, 0xda, 0xf0, 0x7e, 0xab, 0xee, 0x0c, 0x10,   \
-  0x93, 0x86, 0x49, 0x18, 0x34, 0xf3, 0xa8, 0x2a, 0xd2, 0x57, 0xf5, 0x2e,   \
-  0xd4, 0x2f, 0x77, 0x29, 0x84, 0x61, 0x4d, 0x82, 0x50, 0x8f, 0xa7, 0x95,   \
-  0x48, 0x70, 0xf5, 0x6e, 0x4d, 0xb2, 0xd5, 0x13, 0xc3, 0xd2, 0x1a, 0xed,   \
-  0xe6, 0x43, 0xea, 0x42, 0x14, 0xeb, 0x74, 0xea, 0xc0, 0xed, 0x1f, 0xd4,   \
-  0x57, 0x4e, 0xa9, 0xf3, 0xa8, 0xed, 0xd2, 0xe0, 0xc1, 0x30, 0x71, 0x30,   \
-  0x32, 0x30, 0xd5, 0xd3, 0xf6, 0x08, 0xd0, 0x56, 0x4f, 0x46, 0x8e, 0xf2,   \
-  0x5f, 0xf9, 0x3d, 0x67, 0x91, 0x88, 0x30, 0x2e, 0x42, 0xb2, 0xdf, 0x7d,   \
-  0xfb, 0xe5, 0x0c, 0x77, 0xff, 0xec, 0x31, 0xc0, 0x78, 0x8f, 0xbf, 0xc2,   \
-  0x7f, 0xca, 0xad, 0x6c, 0x21, 0xd6, 0x8d, 0xd9, 0x8b, 0x6a, 0x8e, 0x6f,   \
-  0xe0, 0x9b, 0xf8, 0x10, 0x56, 0xcc, 0xb3, 0x8e, 0x13, 0x15, 0xe6, 0x34,   \
-  0x04, 0x66, 0xc7, 0xee, 0xf9, 0x36, 0x0e, 0x6a, 0x95, 0xf6, 0x09, 0x9a,   \
-  0x06, 0x67, 0xf4, 0x65, 0x71, 0xf8, 0xca, 0xa4, 0xb1, 0x25, 0xe0, 0xfe,   \
-  0x3c, 0x8b, 0x35, 0x04, 0x67, 0xba, 0xe0, 0x4f, 0x76, 0x85, 0xfc, 0x7f,   \
-  0xfc, 0x36, 0x6b, 0xb5, 0xe9, 0xcd, 0x2d, 0x03, 0x62, 0x4e, 0xb3, 0x3d,   \
-  0x00, 0xcf, 0xaf, 0x76, 0xa0, 0x69, 0x56, 0x83, 0x6a, 0xd2, 0xa8, 0xd4,   \
-  0xe7, 0x50, 0x71, 0xe6, 0xb5, 0x36, 0x05, 0x77, 0x05, 0x6d, 0x7b, 0xc8,   \
-  0xe4, 0xc4, 0xfd, 0x4c, 0xd5, 0x21, 0x5f, 0x02, 0x03, 0x01, 0x00, 0x01,   \
-  0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,   \
-  0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,   \
-  0x04, 0x14, 0x71, 0xa1, 0x00, 0x73, 0x72, 0x40, 0x2f, 0x54, 0x76, 0x5e,   \
-  0x33, 0xfc, 0x52, 0x8f, 0xbc, 0xf1, 0xdd, 0x6b, 0x46, 0x21, 0x30, 0x1f,   \
-  0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xb4,   \
-  0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, 0xa6, 0x95,   \
-  0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a,   \
-  0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82,   \
-  0x01, 0x01, 0x00, 0x5e, 0x27, 0x6f, 0xd5, 0xde, 0x29, 0x2e, 0x50, 0x62,   \
-  0x29, 0x61, 0x03, 0xf7, 0x9a, 0xcc, 0xc9, 0xc0, 0x5d, 0x80, 0x37, 0x20,   \
-  0xc8, 0xda, 0x89, 0xc5, 0xa9, 0x05, 0x91, 0x17, 0xd1, 0xc8, 0x0d, 0xb2,   \
-  0xd6, 0x69, 0x72, 0x4e, 0x7e, 0xee, 0x05, 0x74, 0x64, 0x34, 0xb6, 0x39,   \
-  0x64, 0x5c, 0xca, 0xf3, 0x61, 0x82, 0x8e, 0x4d, 0x90, 0xd8, 0xe0, 0xf8,   \
-  0x45, 0x94, 0x82, 0x3c, 0x02, 0x49, 0xa8, 0xba, 0x47, 0x1d, 0x4d, 0xf8,   \
-  0xb7, 0xbd, 0x5c, 0x89, 0xf7, 0xef, 0xcb, 0x62, 0x8a, 0xf3, 0x56, 0x2f,   \
-  0xaf, 0x17, 0x33, 0x46, 0x13, 0x00, 0x13, 0xae, 0x22, 0xfa, 0xa9, 0xda,   \
-  0xc8, 0xfd, 0xd3, 0x77, 0x65, 0xee, 0x58, 0x94, 0x74, 0xe4, 0xf5, 0x4f,   \
-  0xa1, 0x27, 0xa6, 0xb0, 0xd1, 0x0b, 0xb3, 0xd8, 0x16, 0xb6, 0xd7, 0x67,   \
-  0x63, 0x2d, 0xdc, 0x7b, 0xe1, 0x18, 0xd9, 0x8d, 0x27, 0xed, 0x1b, 0x22,   \
-  0xef, 0xdf, 0x36, 0x11, 0xe2, 0xc8, 0x00, 0x0e, 0xc7, 0xe9, 0xc6, 0xb8,   \
-  0xd8, 0x4b, 0x3f, 0x35, 0x41, 0xff, 0xfc, 0x96, 0x49, 0x4f, 0x7d, 0x8e,   \
-  0x3f, 0x47, 0x68, 0x33, 0x17, 0x83, 0x44, 0x0f, 0xaf, 0xa6, 0x59, 0x0a,   \
-  0xa9, 0x32, 0xcb, 0x59, 0xfe, 0xdd, 0x5f, 0x6e, 0x8b, 0x22, 0xb8, 0x81,   \
-  0x90, 0x16, 0x91, 0x0a, 0x04, 0x79, 0x62, 0xff, 0x4b, 0x04, 0xf1, 0x5c,   \
-  0x34, 0xeb, 0x69, 0xce, 0xef, 0xcb, 0x6e, 0xb6, 0x3b, 0x40, 0x55, 0xca,   \
-  0x24, 0xc2, 0x3e, 0x25, 0x70, 0xee, 0x74, 0x2b, 0x0e, 0x9f, 0xc2, 0x82,   \
-  0x9a, 0x20, 0x38, 0x77, 0xa1, 0x26, 0x8a, 0xca, 0x9f, 0x87, 0x75, 0x77,   \
-  0xe3, 0xce, 0x65, 0xec, 0x71, 0x10, 0x35, 0xcb, 0xcb, 0x4f, 0x19, 0x43,   \
-  0xeb, 0x30, 0xd0, 0xca, 0x2d, 0x3f, 0xca, 0x46, 0x14, 0x61, 0x99, 0x30,   \
-  0x41, 0x32, 0xb5, 0x37, 0x63, 0x6f, 0x97                                  \
-}
-/* END FILE */
-
-/* This is taken from tests/data_files/cli-rsa.key. */
-/* BEGIN FILE string macro TEST_CLI_KEY_RSA_PEM tests/data_files/cli-rsa.key */
-#define TEST_CLI_KEY_RSA_PEM                                               \
-    "-----BEGIN RSA PRIVATE KEY-----\r\n"                                  \
-    "MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n" \
-    "B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n" \
-    "bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n" \
-    "Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n" \
-    "7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n" \
-    "dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n" \
-    "yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n" \
-    "4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n" \
-    "ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n" \
-    "zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n" \
-    "l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n" \
-    "DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n" \
-    "VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n" \
-    "Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n" \
-    "wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n" \
-    "c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n" \
-    "33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n" \
-    "ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n" \
-    "BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n" \
-    "KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n" \
-    "UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n" \
-    "7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n" \
-    "gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n" \
-    "bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n" \
-    "8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n"         \
-    "-----END RSA PRIVATE KEY-----\r\n"/* END FILE */
-
-/* This was generated from tests/data_files/cli-rsa.key.der using `xxd -i`. */
-/* BEGIN FILE binary macro TEST_CLI_KEY_RSA_DER tests/data_files/cli-rsa.key.der */
-#define TEST_CLI_KEY_RSA_DER {                                               \
-    0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,  \
-    0xc8, 0x74, 0xc4, 0xcc, 0xb9, 0xf9, 0xb5, 0x79, 0xe9, 0x45, 0xd9, 0x14,  \
-    0x60, 0xb0, 0x7d, 0xbb, 0x93, 0xf2, 0x6b, 0x1e, 0x9f, 0x33, 0xad, 0x0d,  \
-    0x8f, 0x8a, 0x3c, 0x56, 0x65, 0xe5, 0xdc, 0x44, 0xd9, 0xcc, 0x66, 0x85,  \
-    0x07, 0xd5, 0xf8, 0x27, 0xb0, 0x4a, 0x35, 0xd0, 0x63, 0x9e, 0x0a, 0x6e,  \
-    0x1b, 0xb7, 0xda, 0xf0, 0x7e, 0xab, 0xee, 0x0c, 0x10, 0x93, 0x86, 0x49,  \
-    0x18, 0x34, 0xf3, 0xa8, 0x2a, 0xd2, 0x57, 0xf5, 0x2e, 0xd4, 0x2f, 0x77,  \
-    0x29, 0x84, 0x61, 0x4d, 0x82, 0x50, 0x8f, 0xa7, 0x95, 0x48, 0x70, 0xf5,  \
-    0x6e, 0x4d, 0xb2, 0xd5, 0x13, 0xc3, 0xd2, 0x1a, 0xed, 0xe6, 0x43, 0xea,  \
-    0x42, 0x14, 0xeb, 0x74, 0xea, 0xc0, 0xed, 0x1f, 0xd4, 0x57, 0x4e, 0xa9,  \
-    0xf3, 0xa8, 0xed, 0xd2, 0xe0, 0xc1, 0x30, 0x71, 0x30, 0x32, 0x30, 0xd5,  \
-    0xd3, 0xf6, 0x08, 0xd0, 0x56, 0x4f, 0x46, 0x8e, 0xf2, 0x5f, 0xf9, 0x3d,  \
-    0x67, 0x91, 0x88, 0x30, 0x2e, 0x42, 0xb2, 0xdf, 0x7d, 0xfb, 0xe5, 0x0c,  \
-    0x77, 0xff, 0xec, 0x31, 0xc0, 0x78, 0x8f, 0xbf, 0xc2, 0x7f, 0xca, 0xad,  \
-    0x6c, 0x21, 0xd6, 0x8d, 0xd9, 0x8b, 0x6a, 0x8e, 0x6f, 0xe0, 0x9b, 0xf8,  \
-    0x10, 0x56, 0xcc, 0xb3, 0x8e, 0x13, 0x15, 0xe6, 0x34, 0x04, 0x66, 0xc7,  \
-    0xee, 0xf9, 0x36, 0x0e, 0x6a, 0x95, 0xf6, 0x09, 0x9a, 0x06, 0x67, 0xf4,  \
-    0x65, 0x71, 0xf8, 0xca, 0xa4, 0xb1, 0x25, 0xe0, 0xfe, 0x3c, 0x8b, 0x35,  \
-    0x04, 0x67, 0xba, 0xe0, 0x4f, 0x76, 0x85, 0xfc, 0x7f, 0xfc, 0x36, 0x6b,  \
-    0xb5, 0xe9, 0xcd, 0x2d, 0x03, 0x62, 0x4e, 0xb3, 0x3d, 0x00, 0xcf, 0xaf,  \
-    0x76, 0xa0, 0x69, 0x56, 0x83, 0x6a, 0xd2, 0xa8, 0xd4, 0xe7, 0x50, 0x71,  \
-    0xe6, 0xb5, 0x36, 0x05, 0x77, 0x05, 0x6d, 0x7b, 0xc8, 0xe4, 0xc4, 0xfd,  \
-    0x4c, 0xd5, 0x21, 0x5f, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01,  \
-    0x00, 0x67, 0x4d, 0xb5, 0xf6, 0x03, 0x89, 0xaa, 0x7a, 0x6f, 0x3b, 0x2d,  \
-    0xca, 0x10, 0xa2, 0x23, 0xc9, 0xbd, 0x4e, 0xda, 0xe1, 0x67, 0x0e, 0x0c,  \
-    0x8a, 0xc6, 0x84, 0x68, 0xdf, 0xe5, 0x97, 0x75, 0xd2, 0x8d, 0xa3, 0x86,  \
-    0xd9, 0xdb, 0xd5, 0xeb, 0x13, 0x19, 0x08, 0xc5, 0x7e, 0xe5, 0x37, 0x97,  \
-    0x0c, 0x73, 0x80, 0x66, 0x76, 0x35, 0xf1, 0x88, 0xb5, 0xf2, 0xfc, 0xf3,  \
-    0xe1, 0x4b, 0x76, 0x4e, 0x73, 0x45, 0xce, 0x2c, 0xc2, 0x10, 0x26, 0x0d,  \
-    0x68, 0x0d, 0x9f, 0x49, 0x3d, 0xd6, 0x80, 0x89, 0xe7, 0xc5, 0x49, 0x15,  \
-    0xdd, 0x85, 0xc0, 0xc8, 0xfe, 0x82, 0x37, 0x12, 0x5a, 0x0a, 0x6b, 0xf6,  \
-    0x68, 0x0d, 0x32, 0x16, 0xbd, 0xa4, 0x15, 0x54, 0x9e, 0x68, 0xa1, 0xad,  \
-    0xca, 0x6b, 0xe5, 0x8c, 0xda, 0x76, 0x35, 0x59, 0x2f, 0x9b, 0xb4, 0xe1,  \
-    0xf1, 0xf0, 0x50, 0x04, 0xee, 0xc8, 0xec, 0x05, 0xe1, 0xcf, 0x8d, 0xe4,  \
-    0xd2, 0x64, 0x7b, 0x5e, 0x63, 0xe0, 0x7b, 0x07, 0xbc, 0x02, 0x96, 0x4e,  \
-    0x1b, 0x78, 0x6c, 0xb6, 0x43, 0x9a, 0x32, 0xf6, 0xd6, 0x02, 0xf5, 0x80,  \
-    0xcc, 0x26, 0x6e, 0xa5, 0xd0, 0xe3, 0x65, 0x88, 0xce, 0x26, 0xa9, 0x40,  \
-    0xe1, 0xe1, 0x00, 0xe0, 0x7f, 0x3f, 0xc3, 0xb1, 0x7c, 0xde, 0xbe, 0x42,  \
-    0xba, 0x07, 0x81, 0x13, 0xc2, 0xe0, 0x11, 0x11, 0x23, 0x2c, 0xf8, 0xb2,  \
-    0x7a, 0x3a, 0xd4, 0xe4, 0x7d, 0x5f, 0xb9, 0xb1, 0x18, 0xfa, 0x1d, 0x1d,  \
-    0x97, 0x91, 0xd9, 0x04, 0x9e, 0xbc, 0xc9, 0xb4, 0xd7, 0x7d, 0x0e, 0x54,  \
-    0xf6, 0x8f, 0xd0, 0x28, 0x0d, 0xdd, 0x77, 0x4b, 0x68, 0x04, 0x48, 0x61,  \
-    0x75, 0x15, 0x03, 0x1b, 0x35, 0xad, 0x8e, 0xfc, 0x24, 0x11, 0x07, 0xea,  \
-    0x17, 0x5a, 0xde, 0x19, 0x68, 0xff, 0xb6, 0x87, 0x7f, 0x80, 0x2a, 0x5f,  \
-    0x0c, 0x58, 0xba, 0x5f, 0x41, 0x02, 0x81, 0x81, 0x00, 0xe3, 0x03, 0xaf,  \
-    0xfe, 0x98, 0xd2, 0x0b, 0x7b, 0x72, 0xe9, 0x3b, 0x8e, 0xbc, 0xa5, 0xf6,  \
-    0xac, 0xe5, 0x22, 0x06, 0xb2, 0xd7, 0x5e, 0xfd, 0x89, 0x4b, 0x16, 0x67,  \
-    0x32, 0x83, 0x22, 0x58, 0x8e, 0x62, 0xa4, 0xb4, 0x2d, 0xf9, 0x16, 0x13,  \
-    0x54, 0xf6, 0x9f, 0x2f, 0xf9, 0xbb, 0x0e, 0x7e, 0x8c, 0x6f, 0x08, 0xda,  \
-    0xc8, 0xe9, 0x1c, 0x66, 0x10, 0x70, 0x93, 0x90, 0x8d, 0xcf, 0x90, 0x3a,  \
-    0x43, 0x89, 0x49, 0xeb, 0x83, 0x2a, 0xfe, 0x5a, 0x87, 0xce, 0x74, 0x42,  \
-    0x41, 0x0d, 0x8c, 0x73, 0x51, 0xbc, 0x7b, 0x20, 0xc5, 0xfd, 0xf6, 0x0b,  \
-    0x65, 0xed, 0xa9, 0x2e, 0xfc, 0x0f, 0xf5, 0x50, 0xf9, 0x8d, 0x37, 0x36,  \
-    0x9a, 0x20, 0xdf, 0xc3, 0xe3, 0x27, 0xbc, 0x98, 0x72, 0xc1, 0x14, 0x4b,  \
-    0x71, 0xe9, 0x83, 0x14, 0xff, 0x24, 0xe2, 0x14, 0x15, 0xb6, 0x6f, 0x0f,  \
-    0x32, 0x9d, 0xd9, 0x98, 0xd1, 0x02, 0x81, 0x81, 0x00, 0xe2, 0x0c, 0xfb,  \
-    0xc3, 0x33, 0x9b, 0x47, 0x88, 0x27, 0xf2, 0x26, 0xde, 0xeb, 0x5e, 0xee,  \
-    0x40, 0xf6, 0x63, 0x5b, 0x35, 0x23, 0xf5, 0xd5, 0x07, 0x61, 0xdf, 0xa2,  \
-    0x9f, 0x58, 0x30, 0x04, 0x22, 0x2b, 0xb4, 0xd9, 0xda, 0x46, 0x7f, 0x48,  \
-    0xf5, 0x4f, 0xd0, 0xea, 0xd7, 0xa0, 0x45, 0x8a, 0x62, 0x8b, 0x8c, 0xac,  \
-    0x73, 0x5e, 0xfa, 0x36, 0x65, 0x3e, 0xba, 0x6c, 0xba, 0x5e, 0x6b, 0x92,  \
-    0x29, 0x5e, 0x6a, 0x0f, 0xd6, 0xd2, 0xa5, 0x95, 0x86, 0xda, 0x72, 0xc5,  \
-    0x9e, 0xc9, 0x6b, 0x37, 0x5e, 0x4b, 0x9b, 0x77, 0xe1, 0x67, 0x1a, 0x1e,  \
-    0x30, 0xd8, 0x41, 0x68, 0x40, 0xd3, 0x9c, 0xb4, 0xf6, 0xeb, 0x2a, 0x22,  \
-    0xdf, 0x78, 0x29, 0xd2, 0x64, 0x92, 0x5b, 0x2f, 0x78, 0x64, 0x4a, 0xa2,  \
-    0xa6, 0x6b, 0x3e, 0x50, 0xb1, 0x7a, 0xb1, 0x8d, 0x59, 0xb4, 0x55, 0xba,  \
-    0xb6, 0x91, 0x85, 0xa3, 0x2f, 0x02, 0x81, 0x80, 0x10, 0x1e, 0x19, 0xe7,  \
-    0xbc, 0x97, 0xe5, 0x22, 0xcd, 0xa4, 0xcb, 0x8a, 0xb5, 0xd0, 0x1e, 0xb4,  \
-    0x65, 0xcc, 0x45, 0xa7, 0x7a, 0xed, 0x0e, 0x99, 0x29, 0xd0, 0x9c, 0x61,  \
-    0x14, 0xb8, 0x62, 0x8b, 0x31, 0x6b, 0xba, 0x33, 0x2d, 0x65, 0x28, 0xd8,  \
-    0x36, 0x6e, 0x54, 0xec, 0xa9, 0x20, 0x3d, 0x51, 0xe1, 0x2c, 0x42, 0xc4,  \
-    0x52, 0xf0, 0xa6, 0x3a, 0x72, 0x93, 0xb7, 0x86, 0xa9, 0xfe, 0xf6, 0x74,  \
-    0x07, 0x12, 0x4d, 0x7b, 0x51, 0x99, 0x1f, 0x7a, 0x56, 0xe9, 0x20, 0x2f,  \
-    0x18, 0x34, 0x29, 0x97, 0xdb, 0x06, 0xee, 0xeb, 0xbf, 0xbd, 0x31, 0x4f,  \
-    0xfa, 0x50, 0xb1, 0xba, 0x49, 0xb3, 0xc4, 0x1d, 0x03, 0xae, 0xb0, 0xdc,  \
-    0xbe, 0x8a, 0xc4, 0x90, 0xa3, 0x28, 0x9b, 0xb6, 0x42, 0x09, 0x1b, 0xd6,  \
-    0x29, 0x9b, 0x19, 0xe9, 0x87, 0x87, 0xd9, 0x9f, 0x35, 0x05, 0xab, 0x91,  \
-    0x8f, 0x6d, 0x7c, 0x91, 0x02, 0x81, 0x81, 0x00, 0x94, 0x57, 0xf0, 0xe0,  \
-    0x28, 0xfd, 0xbd, 0xf3, 0x9c, 0x43, 0x4d, 0x3e, 0xfd, 0x37, 0x4f, 0x23,  \
-    0x52, 0x8d, 0xe1, 0x4c, 0xfe, 0x4c, 0x55, 0x80, 0x82, 0xba, 0x3f, 0xfe,  \
-    0x51, 0xe1, 0x30, 0xd5, 0x3b, 0xd9, 0x73, 0x1d, 0xcb, 0x25, 0xbc, 0xbb,  \
-    0x3f, 0xa5, 0xda, 0x77, 0xa6, 0xb5, 0xfc, 0x1a, 0xaf, 0x79, 0xa1, 0xb2,  \
-    0x14, 0xa2, 0x1f, 0x10, 0x52, 0x1a, 0x05, 0x40, 0x48, 0xb6, 0x4f, 0x34,  \
-    0xd6, 0xc0, 0xc3, 0xa4, 0x36, 0x98, 0x73, 0x88, 0x0b, 0xd3, 0x45, 0xdc,  \
-    0xee, 0x51, 0x6e, 0x04, 0x73, 0x99, 0x93, 0x12, 0x58, 0x96, 0xcb, 0x39,  \
-    0x42, 0xb1, 0xa9, 0xb8, 0xe1, 0x25, 0xf5, 0x9c, 0x14, 0xb7, 0x92, 0x2b,  \
-    0x14, 0xb0, 0x5d, 0x61, 0xa2, 0xaa, 0x34, 0x7c, 0xcd, 0x54, 0x2d, 0x69,  \
-    0x08, 0xf7, 0xdb, 0xfc, 0x9c, 0x87, 0xe8, 0x3a, 0xf6, 0x1d, 0x4c, 0x6a,  \
-    0x83, 0x15, 0x30, 0x01, 0x02, 0x81, 0x81, 0x00, 0x9c, 0x53, 0xa1, 0xb6,  \
-    0x2f, 0xc0, 0x06, 0xf5, 0xdf, 0x5c, 0xd1, 0x4a, 0x4e, 0xc8, 0xbd, 0x6d,  \
-    0x32, 0xf1, 0x5e, 0xe5, 0x3b, 0x70, 0xd0, 0xa8, 0xe5, 0x41, 0x57, 0x6c,  \
-    0x87, 0x53, 0x0f, 0xeb, 0x28, 0xa0, 0x62, 0x8f, 0x43, 0x62, 0xec, 0x2e,  \
-    0x6c, 0x71, 0x55, 0x5b, 0x6a, 0xf4, 0x74, 0x14, 0xea, 0x7a, 0x03, 0xf6,  \
-    0xfc, 0xa4, 0xce, 0xc4, 0xac, 0xda, 0x1d, 0xf0, 0xb5, 0xa9, 0xfd, 0x11,  \
-    0x18, 0x3b, 0x14, 0xa0, 0x90, 0x8d, 0x26, 0xb7, 0x75, 0x73, 0x0a, 0x02,  \
-    0x2c, 0x6f, 0x0f, 0xd8, 0x41, 0x78, 0xc3, 0x73, 0x81, 0xac, 0xaa, 0xaf,  \
-    0xf2, 0xee, 0x32, 0xb5, 0x8d, 0x05, 0xf9, 0x59, 0x5a, 0x9e, 0x3e, 0x65,  \
-    0x9b, 0x74, 0xda, 0xa0, 0x74, 0x95, 0x17, 0x5f, 0x8d, 0x58, 0xfc, 0x8e,  \
-    0x4e, 0x2c, 0x1e, 0xbc, 0x81, 0x02, 0x18, 0xac, 0x12, 0xc6, 0xf9, 0x64,  \
-    0x8b, 0x87, 0xc3, 0x00                                                   \
-}
-/* END FILE */
-
-/*
- *
- * Test certificates and keys as C variables
- *
- */
-
-/*
- * CA
- */
-
-const char mbedtls_test_ca_crt_ec_pem[]           = TEST_CA_CRT_EC_PEM;
-const char mbedtls_test_ca_key_ec_pem[]           = TEST_CA_KEY_EC_PEM;
-const char mbedtls_test_ca_pwd_ec_pem[]           = TEST_CA_PWD_EC_PEM;
-const char mbedtls_test_ca_key_rsa_pem[]          = TEST_CA_KEY_RSA_PEM;
-const char mbedtls_test_ca_pwd_rsa_pem[]          = TEST_CA_PWD_RSA_PEM;
-const char mbedtls_test_ca_crt_rsa_sha1_pem[]     = TEST_CA_CRT_RSA_SHA1_PEM;
-const char mbedtls_test_ca_crt_rsa_sha256_pem[]   = TEST_CA_CRT_RSA_SHA256_PEM;
-
-const unsigned char mbedtls_test_ca_crt_ec_der[]   = TEST_CA_CRT_EC_DER;
-const unsigned char mbedtls_test_ca_key_ec_der[]   = TEST_CA_KEY_EC_DER;
-const unsigned char mbedtls_test_ca_key_rsa_der[]  = TEST_CA_KEY_RSA_DER;
-const unsigned char mbedtls_test_ca_crt_rsa_sha1_der[]   =
-    TEST_CA_CRT_RSA_SHA1_DER;
-const unsigned char mbedtls_test_ca_crt_rsa_sha256_der[] =
-    TEST_CA_CRT_RSA_SHA256_DER;
-
-const size_t mbedtls_test_ca_crt_ec_pem_len =
-    sizeof( mbedtls_test_ca_crt_ec_pem );
-const size_t mbedtls_test_ca_key_ec_pem_len =
-    sizeof( mbedtls_test_ca_key_ec_pem );
-const size_t mbedtls_test_ca_pwd_ec_pem_len =
-    sizeof( mbedtls_test_ca_pwd_ec_pem ) - 1;
-const size_t mbedtls_test_ca_key_rsa_pem_len =
-    sizeof( mbedtls_test_ca_key_rsa_pem );
-const size_t mbedtls_test_ca_pwd_rsa_pem_len =
-    sizeof( mbedtls_test_ca_pwd_rsa_pem ) - 1;
-const size_t mbedtls_test_ca_crt_rsa_sha1_pem_len =
-    sizeof( mbedtls_test_ca_crt_rsa_sha1_pem );
-const size_t mbedtls_test_ca_crt_rsa_sha256_pem_len =
-    sizeof( mbedtls_test_ca_crt_rsa_sha256_pem );
-
-const size_t mbedtls_test_ca_crt_ec_der_len =
-    sizeof( mbedtls_test_ca_crt_ec_der );
-const size_t mbedtls_test_ca_key_ec_der_len =
-    sizeof( mbedtls_test_ca_key_ec_der );
-const size_t mbedtls_test_ca_pwd_ec_der_len = 0;
-const size_t mbedtls_test_ca_key_rsa_der_len =
-    sizeof( mbedtls_test_ca_key_rsa_der );
-const size_t mbedtls_test_ca_pwd_rsa_der_len = 0;
-const size_t mbedtls_test_ca_crt_rsa_sha1_der_len =
-    sizeof( mbedtls_test_ca_crt_rsa_sha1_der );
-const size_t mbedtls_test_ca_crt_rsa_sha256_der_len =
-    sizeof( mbedtls_test_ca_crt_rsa_sha256_der );
-
-/*
- * Server
- */
-
-const char mbedtls_test_srv_crt_ec_pem[]           = TEST_SRV_CRT_EC_PEM;
-const char mbedtls_test_srv_key_ec_pem[]           = TEST_SRV_KEY_EC_PEM;
-const char mbedtls_test_srv_pwd_ec_pem[]           = "";
-const char mbedtls_test_srv_key_rsa_pem[]          = TEST_SRV_KEY_RSA_PEM;
-const char mbedtls_test_srv_pwd_rsa_pem[]          = "";
-const char mbedtls_test_srv_crt_rsa_sha1_pem[]     = TEST_SRV_CRT_RSA_SHA1_PEM;
-const char mbedtls_test_srv_crt_rsa_sha256_pem[]   = TEST_SRV_CRT_RSA_SHA256_PEM;
-
-const unsigned char mbedtls_test_srv_crt_ec_der[]   = TEST_SRV_CRT_EC_DER;
-const unsigned char mbedtls_test_srv_key_ec_der[]   = TEST_SRV_KEY_EC_DER;
-const unsigned char mbedtls_test_srv_key_rsa_der[]  = TEST_SRV_KEY_RSA_DER;
-const unsigned char mbedtls_test_srv_crt_rsa_sha1_der[]   =
-    TEST_SRV_CRT_RSA_SHA1_DER;
-const unsigned char mbedtls_test_srv_crt_rsa_sha256_der[] =
-    TEST_SRV_CRT_RSA_SHA256_DER;
-
-const size_t mbedtls_test_srv_crt_ec_pem_len =
-    sizeof( mbedtls_test_srv_crt_ec_pem );
-const size_t mbedtls_test_srv_key_ec_pem_len =
-    sizeof( mbedtls_test_srv_key_ec_pem );
-const size_t mbedtls_test_srv_pwd_ec_pem_len =
-    sizeof( mbedtls_test_srv_pwd_ec_pem ) - 1;
-const size_t mbedtls_test_srv_key_rsa_pem_len =
-    sizeof( mbedtls_test_srv_key_rsa_pem );
-const size_t mbedtls_test_srv_pwd_rsa_pem_len =
-    sizeof( mbedtls_test_srv_pwd_rsa_pem ) - 1;
-const size_t mbedtls_test_srv_crt_rsa_sha1_pem_len =
-    sizeof( mbedtls_test_srv_crt_rsa_sha1_pem );
-const size_t mbedtls_test_srv_crt_rsa_sha256_pem_len =
-    sizeof( mbedtls_test_srv_crt_rsa_sha256_pem );
-
-const size_t mbedtls_test_srv_crt_ec_der_len =
-    sizeof( mbedtls_test_srv_crt_ec_der );
-const size_t mbedtls_test_srv_key_ec_der_len =
-    sizeof( mbedtls_test_srv_key_ec_der );
-const size_t mbedtls_test_srv_pwd_ec_der_len = 0;
-const size_t mbedtls_test_srv_key_rsa_der_len =
-    sizeof( mbedtls_test_srv_key_rsa_der );
-const size_t mbedtls_test_srv_pwd_rsa_der_len = 0;
-const size_t mbedtls_test_srv_crt_rsa_sha1_der_len =
-    sizeof( mbedtls_test_srv_crt_rsa_sha1_der );
-const size_t mbedtls_test_srv_crt_rsa_sha256_der_len =
-    sizeof( mbedtls_test_srv_crt_rsa_sha256_der );
-
-/*
- * Client
- */
-
-const char mbedtls_test_cli_crt_ec_pem[]   = TEST_CLI_CRT_EC_PEM;
-const char mbedtls_test_cli_key_ec_pem[]   = TEST_CLI_KEY_EC_PEM;
-const char mbedtls_test_cli_pwd_ec_pem[]   = "";
-const char mbedtls_test_cli_key_rsa_pem[]  = TEST_CLI_KEY_RSA_PEM;
-const char mbedtls_test_cli_pwd_rsa_pem[]  = "";
-const char mbedtls_test_cli_crt_rsa_pem[]  = TEST_CLI_CRT_RSA_PEM;
-
-const unsigned char mbedtls_test_cli_crt_ec_der[]   = TEST_CLI_CRT_EC_DER;
-const unsigned char mbedtls_test_cli_key_ec_der[]   = TEST_CLI_KEY_EC_DER;
-const unsigned char mbedtls_test_cli_key_rsa_der[]  = TEST_CLI_KEY_RSA_DER;
-const unsigned char mbedtls_test_cli_crt_rsa_der[]  = TEST_CLI_CRT_RSA_DER;
-
-const size_t mbedtls_test_cli_crt_ec_pem_len =
-    sizeof( mbedtls_test_cli_crt_ec_pem );
-const size_t mbedtls_test_cli_key_ec_pem_len =
-    sizeof( mbedtls_test_cli_key_ec_pem );
-const size_t mbedtls_test_cli_pwd_ec_pem_len =
-    sizeof( mbedtls_test_cli_pwd_ec_pem ) - 1;
-const size_t mbedtls_test_cli_key_rsa_pem_len =
-    sizeof( mbedtls_test_cli_key_rsa_pem );
-const size_t mbedtls_test_cli_pwd_rsa_pem_len =
-    sizeof( mbedtls_test_cli_pwd_rsa_pem ) - 1;
-const size_t mbedtls_test_cli_crt_rsa_pem_len =
-    sizeof( mbedtls_test_cli_crt_rsa_pem );
-
-const size_t mbedtls_test_cli_crt_ec_der_len =
-    sizeof( mbedtls_test_cli_crt_ec_der );
-const size_t mbedtls_test_cli_key_ec_der_len =
-    sizeof( mbedtls_test_cli_key_ec_der );
-const size_t mbedtls_test_cli_key_rsa_der_len =
-    sizeof( mbedtls_test_cli_key_rsa_der );
-const size_t mbedtls_test_cli_crt_rsa_der_len =
-    sizeof( mbedtls_test_cli_crt_rsa_der );
-
-/*
- *
- * Definitions of test CRTs without specification of all parameters, choosing
- * them automatically according to the config. For example, mbedtls_test_ca_crt
- * is one of mbedtls_test_ca_crt_{rsa|ec}_{sha1|sha256}_{pem|der}.
- *
- */
-
-/*
- * Dispatch between PEM and DER according to config
- */
-
-#if defined(MBEDTLS_PEM_PARSE_C)
-
-/* PEM encoded test CA certificates and keys */
-
-#define TEST_CA_KEY_RSA        TEST_CA_KEY_RSA_PEM
-#define TEST_CA_PWD_RSA        TEST_CA_PWD_RSA_PEM
-#define TEST_CA_CRT_RSA_SHA256 TEST_CA_CRT_RSA_SHA256_PEM
-#define TEST_CA_CRT_RSA_SHA1   TEST_CA_CRT_RSA_SHA1_PEM
-#define TEST_CA_KEY_EC         TEST_CA_KEY_EC_PEM
-#define TEST_CA_PWD_EC         TEST_CA_PWD_EC_PEM
-#define TEST_CA_CRT_EC         TEST_CA_CRT_EC_PEM
-
-/* PEM encoded test server certificates and keys */
-
-#define TEST_SRV_KEY_RSA        TEST_SRV_KEY_RSA_PEM
-#define TEST_SRV_PWD_RSA        ""
-#define TEST_SRV_CRT_RSA_SHA256 TEST_SRV_CRT_RSA_SHA256_PEM
-#define TEST_SRV_CRT_RSA_SHA1   TEST_SRV_CRT_RSA_SHA1_PEM
-#define TEST_SRV_KEY_EC         TEST_SRV_KEY_EC_PEM
-#define TEST_SRV_PWD_EC         ""
-#define TEST_SRV_CRT_EC         TEST_SRV_CRT_EC_PEM
-
-/* PEM encoded test client certificates and keys */
-
-#define TEST_CLI_KEY_RSA  TEST_CLI_KEY_RSA_PEM
-#define TEST_CLI_PWD_RSA  ""
-#define TEST_CLI_CRT_RSA  TEST_CLI_CRT_RSA_PEM
-#define TEST_CLI_KEY_EC   TEST_CLI_KEY_EC_PEM
-#define TEST_CLI_PWD_EC   ""
-#define TEST_CLI_CRT_EC   TEST_CLI_CRT_EC_PEM
-
-#else /* MBEDTLS_PEM_PARSE_C */
-
-/* DER encoded test CA certificates and keys */
-
-#define TEST_CA_KEY_RSA        TEST_CA_KEY_RSA_DER
-#define TEST_CA_PWD_RSA        ""
-#define TEST_CA_CRT_RSA_SHA256 TEST_CA_CRT_RSA_SHA256_DER
-#define TEST_CA_CRT_RSA_SHA1   TEST_CA_CRT_RSA_SHA1_DER
-#define TEST_CA_KEY_EC         TEST_CA_KEY_EC_DER
-#define TEST_CA_PWD_EC         ""
-#define TEST_CA_CRT_EC         TEST_CA_CRT_EC_DER
-
-/* DER encoded test server certificates and keys */
-
-#define TEST_SRV_KEY_RSA        TEST_SRV_KEY_RSA_DER
-#define TEST_SRV_PWD_RSA        ""
-#define TEST_SRV_CRT_RSA_SHA256 TEST_SRV_CRT_RSA_SHA256_DER
-#define TEST_SRV_CRT_RSA_SHA1   TEST_SRV_CRT_RSA_SHA1_DER
-#define TEST_SRV_KEY_EC         TEST_SRV_KEY_EC_DER
-#define TEST_SRV_PWD_EC         ""
-#define TEST_SRV_CRT_EC         TEST_SRV_CRT_EC_DER
-
-/* DER encoded test client certificates and keys */
-
-#define TEST_CLI_KEY_RSA  TEST_CLI_KEY_RSA_DER
-#define TEST_CLI_PWD_RSA  ""
-#define TEST_CLI_CRT_RSA  TEST_CLI_CRT_RSA_DER
-#define TEST_CLI_KEY_EC   TEST_CLI_KEY_EC_DER
-#define TEST_CLI_PWD_EC   ""
-#define TEST_CLI_CRT_EC   TEST_CLI_CRT_EC_DER
-
-#endif /* MBEDTLS_PEM_PARSE_C */
-
-const char mbedtls_test_ca_key_rsa[]         = TEST_CA_KEY_RSA;
-const char mbedtls_test_ca_pwd_rsa[]         = TEST_CA_PWD_RSA;
-const char mbedtls_test_ca_crt_rsa_sha256[]  = TEST_CA_CRT_RSA_SHA256;
-const char mbedtls_test_ca_crt_rsa_sha1[]    = TEST_CA_CRT_RSA_SHA1;
-const char mbedtls_test_ca_key_ec[]          = TEST_CA_KEY_EC;
-const char mbedtls_test_ca_pwd_ec[]          = TEST_CA_PWD_EC;
-const char mbedtls_test_ca_crt_ec[]          = TEST_CA_CRT_EC;
-
-const char mbedtls_test_srv_key_rsa[]        = TEST_SRV_KEY_RSA;
-const char mbedtls_test_srv_pwd_rsa[]        = TEST_SRV_PWD_RSA;
-const char mbedtls_test_srv_crt_rsa_sha256[] = TEST_SRV_CRT_RSA_SHA256;
-const char mbedtls_test_srv_crt_rsa_sha1[]   = TEST_SRV_CRT_RSA_SHA1;
-const char mbedtls_test_srv_key_ec[]         = TEST_SRV_KEY_EC;
-const char mbedtls_test_srv_pwd_ec[]         = TEST_SRV_PWD_EC;
-const char mbedtls_test_srv_crt_ec[]         = TEST_SRV_CRT_EC;
-
-const char mbedtls_test_cli_key_rsa[]        = TEST_CLI_KEY_RSA;
-const char mbedtls_test_cli_pwd_rsa[]        = TEST_CLI_PWD_RSA;
-const char mbedtls_test_cli_crt_rsa[]        = TEST_CLI_CRT_RSA;
-const char mbedtls_test_cli_key_ec[]         = TEST_CLI_KEY_EC;
-const char mbedtls_test_cli_pwd_ec[]         = TEST_CLI_PWD_EC;
-const char mbedtls_test_cli_crt_ec[]         = TEST_CLI_CRT_EC;
-
-const size_t mbedtls_test_ca_key_rsa_len =
-    sizeof( mbedtls_test_ca_key_rsa );
-const size_t mbedtls_test_ca_pwd_rsa_len =
-    sizeof( mbedtls_test_ca_pwd_rsa ) - 1;
-const size_t mbedtls_test_ca_crt_rsa_sha256_len =
-    sizeof( mbedtls_test_ca_crt_rsa_sha256 );
-const size_t mbedtls_test_ca_crt_rsa_sha1_len =
-    sizeof( mbedtls_test_ca_crt_rsa_sha1 );
-const size_t mbedtls_test_ca_key_ec_len =
-    sizeof( mbedtls_test_ca_key_ec );
-const size_t mbedtls_test_ca_pwd_ec_len =
-    sizeof( mbedtls_test_ca_pwd_ec ) - 1;
-const size_t mbedtls_test_ca_crt_ec_len =
-    sizeof( mbedtls_test_ca_crt_ec );
-
-const size_t mbedtls_test_srv_key_rsa_len =
-    sizeof( mbedtls_test_srv_key_rsa );
-const size_t mbedtls_test_srv_pwd_rsa_len =
-    sizeof( mbedtls_test_srv_pwd_rsa ) -1;
-const size_t mbedtls_test_srv_crt_rsa_sha256_len =
-    sizeof( mbedtls_test_srv_crt_rsa_sha256 );
-const size_t mbedtls_test_srv_crt_rsa_sha1_len =
-    sizeof( mbedtls_test_srv_crt_rsa_sha1 );
-const size_t mbedtls_test_srv_key_ec_len =
-    sizeof( mbedtls_test_srv_key_ec );
-const size_t mbedtls_test_srv_pwd_ec_len =
-    sizeof( mbedtls_test_srv_pwd_ec ) - 1;
-const size_t mbedtls_test_srv_crt_ec_len =
-    sizeof( mbedtls_test_srv_crt_ec );
-
-const size_t mbedtls_test_cli_key_rsa_len =
-    sizeof( mbedtls_test_cli_key_rsa );
-const size_t mbedtls_test_cli_pwd_rsa_len =
-    sizeof( mbedtls_test_cli_pwd_rsa ) - 1;
-const size_t mbedtls_test_cli_crt_rsa_len =
-    sizeof( mbedtls_test_cli_crt_rsa );
-const size_t mbedtls_test_cli_key_ec_len =
-    sizeof( mbedtls_test_cli_key_ec );
-const size_t mbedtls_test_cli_pwd_ec_len =
-    sizeof( mbedtls_test_cli_pwd_ec ) - 1;
-const size_t mbedtls_test_cli_crt_ec_len =
-    sizeof( mbedtls_test_cli_crt_ec );
-
-/*
- * Dispatch between SHA-1 and SHA-256
- */
-
-#if defined(MBEDTLS_SHA256_C)
-#define TEST_CA_CRT_RSA  TEST_CA_CRT_RSA_SHA256
-#define TEST_SRV_CRT_RSA TEST_SRV_CRT_RSA_SHA256
-#else
-#define TEST_CA_CRT_RSA  TEST_CA_CRT_RSA_SHA1
-#define TEST_SRV_CRT_RSA TEST_SRV_CRT_RSA_SHA1
-#endif /* MBEDTLS_SHA256_C */
-
-const char mbedtls_test_ca_crt_rsa[]  = TEST_CA_CRT_RSA;
-const char mbedtls_test_srv_crt_rsa[] = TEST_SRV_CRT_RSA;
-
-const size_t mbedtls_test_ca_crt_rsa_len =
-    sizeof( mbedtls_test_ca_crt_rsa );
-const size_t mbedtls_test_srv_crt_rsa_len =
-    sizeof( mbedtls_test_srv_crt_rsa );
-
-/*
- * Dispatch between RSA and EC
- */
-
-#if defined(MBEDTLS_RSA_C)
-
-#define TEST_CA_KEY TEST_CA_KEY_RSA
-#define TEST_CA_PWD TEST_CA_PWD_RSA
-#define TEST_CA_CRT TEST_CA_CRT_RSA
-
-#define TEST_SRV_KEY TEST_SRV_KEY_RSA
-#define TEST_SRV_PWD TEST_SRV_PWD_RSA
-#define TEST_SRV_CRT TEST_SRV_CRT_RSA
-
-#define TEST_CLI_KEY TEST_CLI_KEY_RSA
-#define TEST_CLI_PWD TEST_CLI_PWD_RSA
-#define TEST_CLI_CRT TEST_CLI_CRT_RSA
-
-#else /* no RSA, so assume ECDSA */
-
-#define TEST_CA_KEY TEST_CA_KEY_EC
-#define TEST_CA_PWD TEST_CA_PWD_EC
-#define TEST_CA_CRT TEST_CA_CRT_EC
-
-#define TEST_SRV_KEY TEST_SRV_KEY_EC
-#define TEST_SRV_PWD TEST_SRV_PWD_EC
-#define TEST_SRV_CRT TEST_SRV_CRT_EC
-
-#define TEST_CLI_KEY TEST_CLI_KEY_EC
-#define TEST_CLI_PWD TEST_CLI_PWD_EC
-#define TEST_CLI_CRT TEST_CLI_CRT_EC
-#endif /* MBEDTLS_RSA_C */
-
-/* API stability forces us to declare
- *   mbedtls_test_{ca|srv|cli}_{key|pwd|crt}
- * as pointers. */
-static const char test_ca_key[] = TEST_CA_KEY;
-static const char test_ca_pwd[] = TEST_CA_PWD;
-static const char test_ca_crt[] = TEST_CA_CRT;
-
-static const char test_srv_key[] = TEST_SRV_KEY;
-static const char test_srv_pwd[] = TEST_SRV_PWD;
-static const char test_srv_crt[] = TEST_SRV_CRT;
-
-static const char test_cli_key[] = TEST_CLI_KEY;
-static const char test_cli_pwd[] = TEST_CLI_PWD;
-static const char test_cli_crt[] = TEST_CLI_CRT;
-
-const char *mbedtls_test_ca_key = test_ca_key;
-const char *mbedtls_test_ca_pwd = test_ca_pwd;
-const char *mbedtls_test_ca_crt = test_ca_crt;
-
-const char *mbedtls_test_srv_key = test_srv_key;
-const char *mbedtls_test_srv_pwd = test_srv_pwd;
-const char *mbedtls_test_srv_crt = test_srv_crt;
-
-const char *mbedtls_test_cli_key = test_cli_key;
-const char *mbedtls_test_cli_pwd = test_cli_pwd;
-const char *mbedtls_test_cli_crt = test_cli_crt;
-
-const size_t mbedtls_test_ca_key_len =
-    sizeof( test_ca_key );
-const size_t mbedtls_test_ca_pwd_len =
-    sizeof( test_ca_pwd ) - 1;
-const size_t mbedtls_test_ca_crt_len =
-    sizeof( test_ca_crt );
-
-const size_t mbedtls_test_srv_key_len =
-    sizeof( test_srv_key );
-const size_t mbedtls_test_srv_pwd_len =
-    sizeof( test_srv_pwd ) - 1;
-const size_t mbedtls_test_srv_crt_len =
-    sizeof( test_srv_crt );
-
-const size_t mbedtls_test_cli_key_len =
-    sizeof( test_cli_key );
-const size_t mbedtls_test_cli_pwd_len =
-    sizeof( test_cli_pwd ) - 1;
-const size_t mbedtls_test_cli_crt_len =
-    sizeof( test_cli_crt );
-
-/*
- *
- * Lists of certificates
- *
- */
-
-/* List of CAs in PEM or DER, depending on config */
-const char * mbedtls_test_cas[] = {
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA1_C)
-    mbedtls_test_ca_crt_rsa_sha1,
-#endif
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C)
-    mbedtls_test_ca_crt_rsa_sha256,
-#endif
-#if defined(MBEDTLS_ECDSA_C)
-    mbedtls_test_ca_crt_ec,
-#endif
-    NULL
-};
-const size_t mbedtls_test_cas_len[] = {
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA1_C)
-    sizeof( mbedtls_test_ca_crt_rsa_sha1 ),
-#endif
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C)
-    sizeof( mbedtls_test_ca_crt_rsa_sha256 ),
-#endif
-#if defined(MBEDTLS_ECDSA_C)
-    sizeof( mbedtls_test_ca_crt_ec ),
-#endif
-    0
-};
-
-/* List of all available CA certificates in DER format */
-const unsigned char * mbedtls_test_cas_der[] = {
-#if defined(MBEDTLS_RSA_C)
-#if defined(MBEDTLS_SHA256_C)
-    mbedtls_test_ca_crt_rsa_sha256_der,
-#endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA1_C)
-    mbedtls_test_ca_crt_rsa_sha1_der,
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_RSA_C */
-#if defined(MBEDTLS_ECDSA_C)
-    mbedtls_test_ca_crt_ec_der,
-#endif /* MBEDTLS_ECDSA_C */
-    NULL
-};
-
-const size_t mbedtls_test_cas_der_len[] = {
-#if defined(MBEDTLS_RSA_C)
-#if defined(MBEDTLS_SHA256_C)
-    sizeof( mbedtls_test_ca_crt_rsa_sha256_der ),
-#endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA1_C)
-    sizeof( mbedtls_test_ca_crt_rsa_sha1_der ),
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_RSA_C */
-#if defined(MBEDTLS_ECDSA_C)
-    sizeof( mbedtls_test_ca_crt_ec_der ),
-#endif /* MBEDTLS_ECDSA_C */
-    0
-};
-
-/* Concatenation of all available CA certificates in PEM format */
-#if defined(MBEDTLS_PEM_PARSE_C)
-const char mbedtls_test_cas_pem[] =
-#if defined(MBEDTLS_RSA_C)
-#if defined(MBEDTLS_SHA256_C)
-    TEST_CA_CRT_RSA_SHA256_PEM
-#endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA1_C)
-    TEST_CA_CRT_RSA_SHA1_PEM
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_RSA_C */
-#if defined(MBEDTLS_ECDSA_C)
-    TEST_CA_CRT_EC_PEM
-#endif /* MBEDTLS_ECDSA_C */
-    "";
-const size_t mbedtls_test_cas_pem_len = sizeof( mbedtls_test_cas_pem );
-#endif /* MBEDTLS_PEM_PARSE_C */
-
-#endif /* MBEDTLS_CERTS_C */
diff --git a/lib/libmbedtls/mbedtls/library/chacha20.c b/lib/libmbedtls/mbedtls/library/chacha20.c
index 658f046..cbb01f4 100644
--- a/lib/libmbedtls/mbedtls/library/chacha20.c
+++ b/lib/libmbedtls/mbedtls/library/chacha20.c
@@ -32,34 +32,16 @@
 #include <stddef.h>
 #include <string.h>
 
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
 
 #if !defined(MBEDTLS_CHACHA20_ALT)
 
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
-    !defined(inline) && !defined(__cplusplus)
-#define inline __inline
-#endif
+#define ROTL32(value, amount) \
+    ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount))))
 
-/* Parameter validation macros */
-#define CHACHA20_VALIDATE_RET( cond )                                       \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
-#define CHACHA20_VALIDATE( cond )                                           \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
+#define CHACHA20_CTR_INDEX (12U)
 
-#define ROTL32( value, amount ) \
-    ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) )
-
-#define CHACHA20_CTR_INDEX ( 12U )
-
-#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
+#define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U)
 
 /**
  * \brief           ChaCha20 quarter round operation.
@@ -76,31 +58,31 @@
  * \param c         The index of 'c' in the state.
  * \param d         The index of 'd' in the state.
  */
-static inline void chacha20_quarter_round( uint32_t state[16],
-                                           size_t a,
-                                           size_t b,
-                                           size_t c,
-                                           size_t d )
+static inline void chacha20_quarter_round(uint32_t state[16],
+                                          size_t a,
+                                          size_t b,
+                                          size_t c,
+                                          size_t d)
 {
     /* a += b; d ^= a; d <<<= 16; */
     state[a] += state[b];
     state[d] ^= state[a];
-    state[d] = ROTL32( state[d], 16 );
+    state[d] = ROTL32(state[d], 16);
 
     /* c += d; b ^= c; b <<<= 12 */
     state[c] += state[d];
     state[b] ^= state[c];
-    state[b] = ROTL32( state[b], 12 );
+    state[b] = ROTL32(state[b], 12);
 
     /* a += b; d ^= a; d <<<= 8; */
     state[a] += state[b];
     state[d] ^= state[a];
-    state[d] = ROTL32( state[d], 8 );
+    state[d] = ROTL32(state[d], 8);
 
     /* c += d; b ^= c; b <<<= 7; */
     state[c] += state[d];
     state[b] ^= state[c];
-    state[b] = ROTL32( state[b], 7 );
+    state[b] = ROTL32(state[b], 7);
 }
 
 /**
@@ -111,17 +93,17 @@
  *
  * \param state     The ChaCha20 state to update.
  */
-static void chacha20_inner_block( uint32_t state[16] )
+static void chacha20_inner_block(uint32_t state[16])
 {
-    chacha20_quarter_round( state, 0, 4, 8,  12 );
-    chacha20_quarter_round( state, 1, 5, 9,  13 );
-    chacha20_quarter_round( state, 2, 6, 10, 14 );
-    chacha20_quarter_round( state, 3, 7, 11, 15 );
+    chacha20_quarter_round(state, 0, 4, 8,  12);
+    chacha20_quarter_round(state, 1, 5, 9,  13);
+    chacha20_quarter_round(state, 2, 6, 10, 14);
+    chacha20_quarter_round(state, 3, 7, 11, 15);
 
-    chacha20_quarter_round( state, 0, 5, 10, 15 );
-    chacha20_quarter_round( state, 1, 6, 11, 12 );
-    chacha20_quarter_round( state, 2, 7, 8,  13 );
-    chacha20_quarter_round( state, 3, 4, 9,  14 );
+    chacha20_quarter_round(state, 0, 5, 10, 15);
+    chacha20_quarter_round(state, 1, 6, 11, 12);
+    chacha20_quarter_round(state, 2, 7, 8,  13);
+    chacha20_quarter_round(state, 3, 4, 9,  14);
 }
 
 /**
@@ -130,29 +112,30 @@
  * \param initial_state The initial ChaCha20 state (key, nonce, counter).
  * \param keystream     Generated keystream bytes are written to this buffer.
  */
-static void chacha20_block( const uint32_t initial_state[16],
-                            unsigned char keystream[64] )
+static void chacha20_block(const uint32_t initial_state[16],
+                           unsigned char keystream[64])
 {
     uint32_t working_state[16];
     size_t i;
 
-    memcpy( working_state,
-            initial_state,
-            CHACHA20_BLOCK_SIZE_BYTES );
+    memcpy(working_state,
+           initial_state,
+           CHACHA20_BLOCK_SIZE_BYTES);
 
-    for( i = 0U; i < 10U; i++ )
-        chacha20_inner_block( working_state );
+    for (i = 0U; i < 10U; i++) {
+        chacha20_inner_block(working_state);
+    }
 
-    working_state[ 0] += initial_state[ 0];
-    working_state[ 1] += initial_state[ 1];
-    working_state[ 2] += initial_state[ 2];
-    working_state[ 3] += initial_state[ 3];
-    working_state[ 4] += initial_state[ 4];
-    working_state[ 5] += initial_state[ 5];
-    working_state[ 6] += initial_state[ 6];
-    working_state[ 7] += initial_state[ 7];
-    working_state[ 8] += initial_state[ 8];
-    working_state[ 9] += initial_state[ 9];
+    working_state[0] += initial_state[0];
+    working_state[1] += initial_state[1];
+    working_state[2] += initial_state[2];
+    working_state[3] += initial_state[3];
+    working_state[4] += initial_state[4];
+    working_state[5] += initial_state[5];
+    working_state[6] += initial_state[6];
+    working_state[7] += initial_state[7];
+    working_state[8] += initial_state[8];
+    working_state[9] += initial_state[9];
     working_state[10] += initial_state[10];
     working_state[11] += initial_state[11];
     working_state[12] += initial_state[12];
@@ -160,41 +143,34 @@
     working_state[14] += initial_state[14];
     working_state[15] += initial_state[15];
 
-    for( i = 0U; i < 16; i++ )
-    {
+    for (i = 0U; i < 16; i++) {
         size_t offset = i * 4U;
 
         MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
     }
 
-    mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
+    mbedtls_platform_zeroize(working_state, sizeof(working_state));
 }
 
-void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
+void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx)
 {
-    CHACHA20_VALIDATE( ctx != NULL );
-
-    mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
-    mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
+    mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state));
+    mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
 
     /* Initially, there's no keystream bytes available */
     ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
 }
 
-void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
+void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx)
 {
-    if( ctx != NULL )
-    {
-        mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
+    if (ctx != NULL) {
+        mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context));
     }
 }
 
-int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
-                            const unsigned char key[32] )
+int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,
+                            const unsigned char key[32])
 {
-    CHACHA20_VALIDATE_RET( ctx != NULL );
-    CHACHA20_VALIDATE_RET( key != NULL );
-
     /* ChaCha20 constants - the string "expand 32-byte k" */
     ctx->state[0] = 0x61707865;
     ctx->state[1] = 0x3320646e;
@@ -202,58 +178,49 @@
     ctx->state[3] = 0x6b206574;
 
     /* Set key */
-    ctx->state[4]  = MBEDTLS_GET_UINT32_LE( key, 0 );
-    ctx->state[5]  = MBEDTLS_GET_UINT32_LE( key, 4 );
-    ctx->state[6]  = MBEDTLS_GET_UINT32_LE( key, 8 );
-    ctx->state[7]  = MBEDTLS_GET_UINT32_LE( key, 12 );
-    ctx->state[8]  = MBEDTLS_GET_UINT32_LE( key, 16 );
-    ctx->state[9]  = MBEDTLS_GET_UINT32_LE( key, 20 );
-    ctx->state[10] = MBEDTLS_GET_UINT32_LE( key, 24 );
-    ctx->state[11] = MBEDTLS_GET_UINT32_LE( key, 28 );
+    ctx->state[4]  = MBEDTLS_GET_UINT32_LE(key, 0);
+    ctx->state[5]  = MBEDTLS_GET_UINT32_LE(key, 4);
+    ctx->state[6]  = MBEDTLS_GET_UINT32_LE(key, 8);
+    ctx->state[7]  = MBEDTLS_GET_UINT32_LE(key, 12);
+    ctx->state[8]  = MBEDTLS_GET_UINT32_LE(key, 16);
+    ctx->state[9]  = MBEDTLS_GET_UINT32_LE(key, 20);
+    ctx->state[10] = MBEDTLS_GET_UINT32_LE(key, 24);
+    ctx->state[11] = MBEDTLS_GET_UINT32_LE(key, 28);
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
-                             const unsigned char nonce[12],
-                             uint32_t counter )
+int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx,
+                            const unsigned char nonce[12],
+                            uint32_t counter)
 {
-    CHACHA20_VALIDATE_RET( ctx != NULL );
-    CHACHA20_VALIDATE_RET( nonce != NULL );
-
     /* Counter */
     ctx->state[12] = counter;
 
     /* Nonce */
-    ctx->state[13] = MBEDTLS_GET_UINT32_LE( nonce, 0 );
-    ctx->state[14] = MBEDTLS_GET_UINT32_LE( nonce, 4 );
-    ctx->state[15] = MBEDTLS_GET_UINT32_LE( nonce, 8 );
+    ctx->state[13] = MBEDTLS_GET_UINT32_LE(nonce, 0);
+    ctx->state[14] = MBEDTLS_GET_UINT32_LE(nonce, 4);
+    ctx->state[15] = MBEDTLS_GET_UINT32_LE(nonce, 8);
 
-    mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
+    mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
 
     /* Initially, there's no keystream bytes available */
     ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
-                              size_t size,
-                              const unsigned char *input,
-                              unsigned char *output )
+int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx,
+                            size_t size,
+                            const unsigned char *input,
+                            unsigned char *output)
 {
     size_t offset = 0U;
-    size_t i;
-
-    CHACHA20_VALIDATE_RET( ctx != NULL );
-    CHACHA20_VALIDATE_RET( size == 0 || input  != NULL );
-    CHACHA20_VALIDATE_RET( size == 0 || output != NULL );
 
     /* Use leftover keystream bytes, if available */
-    while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
-    {
+    while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) {
         output[offset] = input[offset]
-                       ^ ctx->keystream8[ctx->keystream_bytes_used];
+                         ^ ctx->keystream8[ctx->keystream_bytes_used];
 
         ctx->keystream_bytes_used++;
         offset++;
@@ -261,77 +228,59 @@
     }
 
     /* Process full blocks */
-    while( size >= CHACHA20_BLOCK_SIZE_BYTES )
-    {
+    while (size >= CHACHA20_BLOCK_SIZE_BYTES) {
         /* Generate new keystream block and increment counter */
-        chacha20_block( ctx->state, ctx->keystream8 );
+        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;
     }
 
     /* Last (partial) block */
-    if( size > 0U )
-    {
+    if (size > 0U) {
         /* Generate new keystream block and increment counter */
-        chacha20_block( ctx->state, ctx->keystream8 );
+        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;
 
     }
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_chacha20_crypt( const unsigned char key[32],
-                            const unsigned char nonce[12],
-                            uint32_t counter,
-                            size_t data_len,
-                            const unsigned char* input,
-                            unsigned char* output )
+int mbedtls_chacha20_crypt(const unsigned char key[32],
+                           const unsigned char nonce[12],
+                           uint32_t counter,
+                           size_t data_len,
+                           const unsigned char *input,
+                           unsigned char *output)
 {
     mbedtls_chacha20_context ctx;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    CHACHA20_VALIDATE_RET( key != NULL );
-    CHACHA20_VALIDATE_RET( nonce != NULL );
-    CHACHA20_VALIDATE_RET( data_len == 0 || input  != NULL );
-    CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL );
+    mbedtls_chacha20_init(&ctx);
 
-    mbedtls_chacha20_init( &ctx );
-
-    ret = mbedtls_chacha20_setkey( &ctx, key );
-    if( ret != 0 )
+    ret = mbedtls_chacha20_setkey(&ctx, key);
+    if (ret != 0) {
         goto cleanup;
+    }
 
-    ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
-    if( ret != 0 )
+    ret = mbedtls_chacha20_starts(&ctx, nonce, counter);
+    if (ret != 0) {
         goto cleanup;
+    }
 
-    ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
+    ret = mbedtls_chacha20_update(&ctx, data_len, input, output);
 
 cleanup:
-    mbedtls_chacha20_free( &ctx );
-    return( ret );
+    mbedtls_chacha20_free(&ctx);
+    return ret;
 }
 
 #endif /* !MBEDTLS_CHACHA20_ALT */
@@ -507,50 +456,52 @@
 /* Make sure no other definition is already present. */
 #undef ASSERT
 
-#define ASSERT( cond, args )            \
+#define ASSERT(cond, args)            \
     do                                  \
     {                                   \
-        if( ! ( cond ) )                \
+        if (!(cond))                \
         {                               \
-            if( verbose != 0 )          \
-                mbedtls_printf args;    \
+            if (verbose != 0)          \
+            mbedtls_printf args;    \
                                         \
-            return( -1 );               \
+            return -1;               \
         }                               \
     }                                   \
-    while( 0 )
+    while (0)
 
-int mbedtls_chacha20_self_test( int verbose )
+int mbedtls_chacha20_self_test(int verbose)
 {
     unsigned char output[381];
     unsigned i;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    for( i = 0U; i < 2U; i++ )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "  ChaCha20 test %u ", i );
+    for (i = 0U; i < 2U; i++) {
+        if (verbose != 0) {
+            mbedtls_printf("  ChaCha20 test %u ", i);
+        }
 
-        ret = mbedtls_chacha20_crypt( test_keys[i],
-                                      test_nonces[i],
-                                      test_counters[i],
-                                      test_lengths[i],
-                                      test_input[i],
-                                      output );
+        ret = mbedtls_chacha20_crypt(test_keys[i],
+                                     test_nonces[i],
+                                     test_counters[i],
+                                     test_lengths[i],
+                                     test_input[i],
+                                     output);
 
-        ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
+        ASSERT(0 == ret, ("error code: %i\n", ret));
 
-        ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
-                ( "failed (output)\n" ) );
+        ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]),
+               ("failed (output)\n"));
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
-    return( 0 );
+    return 0;
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/lib/libmbedtls/mbedtls/library/chachapoly.c b/lib/libmbedtls/mbedtls/library/chachapoly.c
index dc75b20..0124d75 100644
--- a/lib/libmbedtls/mbedtls/library/chachapoly.c
+++ b/lib/libmbedtls/mbedtls/library/chachapoly.c
@@ -28,46 +28,34 @@
 
 #include <string.h>
 
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
 
 #if !defined(MBEDTLS_CHACHAPOLY_ALT)
 
-/* Parameter validation macros */
-#define CHACHAPOLY_VALIDATE_RET( cond )                                       \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA )
-#define CHACHAPOLY_VALIDATE( cond )                                           \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
-
-#define CHACHAPOLY_STATE_INIT       ( 0 )
-#define CHACHAPOLY_STATE_AAD        ( 1 )
-#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
-#define CHACHAPOLY_STATE_FINISHED   ( 3 )
+#define CHACHAPOLY_STATE_INIT       (0)
+#define CHACHAPOLY_STATE_AAD        (1)
+#define CHACHAPOLY_STATE_CIPHERTEXT (2)   /* Encrypting or decrypting */
+#define CHACHAPOLY_STATE_FINISHED   (3)
 
 /**
  * \brief           Adds nul bytes to pad the AAD for Poly1305.
  *
  * \param ctx       The ChaCha20-Poly1305 context.
  */
-static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
+static int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx)
 {
-    uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
+    uint32_t partial_block_len = (uint32_t) (ctx->aad_len % 16U);
     unsigned char zeroes[15];
 
-    if( partial_block_len == 0U )
-        return( 0 );
+    if (partial_block_len == 0U) {
+        return 0;
+    }
 
-    memset( zeroes, 0, sizeof( zeroes ) );
+    memset(zeroes, 0, sizeof(zeroes));
 
-    return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
-                                     zeroes,
-                                     16U - partial_block_len ) );
+    return mbedtls_poly1305_update(&ctx->poly1305_ctx,
+                                   zeroes,
+                                   16U - partial_block_len);
 }
 
 /**
@@ -75,86 +63,83 @@
  *
  * \param ctx       The ChaCha20-Poly1305 context.
  */
-static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
+static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx)
 {
-    uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
+    uint32_t partial_block_len = (uint32_t) (ctx->ciphertext_len % 16U);
     unsigned char zeroes[15];
 
-    if( partial_block_len == 0U )
-        return( 0 );
+    if (partial_block_len == 0U) {
+        return 0;
+    }
 
-    memset( zeroes, 0, sizeof( zeroes ) );
-    return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
-                                     zeroes,
-                                     16U - partial_block_len ) );
+    memset(zeroes, 0, sizeof(zeroes));
+    return mbedtls_poly1305_update(&ctx->poly1305_ctx,
+                                   zeroes,
+                                   16U - partial_block_len);
 }
 
-void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
+void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx)
 {
-    CHACHAPOLY_VALIDATE( ctx != NULL );
-
-    mbedtls_chacha20_init( &ctx->chacha20_ctx );
-    mbedtls_poly1305_init( &ctx->poly1305_ctx );
+    mbedtls_chacha20_init(&ctx->chacha20_ctx);
+    mbedtls_poly1305_init(&ctx->poly1305_ctx);
     ctx->aad_len        = 0U;
     ctx->ciphertext_len = 0U;
     ctx->state          = CHACHAPOLY_STATE_INIT;
     ctx->mode           = MBEDTLS_CHACHAPOLY_ENCRYPT;
 }
 
-void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
+void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_chacha20_free( &ctx->chacha20_ctx );
-    mbedtls_poly1305_free( &ctx->poly1305_ctx );
+    mbedtls_chacha20_free(&ctx->chacha20_ctx);
+    mbedtls_poly1305_free(&ctx->poly1305_ctx);
     ctx->aad_len        = 0U;
     ctx->ciphertext_len = 0U;
     ctx->state          = CHACHAPOLY_STATE_INIT;
     ctx->mode           = MBEDTLS_CHACHAPOLY_ENCRYPT;
 }
 
-int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
-                               const unsigned char key[32] )
+int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx,
+                              const unsigned char key[32])
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    CHACHAPOLY_VALIDATE_RET( ctx != NULL );
-    CHACHAPOLY_VALIDATE_RET( key != NULL );
 
-    ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
+    ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key);
 
-    return( ret );
+    return ret;
 }
 
-int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
-                               const unsigned char nonce[12],
-                               mbedtls_chachapoly_mode_t mode  )
+int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx,
+                              const unsigned char nonce[12],
+                              mbedtls_chachapoly_mode_t mode)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char poly1305_key[64];
-    CHACHAPOLY_VALIDATE_RET( ctx != NULL );
-    CHACHAPOLY_VALIDATE_RET( nonce != NULL );
 
     /* Set counter = 0, will be update to 1 when generating Poly1305 key */
-    ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
-    if( ret != 0 )
+    ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U);
+    if (ret != 0) {
         goto cleanup;
+    }
 
     /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
      * counter = 0.  This is the same as encrypting a buffer of zeroes.
      * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
      * The other 256 bits are discarded.
      */
-    memset( poly1305_key, 0, sizeof( poly1305_key ) );
-    ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
-                                      poly1305_key, poly1305_key );
-    if( ret != 0 )
+    memset(poly1305_key, 0, sizeof(poly1305_key));
+    ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, sizeof(poly1305_key),
+                                  poly1305_key, poly1305_key);
+    if (ret != 0) {
         goto cleanup;
+    }
 
-    ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
+    ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key);
 
-    if( ret == 0 )
-    {
+    if (ret == 0) {
         ctx->aad_len        = 0U;
         ctx->ciphertext_len = 0U;
         ctx->state          = CHACHAPOLY_STATE_AAD;
@@ -162,100 +147,91 @@
     }
 
 cleanup:
-    mbedtls_platform_zeroize( poly1305_key, 64U );
-    return( ret );
+    mbedtls_platform_zeroize(poly1305_key, 64U);
+    return ret;
 }
 
-int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
-                                   const unsigned char *aad,
-                                   size_t aad_len )
+int mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx,
+                                  const unsigned char *aad,
+                                  size_t aad_len)
 {
-    CHACHAPOLY_VALIDATE_RET( ctx != NULL );
-    CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
-
-    if( ctx->state != CHACHAPOLY_STATE_AAD )
-        return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+    if (ctx->state != CHACHAPOLY_STATE_AAD) {
+        return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
+    }
 
     ctx->aad_len += aad_len;
 
-    return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
+    return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len);
 }
 
-int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
-                               size_t len,
-                               const unsigned char *input,
-                               unsigned char *output )
+int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx,
+                              size_t len,
+                              const unsigned char *input,
+                              unsigned char *output)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    CHACHAPOLY_VALIDATE_RET( ctx != NULL );
-    CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL );
-    CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL );
 
-    if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
-        ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
-    {
-        return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+    if ((ctx->state != CHACHAPOLY_STATE_AAD) &&
+        (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) {
+        return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
     }
 
-    if( ctx->state == CHACHAPOLY_STATE_AAD )
-    {
+    if (ctx->state == CHACHAPOLY_STATE_AAD) {
         ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
 
-        ret = chachapoly_pad_aad( ctx );
-        if( ret != 0 )
-            return( ret );
+        ret = chachapoly_pad_aad(ctx);
+        if (ret != 0) {
+            return ret;
+        }
     }
 
     ctx->ciphertext_len += len;
 
-    if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
-    {
-        ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
-        if( ret != 0 )
-            return( ret );
+    if (ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT) {
+        ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
+        if (ret != 0) {
+            return ret;
+        }
 
-        ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
-        if( ret != 0 )
-            return( ret );
-    }
-    else /* DECRYPT */
-    {
-        ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
-        if( ret != 0 )
-            return( ret );
+        ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, output, len);
+        if (ret != 0) {
+            return ret;
+        }
+    } else { /* DECRYPT */
+        ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, input, len);
+        if (ret != 0) {
+            return ret;
+        }
 
-        ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
-        if( ret != 0 )
-            return( ret );
+        ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
+        if (ret != 0) {
+            return ret;
+        }
     }
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
-                               unsigned char mac[16] )
+int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx,
+                              unsigned char mac[16])
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char len_block[16];
-    CHACHAPOLY_VALIDATE_RET( ctx != NULL );
-    CHACHAPOLY_VALIDATE_RET( mac != NULL );
 
-    if( ctx->state == CHACHAPOLY_STATE_INIT )
-    {
-        return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
+    if (ctx->state == CHACHAPOLY_STATE_INIT) {
+        return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
     }
 
-    if( ctx->state == CHACHAPOLY_STATE_AAD )
-    {
-        ret = chachapoly_pad_aad( ctx );
-        if( ret != 0 )
-            return( ret );
-    }
-    else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
-    {
-        ret = chachapoly_pad_ciphertext( ctx );
-        if( ret != 0 )
-            return( ret );
+    if (ctx->state == CHACHAPOLY_STATE_AAD) {
+        ret = chachapoly_pad_aad(ctx);
+        if (ret != 0) {
+            return ret;
+        }
+    } else if (ctx->state == CHACHAPOLY_STATE_CIPHERTEXT) {
+        ret = chachapoly_pad_ciphertext(ctx);
+        if (ret != 0) {
+            return ret;
+        }
     }
 
     ctx->state = CHACHAPOLY_STATE_FINISHED;
@@ -266,104 +242,94 @@
     MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0);
     MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8);
 
-    ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, len_block, 16U);
+    if (ret != 0) {
+        return ret;
+    }
 
-    ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
+    ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac);
 
-    return( ret );
+    return ret;
 }
 
-static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
-                                     mbedtls_chachapoly_mode_t mode,
-                                     size_t length,
-                                     const unsigned char nonce[12],
-                                     const unsigned char *aad,
-                                     size_t aad_len,
-                                     const unsigned char *input,
-                                     unsigned char *output,
-                                     unsigned char tag[16] )
+static int chachapoly_crypt_and_tag(mbedtls_chachapoly_context *ctx,
+                                    mbedtls_chachapoly_mode_t mode,
+                                    size_t length,
+                                    const unsigned char nonce[12],
+                                    const unsigned char *aad,
+                                    size_t aad_len,
+                                    const unsigned char *input,
+                                    unsigned char *output,
+                                    unsigned char tag[16])
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
-    if( ret != 0 )
+    ret = mbedtls_chachapoly_starts(ctx, nonce, mode);
+    if (ret != 0) {
         goto cleanup;
+    }
 
-    ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
-    if( ret != 0 )
+    ret = mbedtls_chachapoly_update_aad(ctx, aad, aad_len);
+    if (ret != 0) {
         goto cleanup;
+    }
 
-    ret = mbedtls_chachapoly_update( ctx, length, input, output );
-    if( ret != 0 )
+    ret = mbedtls_chachapoly_update(ctx, length, input, output);
+    if (ret != 0) {
         goto cleanup;
+    }
 
-    ret = mbedtls_chachapoly_finish( ctx, tag );
+    ret = mbedtls_chachapoly_finish(ctx, tag);
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
-int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
-                                        size_t length,
-                                        const unsigned char nonce[12],
-                                        const unsigned char *aad,
-                                        size_t aad_len,
-                                        const unsigned char *input,
-                                        unsigned char *output,
-                                        unsigned char tag[16] )
+int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx,
+                                       size_t length,
+                                       const unsigned char nonce[12],
+                                       const unsigned char *aad,
+                                       size_t aad_len,
+                                       const unsigned char *input,
+                                       unsigned char *output,
+                                       unsigned char tag[16])
 {
-    CHACHAPOLY_VALIDATE_RET( ctx   != NULL );
-    CHACHAPOLY_VALIDATE_RET( nonce != NULL );
-    CHACHAPOLY_VALIDATE_RET( tag   != NULL );
-    CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad    != NULL );
-    CHACHAPOLY_VALIDATE_RET( length  == 0 || input  != NULL );
-    CHACHAPOLY_VALIDATE_RET( length  == 0 || output != NULL );
-
-    return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
-                                      length, nonce, aad, aad_len,
-                                      input, output, tag ) );
+    return chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
+                                    length, nonce, aad, aad_len,
+                                    input, output, tag);
 }
 
-int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
-                                     size_t length,
-                                     const unsigned char nonce[12],
-                                     const unsigned char *aad,
-                                     size_t aad_len,
-                                     const unsigned char tag[16],
-                                     const unsigned char *input,
-                                     unsigned char *output )
+int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
+                                    size_t length,
+                                    const unsigned char nonce[12],
+                                    const unsigned char *aad,
+                                    size_t aad_len,
+                                    const unsigned char tag[16],
+                                    const unsigned char *input,
+                                    unsigned char *output)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char check_tag[16];
     size_t i;
     int diff;
-    CHACHAPOLY_VALIDATE_RET( ctx   != NULL );
-    CHACHAPOLY_VALIDATE_RET( nonce != NULL );
-    CHACHAPOLY_VALIDATE_RET( tag   != NULL );
-    CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad    != NULL );
-    CHACHAPOLY_VALIDATE_RET( length  == 0 || input  != NULL );
-    CHACHAPOLY_VALIDATE_RET( length  == 0 || output != NULL );
 
-    if( ( ret = chachapoly_crypt_and_tag( ctx,
-                        MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
-                        aad, aad_len, input, output, check_tag ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = chachapoly_crypt_and_tag(ctx,
+                                        MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
+                                        aad, aad_len, input, output, check_tag)) != 0) {
+        return ret;
     }
 
     /* Check tag in "constant-time" */
-    for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
+    for (diff = 0, i = 0; i < sizeof(check_tag); i++) {
         diff |= tag[i] ^ check_tag[i];
-
-    if( diff != 0 )
-    {
-        mbedtls_platform_zeroize( output, length );
-        return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
     }
 
-    return( 0 );
+    if (diff != 0) {
+        mbedtls_platform_zeroize(output, length);
+        return MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED;
+    }
+
+    return 0;
 }
 
 #endif /* MBEDTLS_CHACHAPOLY_ALT */
@@ -459,20 +425,20 @@
 /* Make sure no other definition is already present. */
 #undef ASSERT
 
-#define ASSERT( cond, args )            \
+#define ASSERT(cond, args)            \
     do                                  \
     {                                   \
-        if( ! ( cond ) )                \
+        if (!(cond))                \
         {                               \
-            if( verbose != 0 )          \
-                mbedtls_printf args;    \
+            if (verbose != 0)          \
+            mbedtls_printf args;    \
                                         \
-            return( -1 );               \
+            return -1;               \
         }                               \
     }                                   \
-    while( 0 )
+    while (0)
 
-int mbedtls_chachapoly_self_test( int verbose )
+int mbedtls_chachapoly_self_test(int verbose)
 {
     mbedtls_chachapoly_context ctx;
     unsigned i;
@@ -480,43 +446,45 @@
     unsigned char output[200];
     unsigned char mac[16];
 
-    for( i = 0U; i < 1U; i++ )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "  ChaCha20-Poly1305 test %u ", i );
+    for (i = 0U; i < 1U; i++) {
+        if (verbose != 0) {
+            mbedtls_printf("  ChaCha20-Poly1305 test %u ", i);
+        }
 
-        mbedtls_chachapoly_init( &ctx );
+        mbedtls_chachapoly_init(&ctx);
 
-        ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
-        ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
+        ret = mbedtls_chachapoly_setkey(&ctx, test_key[i]);
+        ASSERT(0 == ret, ("setkey() error code: %i\n", ret));
 
-        ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
-                                                  test_input_len[i],
-                                                  test_nonce[i],
-                                                  test_aad[i],
-                                                  test_aad_len[i],
-                                                  test_input[i],
-                                                  output,
-                                                  mac );
+        ret = mbedtls_chachapoly_encrypt_and_tag(&ctx,
+                                                 test_input_len[i],
+                                                 test_nonce[i],
+                                                 test_aad[i],
+                                                 test_aad_len[i],
+                                                 test_input[i],
+                                                 output,
+                                                 mac);
 
-        ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
+        ASSERT(0 == ret, ("crypt_and_tag() error code: %i\n", ret));
 
-        ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
-                ( "failure (wrong output)\n" ) );
+        ASSERT(0 == memcmp(output, test_output[i], test_input_len[i]),
+               ("failure (wrong output)\n"));
 
-        ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
-                ( "failure (wrong MAC)\n" ) );
+        ASSERT(0 == memcmp(mac, test_mac[i], 16U),
+               ("failure (wrong MAC)\n"));
 
-        mbedtls_chachapoly_free( &ctx );
+        mbedtls_chachapoly_free(&ctx);
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
-    return( 0 );
+    return 0;
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/lib/libmbedtls/mbedtls/library/check_crypto_config.h b/lib/libmbedtls/mbedtls/library/check_crypto_config.h
index d7ad16a..58175e3 100644
--- a/lib/libmbedtls/mbedtls/library/check_crypto_config.h
+++ b/lib/libmbedtls/mbedtls/library/check_crypto_config.h
@@ -29,57 +29,57 @@
 #define MBEDTLS_CHECK_CRYPTO_CONFIG_H
 
 #if defined(PSA_WANT_ALG_CCM) && \
-    !( defined(PSA_WANT_KEY_TYPE_AES) || \
-       defined(PSA_WANT_KEY_TYPE_CAMELLIA) )
+    !(defined(PSA_WANT_KEY_TYPE_AES) || \
+    defined(PSA_WANT_KEY_TYPE_CAMELLIA))
 #error "PSA_WANT_ALG_CCM defined, but not all prerequisites"
 #endif
 
 #if defined(PSA_WANT_ALG_CMAC) && \
-    !( defined(PSA_WANT_KEY_TYPE_AES) || \
-       defined(PSA_WANT_KEY_TYPE_CAMELLIA) || \
-       defined(PSA_WANT_KEY_TYPE_DES) )
+    !(defined(PSA_WANT_KEY_TYPE_AES) || \
+    defined(PSA_WANT_KEY_TYPE_CAMELLIA) || \
+    defined(PSA_WANT_KEY_TYPE_DES))
 #error "PSA_WANT_ALG_CMAC defined, but not all prerequisites"
 #endif
 
 #if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) && \
-    !( defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) || \
-       defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) )
+    !(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) || \
+    defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY))
 #error "PSA_WANT_ALG_DETERMINISTIC_ECDSA defined, but not all prerequisites"
 #endif
 
 #if defined(PSA_WANT_ALG_ECDSA) && \
-    !( defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) || \
-       defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) )
+    !(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) || \
+    defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY))
 #error "PSA_WANT_ALG_ECDSA defined, but not all prerequisites"
 #endif
 
 #if defined(PSA_WANT_ALG_GCM) && \
-    !( defined(PSA_WANT_KEY_TYPE_AES) || \
-       defined(PSA_WANT_KEY_TYPE_CAMELLIA) )
+    !(defined(PSA_WANT_KEY_TYPE_AES) || \
+    defined(PSA_WANT_KEY_TYPE_CAMELLIA))
 #error "PSA_WANT_ALG_GCM defined, but not all prerequisites"
 #endif
 
 #if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) && \
-    !( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
-       defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) )
+    !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
+    defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY))
 #error "PSA_WANT_ALG_RSA_PKCS1V15_CRYPT defined, but not all prerequisites"
 #endif
 
 #if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) && \
-    !( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
-       defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) )
+    !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
+    defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY))
 #error "PSA_WANT_ALG_RSA_PKCS1V15_SIGN defined, but not all prerequisites"
 #endif
 
 #if defined(PSA_WANT_ALG_RSA_OAEP) && \
-    !( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
-       defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) )
+    !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
+    defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY))
 #error "PSA_WANT_ALG_RSA_OAEP defined, but not all prerequisites"
 #endif
 
 #if defined(PSA_WANT_ALG_RSA_PSS) && \
-    !( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
-       defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) )
+    !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
+    defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY))
 #error "PSA_WANT_ALG_RSA_PSS defined, but not all prerequisites"
 #endif
 
@@ -88,4 +88,14 @@
 #error "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_USE_PSA_CRYPTO) && \
+    !(defined(PSA_WANT_ALG_SHA_1) || defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_512))
+#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites"
+#endif
+
+#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) && \
+    !defined(PSA_WANT_ALG_SHA_256)
+#error "PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS defined, but not all prerequisites"
+#endif
+
 #endif /* MBEDTLS_CHECK_CRYPTO_CONFIG_H */
diff --git a/lib/libmbedtls/mbedtls/library/cipher.c b/lib/libmbedtls/mbedtls/library/cipher.c
index 31147df..2f57f95 100644
--- a/lib/libmbedtls/mbedtls/library/cipher.c
+++ b/lib/libmbedtls/mbedtls/library/cipher.c
@@ -26,7 +26,7 @@
 #if defined(MBEDTLS_CIPHER_C)
 
 #include "mbedtls/cipher.h"
-#include "mbedtls/cipher_internal.h"
+#include "cipher_wrap.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 #include "mbedtls/constant_time.h"
@@ -63,140 +63,133 @@
 #include "mbedtls/nist_kw.h"
 #endif
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#define mbedtls_calloc calloc
-#define mbedtls_free   free
-#endif
-
-#define CIPHER_VALIDATE_RET( cond )    \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA )
-#define CIPHER_VALIDATE( cond )        \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
 
 static int supported_init = 0;
 
-const int *mbedtls_cipher_list( void )
+const int *mbedtls_cipher_list(void)
 {
     const mbedtls_cipher_definition_t *def;
     int *type;
 
-    if( ! supported_init )
-    {
+    if (!supported_init) {
         def = mbedtls_cipher_definitions;
         type = mbedtls_cipher_supported;
 
-        while( def->type != 0 )
+        while (def->type != 0) {
             *type++ = (*def++).type;
+        }
 
         *type = 0;
 
         supported_init = 1;
     }
 
-    return( mbedtls_cipher_supported );
+    return mbedtls_cipher_supported;
 }
 
 const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type(
-    const mbedtls_cipher_type_t cipher_type )
+    const mbedtls_cipher_type_t cipher_type)
 {
     const mbedtls_cipher_definition_t *def;
 
-    for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
-        if( def->type == cipher_type )
-            return( def->info );
+    for (def = mbedtls_cipher_definitions; def->info != NULL; def++) {
+        if (def->type == cipher_type) {
+            return def->info;
+        }
+    }
 
-    return( NULL );
+    return NULL;
 }
 
 const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string(
-    const char *cipher_name )
+    const char *cipher_name)
 {
     const mbedtls_cipher_definition_t *def;
 
-    if( NULL == cipher_name )
-        return( NULL );
+    if (NULL == cipher_name) {
+        return NULL;
+    }
 
-    for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
-        if( !  strcmp( def->info->name, cipher_name ) )
-            return( def->info );
+    for (def = mbedtls_cipher_definitions; def->info != NULL; def++) {
+        if (!strcmp(def->info->name, cipher_name)) {
+            return def->info;
+        }
+    }
 
-    return( NULL );
+    return NULL;
 }
 
 const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values(
     const mbedtls_cipher_id_t cipher_id,
     int key_bitlen,
-    const mbedtls_cipher_mode_t mode )
+    const mbedtls_cipher_mode_t mode)
 {
     const mbedtls_cipher_definition_t *def;
 
-    for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
-        if( def->info->base->cipher == cipher_id &&
+    for (def = mbedtls_cipher_definitions; def->info != NULL; def++) {
+        if (def->info->base->cipher == cipher_id &&
             def->info->key_bitlen == (unsigned) key_bitlen &&
-            def->info->mode == mode )
-            return( def->info );
+            def->info->mode == mode) {
+            return def->info;
+        }
+    }
 
-    return( NULL );
+    return NULL;
 }
 
-void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx )
+void mbedtls_cipher_init(mbedtls_cipher_context_t *ctx)
 {
-    CIPHER_VALIDATE( ctx != NULL );
-    memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
+    memset(ctx, 0, sizeof(mbedtls_cipher_context_t));
 }
 
-void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx )
+void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ctx->psa_enabled == 1 )
-    {
-        if( ctx->cipher_ctx != NULL )
-        {
+    if (ctx->psa_enabled == 1) {
+        if (ctx->cipher_ctx != NULL) {
             mbedtls_cipher_context_psa * const cipher_psa =
                 (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
 
-            if( cipher_psa->slot_state == MBEDTLS_CIPHER_PSA_KEY_OWNED )
-            {
+            if (cipher_psa->slot_state == MBEDTLS_CIPHER_PSA_KEY_OWNED) {
                 /* xxx_free() doesn't allow to return failures. */
-                (void) psa_destroy_key( cipher_psa->slot );
+                (void) psa_destroy_key(cipher_psa->slot);
             }
 
-            mbedtls_platform_zeroize( cipher_psa, sizeof( *cipher_psa ) );
-            mbedtls_free( cipher_psa );
+            mbedtls_platform_zeroize(cipher_psa, sizeof(*cipher_psa));
+            mbedtls_free(cipher_psa);
         }
 
-        mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) );
+        mbedtls_platform_zeroize(ctx, sizeof(mbedtls_cipher_context_t));
         return;
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #if defined(MBEDTLS_CMAC_C)
-    if( ctx->cmac_ctx )
-    {
-       mbedtls_platform_zeroize( ctx->cmac_ctx,
-                                 sizeof( mbedtls_cmac_context_t ) );
-       mbedtls_free( ctx->cmac_ctx );
+    if (ctx->cmac_ctx) {
+        mbedtls_platform_zeroize(ctx->cmac_ctx,
+                                 sizeof(mbedtls_cmac_context_t));
+        mbedtls_free(ctx->cmac_ctx);
     }
 #endif
 
-    if( ctx->cipher_ctx )
-        ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
+    if (ctx->cipher_ctx) {
+        ctx->cipher_info->base->ctx_free_func(ctx->cipher_ctx);
+    }
 
-    mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_cipher_context_t));
 }
 
-int mbedtls_cipher_clone( mbedtls_cipher_context_t *dst,
-                          const mbedtls_cipher_context_t *src )
+int mbedtls_cipher_clone(mbedtls_cipher_context_t *dst,
+                         const mbedtls_cipher_context_t *src)
 {
-    if( dst == NULL || dst->cipher_info == NULL ||
-        src == NULL || src->cipher_info == NULL)
-    {
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (dst == NULL || dst->cipher_info == NULL ||
+        src == NULL || src->cipher_info == NULL) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
     dst->cipher_info = src->cipher_info;
@@ -206,31 +199,32 @@
     dst->add_padding = src->add_padding;
     dst->get_padding = src->get_padding;
 #endif
-    memcpy( dst->unprocessed_data, src->unprocessed_data, MBEDTLS_MAX_BLOCK_LENGTH );
+    memcpy(dst->unprocessed_data, src->unprocessed_data, MBEDTLS_MAX_BLOCK_LENGTH);
     dst->unprocessed_len = src->unprocessed_len;
-    memcpy( dst->iv, src->iv, MBEDTLS_MAX_IV_LENGTH );
+    memcpy(dst->iv, src->iv, MBEDTLS_MAX_IV_LENGTH);
     dst->iv_size = src->iv_size;
-    if( dst->cipher_info->base->ctx_clone_func )
-        dst->cipher_info->base->ctx_clone_func( dst->cipher_ctx, src->cipher_ctx );
+    if (dst->cipher_info->base->ctx_clone_func)
+        dst->cipher_info->base->ctx_clone_func(dst->cipher_ctx, src->cipher_ctx);
 
 #if defined(MBEDTLS_CMAC_C)
-    if( dst->cmac_ctx != NULL && src->cmac_ctx != NULL )
-        memcpy( dst->cmac_ctx, src->cmac_ctx, sizeof( mbedtls_cmac_context_t ) );
+    if (dst->cmac_ctx != NULL && src->cmac_ctx != NULL)
+        memcpy(dst->cmac_ctx, src->cmac_ctx, sizeof(mbedtls_cmac_context_t));
 #endif
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx,
-                          const mbedtls_cipher_info_t *cipher_info )
+int mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx,
+                         const mbedtls_cipher_info_t *cipher_info)
 {
-    CIPHER_VALIDATE_RET( ctx != NULL );
-    if( cipher_info == NULL )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (cipher_info == NULL) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
-    memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
+    memset(ctx, 0, sizeof(mbedtls_cipher_context_t));
 
-    if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) )
-        return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
+    if (NULL == (ctx->cipher_ctx = cipher_info->base->ctx_alloc_func())) {
+        return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
+    }
 
     ctx->cipher_info = cipher_info;
 
@@ -239,115 +233,123 @@
      * Ignore possible errors caused by a cipher mode that doesn't use padding
      */
 #if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
-    (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 );
+    (void) mbedtls_cipher_set_padding_mode(ctx, MBEDTLS_PADDING_PKCS7);
 #else
-    (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE );
+    (void) mbedtls_cipher_set_padding_mode(ctx, MBEDTLS_PADDING_NONE);
 #endif
 #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
 
-    return( 0 );
+    return 0;
 }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx,
-                              const mbedtls_cipher_info_t *cipher_info,
-                              size_t taglen )
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+int mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx,
+                             const mbedtls_cipher_info_t *cipher_info,
+                             size_t taglen)
 {
     psa_algorithm_t alg;
     mbedtls_cipher_context_psa *cipher_psa;
 
-    if( NULL == cipher_info || NULL == ctx )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (NULL == cipher_info || NULL == ctx) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
     /* Check that the underlying cipher mode and cipher type are
      * supported by the underlying PSA Crypto implementation. */
-    alg = mbedtls_psa_translate_cipher_mode( cipher_info->mode, taglen );
-    if( alg == 0 )
-        return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
-    if( mbedtls_psa_translate_cipher_type( cipher_info->type ) == 0 )
-        return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+    alg = mbedtls_psa_translate_cipher_mode(cipher_info->mode, taglen);
+    if (alg == 0) {
+        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+    }
+    if (mbedtls_psa_translate_cipher_type(cipher_info->type) == 0) {
+        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+    }
 
-    memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
+    memset(ctx, 0, sizeof(mbedtls_cipher_context_t));
 
-    cipher_psa = mbedtls_calloc( 1, sizeof(mbedtls_cipher_context_psa ) );
-    if( cipher_psa == NULL )
-        return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
+    cipher_psa = mbedtls_calloc(1, sizeof(mbedtls_cipher_context_psa));
+    if (cipher_psa == NULL) {
+        return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
+    }
     cipher_psa->alg  = alg;
     ctx->cipher_ctx  = cipher_psa;
     ctx->cipher_info = cipher_info;
     ctx->psa_enabled = 1;
-    return( 0 );
+    return 0;
 }
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-int mbedtls_cipher_setup_info( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info )
+int mbedtls_cipher_setup_info(mbedtls_cipher_context_t *ctx,
+                              const mbedtls_cipher_info_t *cipher_info )
 {
-    if( NULL == cipher_info || NULL == ctx )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (NULL == cipher_info || NULL == ctx)
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
 
     ctx->cipher_info = cipher_info;
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx,
-                           const unsigned char *key,
-                           int key_bitlen,
-                           const mbedtls_operation_t operation )
+int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx,
+                          const unsigned char *key,
+                          int key_bitlen,
+                          const mbedtls_operation_t operation)
 {
-    CIPHER_VALIDATE_RET( ctx != NULL );
-    CIPHER_VALIDATE_RET( key != NULL );
-    CIPHER_VALIDATE_RET( operation == MBEDTLS_ENCRYPT ||
-                         operation == MBEDTLS_DECRYPT );
-    if( ctx->cipher_info == NULL )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (operation != MBEDTLS_ENCRYPT && operation != MBEDTLS_DECRYPT) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
+    if (ctx->cipher_info == NULL) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ctx->psa_enabled == 1 )
-    {
+    if (ctx->psa_enabled == 1) {
         mbedtls_cipher_context_psa * const cipher_psa =
             (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
 
-        size_t const key_bytelen = ( (size_t) key_bitlen + 7 ) / 8;
+        size_t const key_bytelen = ((size_t) key_bitlen + 7) / 8;
 
         psa_status_t status;
         psa_key_type_t key_type;
         psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
         /* PSA Crypto API only accepts byte-aligned keys. */
-        if( key_bitlen % 8 != 0 )
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        if (key_bitlen % 8 != 0) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+        }
 
         /* Don't allow keys to be set multiple times. */
-        if( cipher_psa->slot_state != MBEDTLS_CIPHER_PSA_KEY_UNSET )
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        if (cipher_psa->slot_state != MBEDTLS_CIPHER_PSA_KEY_UNSET) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+        }
 
         key_type = mbedtls_psa_translate_cipher_type(
-            ctx->cipher_info->type );
-        if( key_type == 0 )
-            return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
-        psa_set_key_type( &attributes, key_type );
+            ctx->cipher_info->type);
+        if (key_type == 0) {
+            return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+        }
+        psa_set_key_type(&attributes, key_type);
 
         /* Mbed TLS' cipher layer doesn't enforce the mode of operation
          * (encrypt vs. decrypt): it is possible to setup a key for encryption
          * and use it for AEAD decryption. Until tests relying on this
          * are changed, allow any usage in PSA. */
-        psa_set_key_usage_flags( &attributes,
-                                 /* mbedtls_psa_translate_cipher_operation( operation ); */
-                                 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
-        psa_set_key_algorithm( &attributes, cipher_psa->alg );
+        psa_set_key_usage_flags(&attributes,
+                                /* mbedtls_psa_translate_cipher_operation( operation ); */
+                                PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
+        psa_set_key_algorithm(&attributes, cipher_psa->alg);
 
-        status = psa_import_key( &attributes, key, key_bytelen,
-                                 &cipher_psa->slot );
-        switch( status )
-        {
+        status = psa_import_key(&attributes, key, key_bytelen,
+                                &cipher_psa->slot);
+        switch (status) {
             case PSA_SUCCESS:
                 break;
             case PSA_ERROR_INSUFFICIENT_MEMORY:
-                return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
+                return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
             case PSA_ERROR_NOT_SUPPORTED:
-                return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+                return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
             default:
-                return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
+                return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
         }
         /* Indicate that we own the key slot and need to
          * destroy it in mbedtls_cipher_free(). */
@@ -355,14 +357,13 @@
 
         ctx->key_bitlen = key_bitlen;
         ctx->operation = operation;
-        return( 0 );
+        return 0;
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-    if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 &&
-        (int) ctx->cipher_info->key_bitlen != key_bitlen )
-    {
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if ((ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN) == 0 &&
+        (int) ctx->cipher_info->key_bitlen != key_bitlen) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
     ctx->key_bitlen = key_bitlen;
@@ -371,268 +372,291 @@
     /*
      * For OFB, CFB and CTR mode always use the encryption key schedule
      */
-    if( MBEDTLS_ENCRYPT == operation ||
+    if (MBEDTLS_ENCRYPT == operation ||
         MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
         MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
-        MBEDTLS_MODE_CTR == ctx->cipher_info->mode )
-    {
-        return( ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
-                                                         ctx->key_bitlen ) );
+        MBEDTLS_MODE_CTR == ctx->cipher_info->mode) {
+        return ctx->cipher_info->base->setkey_enc_func(ctx->cipher_ctx, key,
+                                                       ctx->key_bitlen);
     }
 
-    if( MBEDTLS_DECRYPT == operation )
-        return( ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
-                                                         ctx->key_bitlen ) );
+    if (MBEDTLS_DECRYPT == operation) {
+        return ctx->cipher_info->base->setkey_dec_func(ctx->cipher_ctx, key,
+                                                       ctx->key_bitlen);
+    }
 
-    return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
 }
 
-int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
-                           const unsigned char *iv,
-                           size_t iv_len )
+int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx,
+                          const unsigned char *iv,
+                          size_t iv_len)
 {
     size_t actual_iv_size;
 
-    CIPHER_VALIDATE_RET( ctx != NULL );
-    CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
-    if( ctx->cipher_info == NULL )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (ctx->cipher_info == NULL) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ctx->psa_enabled == 1 )
-    {
+    if (ctx->psa_enabled == 1) {
         /* While PSA Crypto has an API for multipart
          * operations, we currently don't make it
          * accessible through the cipher layer. */
-        return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
     /* avoid buffer overflow in ctx->iv */
-    if( iv_len > MBEDTLS_MAX_IV_LENGTH )
-        return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+    if (iv_len > MBEDTLS_MAX_IV_LENGTH) {
+        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+    }
 
-    if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 )
+    if ((ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN) != 0) {
         actual_iv_size = iv_len;
-    else
-    {
+    } else {
         actual_iv_size = ctx->cipher_info->iv_size;
 
         /* avoid reading past the end of input buffer */
-        if( actual_iv_size > iv_len )
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        if (actual_iv_size > iv_len) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+        }
     }
 
 #if defined(MBEDTLS_CHACHA20_C)
-    if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 )
-    {
+    if (ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20) {
         /* Even though the actual_iv_size is overwritten with a correct value
          * of 12 from the cipher info, return an error to indicate that
          * the input iv_len is wrong. */
-        if( iv_len != 12 )
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        if (iv_len != 12) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+        }
 
-        if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx,
-                                           iv,
-                                           0U ) ) /* Initial counter value */
-        {
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        if (0 != mbedtls_chacha20_starts((mbedtls_chacha20_context *) ctx->cipher_ctx,
+                                         iv,
+                                         0U)) {   /* Initial counter value */
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
         }
     }
 #if defined(MBEDTLS_CHACHAPOLY_C)
-    if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 &&
-         iv_len != 12 )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 &&
+        iv_len != 12) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 #endif
 #endif
 
-    if ( actual_iv_size != 0 )
-    {
-        memcpy( ctx->iv, iv, actual_iv_size );
+#if defined(MBEDTLS_GCM_C)
+    if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) {
+        return mbedtls_gcm_starts((mbedtls_gcm_context *) ctx->cipher_ctx,
+                                  ctx->operation,
+                                  iv, iv_len);
+    }
+#endif
+
+#if defined(MBEDTLS_CCM_C)
+    if (MBEDTLS_MODE_CCM_STAR_NO_TAG == ctx->cipher_info->mode) {
+        int set_lengths_result;
+        int ccm_star_mode;
+
+        set_lengths_result = mbedtls_ccm_set_lengths(
+            (mbedtls_ccm_context *) ctx->cipher_ctx,
+            0, 0, 0);
+        if (set_lengths_result != 0) {
+            return set_lengths_result;
+        }
+
+        if (ctx->operation == MBEDTLS_DECRYPT) {
+            ccm_star_mode = MBEDTLS_CCM_STAR_DECRYPT;
+        } else if (ctx->operation == MBEDTLS_ENCRYPT) {
+            ccm_star_mode = MBEDTLS_CCM_STAR_ENCRYPT;
+        } else {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+        }
+
+        return mbedtls_ccm_starts((mbedtls_ccm_context *) ctx->cipher_ctx,
+                                  ccm_star_mode,
+                                  iv, iv_len);
+    }
+#endif
+
+    if (actual_iv_size != 0) {
+        memcpy(ctx->iv, iv, actual_iv_size);
         ctx->iv_size = actual_iv_size;
     }
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx )
+int mbedtls_cipher_reset(mbedtls_cipher_context_t *ctx)
 {
-    CIPHER_VALIDATE_RET( ctx != NULL );
-    if( ctx->cipher_info == NULL )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (ctx->cipher_info == NULL) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ctx->psa_enabled == 1 )
-    {
+    if (ctx->psa_enabled == 1) {
         /* We don't support resetting PSA-based
          * cipher contexts, yet. */
-        return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
     ctx->unprocessed_len = 0;
 
-    return( 0 );
+    return 0;
 }
 
 #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
-int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
-                      const unsigned char *ad, size_t ad_len )
+int mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx,
+                             const unsigned char *ad, size_t ad_len)
 {
-    CIPHER_VALIDATE_RET( ctx != NULL );
-    CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
-    if( ctx->cipher_info == NULL )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (ctx->cipher_info == NULL) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ctx->psa_enabled == 1 )
-    {
+    if (ctx->psa_enabled == 1) {
         /* While PSA Crypto has an API for multipart
          * operations, we currently don't make it
          * accessible through the cipher layer. */
-        return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #if defined(MBEDTLS_GCM_C)
-    if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
-    {
-        return( mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation,
-                                    ctx->iv, ctx->iv_size, ad, ad_len ) );
+    if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) {
+        return mbedtls_gcm_update_ad((mbedtls_gcm_context *) ctx->cipher_ctx,
+                                     ad, ad_len);
     }
 #endif
 
 #if defined(MBEDTLS_CHACHAPOLY_C)
-    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
-    {
+    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) {
         int result;
         mbedtls_chachapoly_mode_t mode;
 
-        mode = ( ctx->operation == MBEDTLS_ENCRYPT )
+        mode = (ctx->operation == MBEDTLS_ENCRYPT)
                 ? MBEDTLS_CHACHAPOLY_ENCRYPT
                 : MBEDTLS_CHACHAPOLY_DECRYPT;
 
-        result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
-                                                        ctx->iv,
-                                                        mode );
-        if ( result != 0 )
-            return( result );
+        result = mbedtls_chachapoly_starts((mbedtls_chachapoly_context *) ctx->cipher_ctx,
+                                           ctx->iv,
+                                           mode);
+        if (result != 0) {
+            return result;
+        }
 
-        return( mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
-                                               ad, ad_len ) );
+        return mbedtls_chachapoly_update_aad((mbedtls_chachapoly_context *) ctx->cipher_ctx,
+                                             ad, ad_len);
     }
 #endif
 
-    return( 0 );
+    return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
 }
 #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
 
-int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
-                   size_t ilen, unsigned char *output, size_t *olen )
+int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *input,
+                          size_t ilen, unsigned char *output, size_t *olen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t block_size;
 
-    CIPHER_VALIDATE_RET( ctx != NULL );
-    CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
-    CIPHER_VALIDATE_RET( output != NULL );
-    CIPHER_VALIDATE_RET( olen != NULL );
-    if( ctx->cipher_info == NULL )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (ctx->cipher_info == NULL) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ctx->psa_enabled == 1 )
-    {
+    if (ctx->psa_enabled == 1) {
         /* While PSA Crypto has an API for multipart
          * operations, we currently don't make it
          * accessible through the cipher layer. */
-        return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
     *olen = 0;
-    block_size = mbedtls_cipher_get_block_size( ctx );
-    if ( 0 == block_size )
-    {
-        return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT );
+    block_size = mbedtls_cipher_get_block_size(ctx);
+    if (0 == block_size) {
+        return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
     }
 
-    if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB )
-    {
-        if( ilen != block_size )
-            return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
+    if (ctx->cipher_info->mode == MBEDTLS_MODE_ECB) {
+        if (ilen != block_size) {
+            return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED;
+        }
 
         *olen = ilen;
 
-        if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx,
-                    ctx->operation, input, output ) ) )
-        {
-            return( ret );
+        if (0 != (ret = ctx->cipher_info->base->ecb_func(ctx->cipher_ctx,
+                                                         ctx->operation, input, output))) {
+            return ret;
         }
 
-        return( 0 );
+        return 0;
     }
 
 #if defined(MBEDTLS_GCM_C)
-    if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM )
-    {
-        *olen = ilen;
-        return( mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input,
-                                    output ) );
+    if (ctx->cipher_info->mode == MBEDTLS_MODE_GCM) {
+        return mbedtls_gcm_update((mbedtls_gcm_context *) ctx->cipher_ctx,
+                                  input, ilen,
+                                  output, ilen, olen);
+    }
+#endif
+
+#if defined(MBEDTLS_CCM_C)
+    if (ctx->cipher_info->mode == MBEDTLS_MODE_CCM_STAR_NO_TAG) {
+        return mbedtls_ccm_update((mbedtls_ccm_context *) ctx->cipher_ctx,
+                                  input, ilen,
+                                  output, ilen, olen);
     }
 #endif
 
 #if defined(MBEDTLS_CHACHAPOLY_C)
-    if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 )
-    {
+    if (ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305) {
         *olen = ilen;
-        return( mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
-                                           ilen, input, output ) );
+        return mbedtls_chachapoly_update((mbedtls_chachapoly_context *) ctx->cipher_ctx,
+                                         ilen, input, output);
     }
 #endif
 
-    if( input == output &&
-       ( ctx->unprocessed_len != 0 || ilen % block_size ) )
-    {
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (input == output &&
+        (ctx->unprocessed_len != 0 || ilen % block_size)) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-    if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC )
-    {
+    if (ctx->cipher_info->mode == MBEDTLS_MODE_CBC) {
         size_t copy_len = 0;
 
         /*
          * If there is not enough data for a full block, cache it.
          */
-        if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding &&
-                ilen <= block_size - ctx->unprocessed_len ) ||
-            ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding &&
-                ilen < block_size - ctx->unprocessed_len ) ||
-             ( ctx->operation == MBEDTLS_ENCRYPT &&
-                ilen < block_size - ctx->unprocessed_len ) )
-        {
-            memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
-                    ilen );
+        if ((ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding &&
+             ilen <= block_size - ctx->unprocessed_len) ||
+            (ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding &&
+             ilen < block_size - ctx->unprocessed_len) ||
+            (ctx->operation == MBEDTLS_ENCRYPT &&
+             ilen < block_size - ctx->unprocessed_len)) {
+            memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input,
+                   ilen);
 
             ctx->unprocessed_len += ilen;
-            return( 0 );
+            return 0;
         }
 
         /*
          * Process cached data first
          */
-        if( 0 != ctx->unprocessed_len )
-        {
+        if (0 != ctx->unprocessed_len) {
             copy_len = block_size - ctx->unprocessed_len;
 
-            memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
-                    copy_len );
+            memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input,
+                   copy_len);
 
-            if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
-                    ctx->operation, block_size, ctx->iv,
-                    ctx->unprocessed_data, output ) ) )
-            {
-                return( ret );
+            if (0 != (ret = ctx->cipher_info->base->cbc_func(ctx->cipher_ctx,
+                                                             ctx->operation, block_size, ctx->iv,
+                                                             ctx->unprocessed_data, output))) {
+                return ret;
             }
 
             *olen += block_size;
@@ -646,22 +670,20 @@
         /*
          * Cache final, incomplete block
          */
-        if( 0 != ilen )
-        {
+        if (0 != ilen) {
             /* Encryption: only cache partial blocks
              * Decryption w/ padding: always keep at least one whole block
              * Decryption w/o padding: only cache partial blocks
              */
             copy_len = ilen % block_size;
-            if( copy_len == 0 &&
+            if (copy_len == 0 &&
                 ctx->operation == MBEDTLS_DECRYPT &&
-                NULL != ctx->add_padding)
-            {
+                NULL != ctx->add_padding) {
                 copy_len = block_size;
             }
 
-            memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),
-                    copy_len );
+            memcpy(ctx->unprocessed_data, &(input[ilen - copy_len]),
+                   copy_len);
 
             ctx->unprocessed_len += copy_len;
             ilen -= copy_len;
@@ -670,105 +692,96 @@
         /*
          * Process remaining full blocks
          */
-        if( ilen )
-        {
-            if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
-                    ctx->operation, ilen, ctx->iv, input, output ) ) )
-            {
-                return( ret );
+        if (ilen) {
+            if (0 != (ret = ctx->cipher_info->base->cbc_func(ctx->cipher_ctx,
+                                                             ctx->operation, ilen, ctx->iv, input,
+                                                             output))) {
+                return ret;
             }
 
             *olen += ilen;
         }
 
-        return( 0 );
+        return 0;
     }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
-    if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB )
-    {
-        if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx,
-                ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv,
-                input, output ) ) )
-        {
-            return( ret );
+    if (ctx->cipher_info->mode == MBEDTLS_MODE_CFB) {
+        if (0 != (ret = ctx->cipher_info->base->cfb_func(ctx->cipher_ctx,
+                                                         ctx->operation, ilen,
+                                                         &ctx->unprocessed_len, ctx->iv,
+                                                         input, output))) {
+            return ret;
         }
 
         *olen = ilen;
 
-        return( 0 );
+        return 0;
     }
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_OFB)
-    if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB )
-    {
-        if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx,
-                ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) )
-        {
-            return( ret );
+    if (ctx->cipher_info->mode == MBEDTLS_MODE_OFB) {
+        if (0 != (ret = ctx->cipher_info->base->ofb_func(ctx->cipher_ctx,
+                                                         ilen, &ctx->unprocessed_len, ctx->iv,
+                                                         input, output))) {
+            return ret;
         }
 
         *olen = ilen;
 
-        return( 0 );
+        return 0;
     }
 #endif /* MBEDTLS_CIPHER_MODE_OFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
-    if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR )
-    {
-        if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx,
-                ilen, &ctx->unprocessed_len, ctx->iv,
-                ctx->unprocessed_data, input, output ) ) )
-        {
-            return( ret );
+    if (ctx->cipher_info->mode == MBEDTLS_MODE_CTR) {
+        if (0 != (ret = ctx->cipher_info->base->ctr_func(ctx->cipher_ctx,
+                                                         ilen, &ctx->unprocessed_len, ctx->iv,
+                                                         ctx->unprocessed_data, input, output))) {
+            return ret;
         }
 
         *olen = ilen;
 
-        return( 0 );
+        return 0;
     }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
 #if defined(MBEDTLS_CIPHER_MODE_XTS)
-    if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS )
-    {
-        if( ctx->unprocessed_len > 0 ) {
+    if (ctx->cipher_info->mode == MBEDTLS_MODE_XTS) {
+        if (ctx->unprocessed_len > 0) {
             /* We can only process an entire data unit at a time. */
-            return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+            return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
         }
 
-        ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx,
-                ctx->operation, ilen, ctx->iv, input, output );
-        if( ret != 0 )
-        {
-            return( ret );
+        ret = ctx->cipher_info->base->xts_func(ctx->cipher_ctx,
+                                               ctx->operation, ilen, ctx->iv, input, output);
+        if (ret != 0) {
+            return ret;
         }
 
         *olen = ilen;
 
-        return( 0 );
+        return 0;
     }
 #endif /* MBEDTLS_CIPHER_MODE_XTS */
 
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
-    if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM )
-    {
-        if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx,
-                                                    ilen, input, output ) ) )
-        {
-            return( ret );
+    if (ctx->cipher_info->mode == MBEDTLS_MODE_STREAM) {
+        if (0 != (ret = ctx->cipher_info->base->stream_func(ctx->cipher_ctx,
+                                                            ilen, input, output))) {
+            return ret;
         }
 
         *olen = ilen;
 
-        return( 0 );
+        return 0;
     }
 #endif /* MBEDTLS_CIPHER_MODE_STREAM */
 
-    return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
 }
 
 #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
@@ -776,24 +789,26 @@
 /*
  * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len
  */
-static void add_pkcs_padding( unsigned char *output, size_t output_len,
-        size_t data_len )
+static void add_pkcs_padding(unsigned char *output, size_t output_len,
+                             size_t data_len)
 {
     size_t padding_len = output_len - data_len;
     unsigned char i;
 
-    for( i = 0; i < padding_len; i++ )
+    for (i = 0; i < padding_len; i++) {
         output[data_len + i] = (unsigned char) padding_len;
+    }
 }
 
-static int get_pkcs_padding( unsigned char *input, size_t input_len,
-        size_t *data_len )
+static int get_pkcs_padding(unsigned char *input, size_t input_len,
+                            size_t *data_len)
 {
     size_t i, pad_idx;
     unsigned char padding_len, bad = 0;
 
-    if( NULL == input || NULL == data_len )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (NULL == input || NULL == data_len) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
     padding_len = input[input_len - 1];
     *data_len = input_len - padding_len;
@@ -805,10 +820,11 @@
     /* The number of bytes checked must be independent of padding_len,
      * so pick input_len, which is usually 8 or 16 (one block) */
     pad_idx = input_len - padding_len;
-    for( i = 0; i < input_len; i++ )
-        bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx );
+    for (i = 0; i < input_len; i++) {
+        bad |= (input[i] ^ padding_len) * (i >= pad_idx);
+    }
 
-    return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
+    return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0);
 }
 #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */
 
@@ -816,37 +832,38 @@
 /*
  * One and zeros padding: fill with 80 00 ... 00
  */
-static void add_one_and_zeros_padding( unsigned char *output,
-                                       size_t output_len, size_t data_len )
+static void add_one_and_zeros_padding(unsigned char *output,
+                                      size_t output_len, size_t data_len)
 {
     size_t padding_len = output_len - data_len;
     unsigned char i = 0;
 
     output[data_len] = 0x80;
-    for( i = 1; i < padding_len; i++ )
+    for (i = 1; i < padding_len; i++) {
         output[data_len + i] = 0x00;
+    }
 }
 
-static int get_one_and_zeros_padding( unsigned char *input, size_t input_len,
-                                      size_t *data_len )
+static int get_one_and_zeros_padding(unsigned char *input, size_t input_len,
+                                     size_t *data_len)
 {
     size_t i;
     unsigned char done = 0, prev_done, bad;
 
-    if( NULL == input || NULL == data_len )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (NULL == input || NULL == data_len) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
     bad = 0x80;
     *data_len = 0;
-    for( i = input_len; i > 0; i-- )
-    {
+    for (i = input_len; i > 0; i--) {
         prev_done = done;
-        done |= ( input[i - 1] != 0 );
-        *data_len |= ( i - 1 ) * ( done != prev_done );
-        bad ^= input[i - 1] * ( done != prev_done );
+        done |= (input[i - 1] != 0);
+        *data_len |= (i - 1) * (done != prev_done);
+        bad ^= input[i - 1] * (done != prev_done);
     }
 
-    return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
+    return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0);
 
 }
 #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */
@@ -855,25 +872,27 @@
 /*
  * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length
  */
-static void add_zeros_and_len_padding( unsigned char *output,
-                                       size_t output_len, size_t data_len )
+static void add_zeros_and_len_padding(unsigned char *output,
+                                      size_t output_len, size_t data_len)
 {
     size_t padding_len = output_len - data_len;
     unsigned char i = 0;
 
-    for( i = 1; i < padding_len; i++ )
+    for (i = 1; i < padding_len; i++) {
         output[data_len + i - 1] = 0x00;
+    }
     output[output_len - 1] = (unsigned char) padding_len;
 }
 
-static int get_zeros_and_len_padding( unsigned char *input, size_t input_len,
-                                      size_t *data_len )
+static int get_zeros_and_len_padding(unsigned char *input, size_t input_len,
+                                     size_t *data_len)
 {
     size_t i, pad_idx;
     unsigned char padding_len, bad = 0;
 
-    if( NULL == input || NULL == data_len )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (NULL == input || NULL == data_len) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
     padding_len = input[input_len - 1];
     *data_len = input_len - padding_len;
@@ -884,10 +903,11 @@
 
     /* The number of bytes checked must be independent of padding_len */
     pad_idx = input_len - padding_len;
-    for( i = 0; i < input_len - 1; i++ )
-        bad |= input[i] * ( i >= pad_idx );
+    for (i = 0; i < input_len - 1; i++) {
+        bad |= input[i] * (i >= pad_idx);
+    }
 
-    return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
+    return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0);
 }
 #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */
 
@@ -895,33 +915,34 @@
 /*
  * Zero padding: fill with 00 ... 00
  */
-static void add_zeros_padding( unsigned char *output,
-                               size_t output_len, size_t data_len )
+static void add_zeros_padding(unsigned char *output,
+                              size_t output_len, size_t data_len)
 {
     size_t i;
 
-    for( i = data_len; i < output_len; i++ )
+    for (i = data_len; i < output_len; i++) {
         output[i] = 0x00;
+    }
 }
 
-static int get_zeros_padding( unsigned char *input, size_t input_len,
-                              size_t *data_len )
+static int get_zeros_padding(unsigned char *input, size_t input_len,
+                             size_t *data_len)
 {
     size_t i;
     unsigned char done = 0, prev_done;
 
-    if( NULL == input || NULL == data_len )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
-
-    *data_len = 0;
-    for( i = input_len; i > 0; i-- )
-    {
-        prev_done = done;
-        done |= ( input[i-1] != 0 );
-        *data_len |= i * ( done != prev_done );
+    if (NULL == input || NULL == data_len) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
-    return( 0 );
+    *data_len = 0;
+    for (i = input_len; i > 0; i--) {
+        prev_done = done;
+        done |= (input[i-1] != 0);
+        *data_len |= i * (done != prev_done);
+    }
+
+    return 0;
 }
 #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */
 
@@ -931,272 +952,265 @@
  * There is no add_padding function (check for NULL in mbedtls_cipher_finish)
  * but a trivial get_padding function
  */
-static int get_no_padding( unsigned char *input, size_t input_len,
-                              size_t *data_len )
+static int get_no_padding(unsigned char *input, size_t input_len,
+                          size_t *data_len)
 {
-    if( NULL == input || NULL == data_len )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (NULL == input || NULL == data_len) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
     *data_len = input_len;
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
 
-int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
-                   unsigned char *output, size_t *olen )
+int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx,
+                          unsigned char *output, size_t *olen)
 {
-    CIPHER_VALIDATE_RET( ctx != NULL );
-    CIPHER_VALIDATE_RET( output != NULL );
-    CIPHER_VALIDATE_RET( olen != NULL );
-    if( ctx->cipher_info == NULL )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (ctx->cipher_info == NULL) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ctx->psa_enabled == 1 )
-    {
+    if (ctx->psa_enabled == 1) {
         /* While PSA Crypto has an API for multipart
          * operations, we currently don't make it
          * accessible through the cipher layer. */
-        return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
     *olen = 0;
 
-    if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
+    if (MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
         MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
         MBEDTLS_MODE_CTR == ctx->cipher_info->mode ||
         MBEDTLS_MODE_GCM == ctx->cipher_info->mode ||
+        MBEDTLS_MODE_CCM_STAR_NO_TAG == ctx->cipher_info->mode ||
         MBEDTLS_MODE_XTS == ctx->cipher_info->mode ||
-        MBEDTLS_MODE_STREAM == ctx->cipher_info->mode )
-    {
-        return( 0 );
+        MBEDTLS_MODE_STREAM == ctx->cipher_info->mode) {
+        return 0;
     }
 
-    if ( ( MBEDTLS_CIPHER_CHACHA20          == ctx->cipher_info->type ) ||
-         ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) )
-    {
-        return( 0 );
+    if ((MBEDTLS_CIPHER_CHACHA20          == ctx->cipher_info->type) ||
+        (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type)) {
+        return 0;
     }
 
-    if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode )
-    {
-        if( ctx->unprocessed_len != 0 )
-            return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
+    if (MBEDTLS_MODE_ECB == ctx->cipher_info->mode) {
+        if (ctx->unprocessed_len != 0) {
+            return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED;
+        }
 
-        return( 0 );
+        return 0;
     }
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-    if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode )
-    {
+    if (MBEDTLS_MODE_CBC == ctx->cipher_info->mode) {
         int ret = 0;
 
-        if( MBEDTLS_ENCRYPT == ctx->operation )
-        {
+        if (MBEDTLS_ENCRYPT == ctx->operation) {
             /* check for 'no padding' mode */
-            if( NULL == ctx->add_padding )
-            {
-                if( 0 != ctx->unprocessed_len )
-                    return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
+            if (NULL == ctx->add_padding) {
+                if (0 != ctx->unprocessed_len) {
+                    return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED;
+                }
 
-                return( 0 );
+                return 0;
             }
 
-            ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ),
-                    ctx->unprocessed_len );
-        }
-        else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len )
-        {
+            ctx->add_padding(ctx->unprocessed_data, mbedtls_cipher_get_iv_size(ctx),
+                             ctx->unprocessed_len);
+        } else if (mbedtls_cipher_get_block_size(ctx) != ctx->unprocessed_len) {
             /*
              * For decrypt operations, expect a full block,
              * or an empty block if no padding
              */
-            if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len )
-                return( 0 );
+            if (NULL == ctx->add_padding && 0 == ctx->unprocessed_len) {
+                return 0;
+            }
 
-            return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
+            return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED;
         }
 
         /* cipher block */
-        if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
-                ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv,
-                ctx->unprocessed_data, output ) ) )
-        {
-            return( ret );
+        if (0 != (ret = ctx->cipher_info->base->cbc_func(ctx->cipher_ctx,
+                                                         ctx->operation,
+                                                         mbedtls_cipher_get_block_size(ctx),
+                                                         ctx->iv,
+                                                         ctx->unprocessed_data, output))) {
+            return ret;
         }
 
         /* Set output size for decryption */
-        if( MBEDTLS_DECRYPT == ctx->operation )
-            return( ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ),
-                                      olen ) );
+        if (MBEDTLS_DECRYPT == ctx->operation) {
+            return ctx->get_padding(output, mbedtls_cipher_get_block_size(ctx),
+                                    olen);
+        }
 
         /* Set output size for encryption */
-        *olen = mbedtls_cipher_get_block_size( ctx );
-        return( 0 );
+        *olen = mbedtls_cipher_get_block_size(ctx);
+        return 0;
     }
 #else
     ((void) output);
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
-    return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
 }
 
 #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
-int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx,
-                                     mbedtls_cipher_padding_t mode )
+int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx,
+                                    mbedtls_cipher_padding_t mode)
 {
-    CIPHER_VALIDATE_RET( ctx != NULL );
-
-    if( NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode )
-    {
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ctx->psa_enabled == 1 )
-    {
+    if (ctx->psa_enabled == 1) {
         /* While PSA Crypto knows about CBC padding
          * schemes, we currently don't make them
          * accessible through the cipher layer. */
-        if( mode != MBEDTLS_PADDING_NONE )
-            return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+        if (mode != MBEDTLS_PADDING_NONE) {
+            return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+        }
 
-        return( 0 );
+        return 0;
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-    switch( mode )
-    {
+    switch (mode) {
 #if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
-    case MBEDTLS_PADDING_PKCS7:
-        ctx->add_padding = add_pkcs_padding;
-        ctx->get_padding = get_pkcs_padding;
-        break;
+        case MBEDTLS_PADDING_PKCS7:
+            ctx->add_padding = add_pkcs_padding;
+            ctx->get_padding = get_pkcs_padding;
+            break;
 #endif
 #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)
-    case MBEDTLS_PADDING_ONE_AND_ZEROS:
-        ctx->add_padding = add_one_and_zeros_padding;
-        ctx->get_padding = get_one_and_zeros_padding;
-        break;
+        case MBEDTLS_PADDING_ONE_AND_ZEROS:
+            ctx->add_padding = add_one_and_zeros_padding;
+            ctx->get_padding = get_one_and_zeros_padding;
+            break;
 #endif
 #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)
-    case MBEDTLS_PADDING_ZEROS_AND_LEN:
-        ctx->add_padding = add_zeros_and_len_padding;
-        ctx->get_padding = get_zeros_and_len_padding;
-        break;
+        case MBEDTLS_PADDING_ZEROS_AND_LEN:
+            ctx->add_padding = add_zeros_and_len_padding;
+            ctx->get_padding = get_zeros_and_len_padding;
+            break;
 #endif
 #if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
-    case MBEDTLS_PADDING_ZEROS:
-        ctx->add_padding = add_zeros_padding;
-        ctx->get_padding = get_zeros_padding;
-        break;
+        case MBEDTLS_PADDING_ZEROS:
+            ctx->add_padding = add_zeros_padding;
+            ctx->get_padding = get_zeros_padding;
+            break;
 #endif
-    case MBEDTLS_PADDING_NONE:
-        ctx->add_padding = NULL;
-        ctx->get_padding = get_no_padding;
-        break;
+        case MBEDTLS_PADDING_NONE:
+            ctx->add_padding = NULL;
+            ctx->get_padding = get_no_padding;
+            break;
 
-    default:
-        return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+        default:
+            return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
 
 #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
-int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
-                      unsigned char *tag, size_t tag_len )
+int mbedtls_cipher_write_tag(mbedtls_cipher_context_t *ctx,
+                             unsigned char *tag, size_t tag_len)
 {
-    CIPHER_VALIDATE_RET( ctx != NULL );
-    CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
-    if( ctx->cipher_info == NULL )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (ctx->cipher_info == NULL) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
-    if( MBEDTLS_ENCRYPT != ctx->operation )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (MBEDTLS_ENCRYPT != ctx->operation) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ctx->psa_enabled == 1 )
-    {
+    if (ctx->psa_enabled == 1) {
         /* While PSA Crypto has an API for multipart
          * operations, we currently don't make it
          * accessible through the cipher layer. */
-        return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #if defined(MBEDTLS_GCM_C)
-    if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
-        return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx,
-                                    tag, tag_len ) );
-#endif
-
-#if defined(MBEDTLS_CHACHAPOLY_C)
-    if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
-    {
-        /* Don't allow truncated MAC for Poly1305 */
-        if ( tag_len != 16U )
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
-
-        return( mbedtls_chachapoly_finish(
-                    (mbedtls_chachapoly_context*) ctx->cipher_ctx, tag ) );
+    if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) {
+        size_t output_length;
+        /* The code here doesn't yet support alternative implementations
+         * that can delay up to a block of output. */
+        return mbedtls_gcm_finish((mbedtls_gcm_context *) ctx->cipher_ctx,
+                                  NULL, 0, &output_length,
+                                  tag, tag_len);
     }
 #endif
 
-    return( 0 );
+#if defined(MBEDTLS_CHACHAPOLY_C)
+    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) {
+        /* Don't allow truncated MAC for Poly1305 */
+        if (tag_len != 16U) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+        }
+
+        return mbedtls_chachapoly_finish(
+            (mbedtls_chachapoly_context *) ctx->cipher_ctx, tag);
+    }
+#endif
+
+    return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
 }
 
-int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
-                      const unsigned char *tag, size_t tag_len )
+int mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx,
+                             const unsigned char *tag, size_t tag_len)
 {
     unsigned char check_tag[16];
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    CIPHER_VALIDATE_RET( ctx != NULL );
-    CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
-    if( ctx->cipher_info == NULL )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (ctx->cipher_info == NULL) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
-    if( MBEDTLS_DECRYPT != ctx->operation )
-    {
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (MBEDTLS_DECRYPT != ctx->operation) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ctx->psa_enabled == 1 )
-    {
+    if (ctx->psa_enabled == 1) {
         /* While PSA Crypto has an API for multipart
          * operations, we currently don't make it
          * accessible through the cipher layer. */
-        return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-    /* Status to return on a non-authenticated algorithm. It would make sense
-     * to return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT or perhaps
-     * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, but at the time I write this our
-     * unit tests assume 0. */
-    ret = 0;
+    /* Status to return on a non-authenticated algorithm. */
+    ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
 
 #if defined(MBEDTLS_GCM_C)
-    if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
-    {
-        if( tag_len > sizeof( check_tag ) )
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) {
+        size_t output_length;
+        /* The code here doesn't yet support alternative implementations
+         * that can delay up to a block of output. */
 
-        if( 0 != ( ret = mbedtls_gcm_finish(
-                       (mbedtls_gcm_context *) ctx->cipher_ctx,
-                       check_tag, tag_len ) ) )
-        {
-            return( ret );
+        if (tag_len > sizeof(check_tag)) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+        }
+
+        if (0 != (ret = mbedtls_gcm_finish(
+                      (mbedtls_gcm_context *) ctx->cipher_ctx,
+                      NULL, 0, &output_length,
+                      check_tag, tag_len))) {
+            return ret;
         }
 
         /* Check the tag in "constant-time" */
-        if( mbedtls_ct_memcmp( tag, check_tag, tag_len ) != 0 )
-        {
+        if (mbedtls_ct_memcmp(tag, check_tag, tag_len) != 0) {
             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
             goto exit;
         }
@@ -1204,22 +1218,20 @@
 #endif /* MBEDTLS_GCM_C */
 
 #if defined(MBEDTLS_CHACHAPOLY_C)
-    if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
-    {
+    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) {
         /* Don't allow truncated MAC for Poly1305 */
-        if ( tag_len != sizeof( check_tag ) )
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        if (tag_len != sizeof(check_tag)) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+        }
 
         ret = mbedtls_chachapoly_finish(
-            (mbedtls_chachapoly_context*) ctx->cipher_ctx, check_tag );
-        if ( ret != 0 )
-        {
-            return( ret );
+            (mbedtls_chachapoly_context *) ctx->cipher_ctx, check_tag);
+        if (ret != 0) {
+            return ret;
         }
 
         /* Check the tag in "constant-time" */
-        if( mbedtls_ct_memcmp( tag, check_tag, tag_len ) != 0 )
-        {
+        if (mbedtls_ct_memcmp(tag, check_tag, tag_len) != 0) {
             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
             goto exit;
         }
@@ -1227,31 +1239,24 @@
 #endif /* MBEDTLS_CHACHAPOLY_C */
 
 exit:
-    mbedtls_platform_zeroize( check_tag, tag_len );
-    return( ret );
+    mbedtls_platform_zeroize(check_tag, tag_len);
+    return ret;
 }
 #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
 
 /*
  * Packet-oriented wrapper for non-AEAD modes
  */
-int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx,
-                  const unsigned char *iv, size_t iv_len,
-                  const unsigned char *input, size_t ilen,
-                  unsigned char *output, size_t *olen )
+int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *input, size_t ilen,
+                         unsigned char *output, size_t *olen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t finish_olen;
 
-    CIPHER_VALIDATE_RET( ctx != NULL );
-    CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
-    CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
-    CIPHER_VALIDATE_RET( output != NULL );
-    CIPHER_VALIDATE_RET( olen != NULL );
-
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ctx->psa_enabled == 1 )
-    {
+    if (ctx->psa_enabled == 1) {
         /* As in the non-PSA case, we don't check that
          * a key has been set. If not, the key slot will
          * still be in its default state of 0, which is
@@ -1264,86 +1269,89 @@
         psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT;
         size_t part_len;
 
-        if( ctx->operation == MBEDTLS_DECRYPT )
-        {
-            status = psa_cipher_decrypt_setup( &cipher_op,
-                                               cipher_psa->slot,
-                                               cipher_psa->alg );
+        if (ctx->operation == MBEDTLS_DECRYPT) {
+            status = psa_cipher_decrypt_setup(&cipher_op,
+                                              cipher_psa->slot,
+                                              cipher_psa->alg);
+        } else if (ctx->operation == MBEDTLS_ENCRYPT) {
+            status = psa_cipher_encrypt_setup(&cipher_op,
+                                              cipher_psa->slot,
+                                              cipher_psa->alg);
+        } else {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
         }
-        else if( ctx->operation == MBEDTLS_ENCRYPT )
-        {
-            status = psa_cipher_encrypt_setup( &cipher_op,
-                                               cipher_psa->slot,
-                                               cipher_psa->alg );
-        }
-        else
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
 
         /* In the following, we can immediately return on an error,
          * because the PSA Crypto API guarantees that cipher operations
          * are terminated by unsuccessful calls to psa_cipher_update(),
          * and by any call to psa_cipher_finish(). */
-        if( status != PSA_SUCCESS )
-            return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
-
-        if( ctx->cipher_info->mode != MBEDTLS_MODE_ECB )
-        {
-            status = psa_cipher_set_iv( &cipher_op, iv, iv_len );
-            if( status != PSA_SUCCESS )
-                return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
+        if (status != PSA_SUCCESS) {
+            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
         }
 
-        status = psa_cipher_update( &cipher_op,
-                                    input, ilen,
-                                    output, ilen, olen );
-        if( status != PSA_SUCCESS )
-            return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
+        if (ctx->cipher_info->mode != MBEDTLS_MODE_ECB) {
+            status = psa_cipher_set_iv(&cipher_op, iv, iv_len);
+            if (status != PSA_SUCCESS) {
+                return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+            }
+        }
 
-        status = psa_cipher_finish( &cipher_op,
-                                    output + *olen, ilen - *olen,
-                                    &part_len );
-        if( status != PSA_SUCCESS )
-            return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
+        status = psa_cipher_update(&cipher_op,
+                                   input, ilen,
+                                   output, ilen, olen);
+        if (status != PSA_SUCCESS) {
+            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+        }
+
+        status = psa_cipher_finish(&cipher_op,
+                                   output + *olen, ilen - *olen,
+                                   &part_len);
+        if (status != PSA_SUCCESS) {
+            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+        }
 
         *olen += part_len;
-        return( 0 );
+        return 0;
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-    if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_cipher_set_iv(ctx, iv, iv_len)) != 0) {
+        return ret;
+    }
 
-    if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_cipher_reset(ctx)) != 0) {
+        return ret;
+    }
 
-    if( ( ret = mbedtls_cipher_update( ctx, input, ilen,
-                                       output, olen ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_cipher_update(ctx, input, ilen,
+                                     output, olen)) != 0) {
+        return ret;
+    }
 
-    if( ( ret = mbedtls_cipher_finish( ctx, output + *olen,
-                                       &finish_olen ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_cipher_finish(ctx, output + *olen,
+                                     &finish_olen)) != 0) {
+        return ret;
+    }
 
     *olen += finish_olen;
 
-    return( 0 );
+    return 0;
 }
 
 #if defined(MBEDTLS_CIPHER_MODE_AEAD)
 /*
- * Packet-oriented encryption for AEAD modes: internal function shared by
- * mbedtls_cipher_auth_encrypt() and mbedtls_cipher_auth_encrypt_ext().
+ * Packet-oriented encryption for AEAD modes: internal function used by
+ * mbedtls_cipher_auth_encrypt_ext().
  */
-static int mbedtls_cipher_aead_encrypt( mbedtls_cipher_context_t *ctx,
-                         const unsigned char *iv, size_t iv_len,
-                         const unsigned char *ad, size_t ad_len,
-                         const unsigned char *input, size_t ilen,
-                         unsigned char *output, size_t *olen,
-                         unsigned char *tag, size_t tag_len )
+static int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t *ctx,
+                                       const unsigned char *iv, size_t iv_len,
+                                       const unsigned char *ad, size_t ad_len,
+                                       const unsigned char *input, size_t ilen,
+                                       unsigned char *output, size_t *olen,
+                                       unsigned char *tag, size_t tag_len)
 {
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ctx->psa_enabled == 1 )
-    {
+    if (ctx->psa_enabled == 1) {
         /* As in the non-PSA case, we don't check that
          * a key has been set. If not, the key slot will
          * still be in its default state of 0, which is
@@ -1356,74 +1364,71 @@
 
         /* PSA Crypto API always writes the authentication tag
          * at the end of the encrypted message. */
-        if( output == NULL || tag != output + ilen )
-            return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+        if (output == NULL || tag != output + ilen) {
+            return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+        }
 
-        status = psa_aead_encrypt( cipher_psa->slot,
-                                   cipher_psa->alg,
-                                   iv, iv_len,
-                                   ad, ad_len,
-                                   input, ilen,
-                                   output, ilen + tag_len, olen );
-        if( status != PSA_SUCCESS )
-            return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
+        status = psa_aead_encrypt(cipher_psa->slot,
+                                  cipher_psa->alg,
+                                  iv, iv_len,
+                                  ad, ad_len,
+                                  input, ilen,
+                                  output, ilen + tag_len, olen);
+        if (status != PSA_SUCCESS) {
+            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+        }
 
         *olen -= tag_len;
-        return( 0 );
+        return 0;
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #if defined(MBEDTLS_GCM_C)
-    if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
-    {
+    if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) {
         *olen = ilen;
-        return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT,
-                                           ilen, iv, iv_len, ad, ad_len,
-                                           input, output, tag_len, tag ) );
+        return mbedtls_gcm_crypt_and_tag(ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT,
+                                         ilen, iv, iv_len, ad, ad_len,
+                                         input, output, tag_len, tag);
     }
 #endif /* MBEDTLS_GCM_C */
 #if defined(MBEDTLS_CCM_C)
-    if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode )
-    {
+    if (MBEDTLS_MODE_CCM == ctx->cipher_info->mode) {
         *olen = ilen;
-        return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen,
-                                     iv, iv_len, ad, ad_len, input, output,
-                                     tag, tag_len ) );
+        return mbedtls_ccm_encrypt_and_tag(ctx->cipher_ctx, ilen,
+                                           iv, iv_len, ad, ad_len, input, output,
+                                           tag, tag_len);
     }
 #endif /* MBEDTLS_CCM_C */
 #if defined(MBEDTLS_CHACHAPOLY_C)
-    if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
-    {
+    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) {
         /* ChachaPoly has fixed length nonce and MAC (tag) */
-        if ( ( iv_len != ctx->cipher_info->iv_size ) ||
-             ( tag_len != 16U ) )
-        {
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        if ((iv_len != ctx->cipher_info->iv_size) ||
+            (tag_len != 16U)) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
         }
 
         *olen = ilen;
-        return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx,
-                                ilen, iv, ad, ad_len, input, output, tag ) );
+        return mbedtls_chachapoly_encrypt_and_tag(ctx->cipher_ctx,
+                                                  ilen, iv, ad, ad_len, input, output, tag);
     }
 #endif /* MBEDTLS_CHACHAPOLY_C */
 
-    return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
 }
 
 /*
- * Packet-oriented encryption for AEAD modes: internal function shared by
- * mbedtls_cipher_auth_encrypt() and mbedtls_cipher_auth_encrypt_ext().
+ * Packet-oriented encryption for AEAD modes: internal function used by
+ * mbedtls_cipher_auth_encrypt_ext().
  */
-static int mbedtls_cipher_aead_decrypt( mbedtls_cipher_context_t *ctx,
-                         const unsigned char *iv, size_t iv_len,
-                         const unsigned char *ad, size_t ad_len,
-                         const unsigned char *input, size_t ilen,
-                         unsigned char *output, size_t *olen,
-                         const unsigned char *tag, size_t tag_len )
+static int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t *ctx,
+                                       const unsigned char *iv, size_t iv_len,
+                                       const unsigned char *ad, size_t ad_len,
+                                       const unsigned char *input, size_t ilen,
+                                       unsigned char *output, size_t *olen,
+                                       const unsigned char *tag, size_t tag_len)
 {
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ctx->psa_enabled == 1 )
-    {
+    if (ctx->psa_enabled == 1) {
         /* As in the non-PSA case, we don't check that
          * a key has been set. If not, the key slot will
          * still be in its default state of 0, which is
@@ -1436,239 +1441,180 @@
 
         /* PSA Crypto API always writes the authentication tag
          * at the end of the encrypted message. */
-        if( input == NULL || tag != input + ilen )
-            return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+        if (input == NULL || tag != input + ilen) {
+            return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+        }
 
-        status = psa_aead_decrypt( cipher_psa->slot,
-                                   cipher_psa->alg,
-                                   iv, iv_len,
-                                   ad, ad_len,
-                                   input, ilen + tag_len,
-                                   output, ilen, olen );
-        if( status == PSA_ERROR_INVALID_SIGNATURE )
-            return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
-        else if( status != PSA_SUCCESS )
-            return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
+        status = psa_aead_decrypt(cipher_psa->slot,
+                                  cipher_psa->alg,
+                                  iv, iv_len,
+                                  ad, ad_len,
+                                  input, ilen + tag_len,
+                                  output, ilen, olen);
+        if (status == PSA_ERROR_INVALID_SIGNATURE) {
+            return MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+        } else if (status != PSA_SUCCESS) {
+            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+        }
 
-        return( 0 );
+        return 0;
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #if defined(MBEDTLS_GCM_C)
-    if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
-    {
+    if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) {
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
         *olen = ilen;
-        ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen,
-                                iv, iv_len, ad, ad_len,
-                                tag, tag_len, input, output );
+        ret = mbedtls_gcm_auth_decrypt(ctx->cipher_ctx, ilen,
+                                       iv, iv_len, ad, ad_len,
+                                       tag, tag_len, input, output);
 
-        if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED )
+        if (ret == MBEDTLS_ERR_GCM_AUTH_FAILED) {
             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+        }
 
-        return( ret );
+        return ret;
     }
 #endif /* MBEDTLS_GCM_C */
 #if defined(MBEDTLS_CCM_C)
-    if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode )
-    {
+    if (MBEDTLS_MODE_CCM == ctx->cipher_info->mode) {
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
         *olen = ilen;
-        ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen,
-                                iv, iv_len, ad, ad_len,
-                                input, output, tag, tag_len );
+        ret = mbedtls_ccm_auth_decrypt(ctx->cipher_ctx, ilen,
+                                       iv, iv_len, ad, ad_len,
+                                       input, output, tag, tag_len);
 
-        if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED )
+        if (ret == MBEDTLS_ERR_CCM_AUTH_FAILED) {
             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+        }
 
-        return( ret );
+        return ret;
     }
 #endif /* MBEDTLS_CCM_C */
 #if defined(MBEDTLS_CHACHAPOLY_C)
-    if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
-    {
+    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) {
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
         /* ChachaPoly has fixed length nonce and MAC (tag) */
-        if ( ( iv_len != ctx->cipher_info->iv_size ) ||
-             ( tag_len != 16U ) )
-        {
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        if ((iv_len != ctx->cipher_info->iv_size) ||
+            (tag_len != 16U)) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
         }
 
         *olen = ilen;
-        ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen,
-                                iv, ad, ad_len, tag, input, output );
+        ret = mbedtls_chachapoly_auth_decrypt(ctx->cipher_ctx, ilen,
+                                              iv, ad, ad_len, tag, input, output);
 
-        if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED )
+        if (ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED) {
             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+        }
 
-        return( ret );
+        return ret;
     }
 #endif /* MBEDTLS_CHACHAPOLY_C */
 
-    return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
 }
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-/*
- * Packet-oriented encryption for AEAD modes: public legacy function.
- */
-int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx,
-                         const unsigned char *iv, size_t iv_len,
-                         const unsigned char *ad, size_t ad_len,
-                         const unsigned char *input, size_t ilen,
-                         unsigned char *output, size_t *olen,
-                         unsigned char *tag, size_t tag_len )
-{
-    CIPHER_VALIDATE_RET( ctx != NULL );
-    CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
-    CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
-    CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
-    CIPHER_VALIDATE_RET( ilen == 0 || output != NULL );
-    CIPHER_VALIDATE_RET( olen != NULL );
-    CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
-
-    return( mbedtls_cipher_aead_encrypt( ctx, iv, iv_len, ad, ad_len,
-                                         input, ilen, output, olen,
-                                         tag, tag_len ) );
-}
-
-/*
- * Packet-oriented decryption for AEAD modes: public legacy function.
- */
-int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
-                         const unsigned char *iv, size_t iv_len,
-                         const unsigned char *ad, size_t ad_len,
-                         const unsigned char *input, size_t ilen,
-                         unsigned char *output, size_t *olen,
-                         const unsigned char *tag, size_t tag_len )
-{
-    CIPHER_VALIDATE_RET( ctx != NULL );
-    CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
-    CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
-    CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
-    CIPHER_VALIDATE_RET( ilen == 0 || output != NULL );
-    CIPHER_VALIDATE_RET( olen != NULL );
-    CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
-
-    return( mbedtls_cipher_aead_decrypt( ctx, iv, iv_len, ad, ad_len,
-                                         input, ilen, output, olen,
-                                         tag, tag_len ) );
-}
-#endif /* !MBEDTLS_DEPRECATED_REMOVED */
 #endif /* MBEDTLS_CIPHER_MODE_AEAD */
 
 #if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C)
 /*
  * Packet-oriented encryption for AEAD/NIST_KW: public function.
  */
-int mbedtls_cipher_auth_encrypt_ext( mbedtls_cipher_context_t *ctx,
-                         const unsigned char *iv, size_t iv_len,
-                         const unsigned char *ad, size_t ad_len,
-                         const unsigned char *input, size_t ilen,
-                         unsigned char *output, size_t output_len,
-                         size_t *olen, size_t tag_len )
+int mbedtls_cipher_auth_encrypt_ext(mbedtls_cipher_context_t *ctx,
+                                    const unsigned char *iv, size_t iv_len,
+                                    const unsigned char *ad, size_t ad_len,
+                                    const unsigned char *input, size_t ilen,
+                                    unsigned char *output, size_t output_len,
+                                    size_t *olen, size_t tag_len)
 {
-    CIPHER_VALIDATE_RET( ctx != NULL );
-    CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
-    CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
-    CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
-    CIPHER_VALIDATE_RET( output != NULL );
-    CIPHER_VALIDATE_RET( olen != NULL );
-
 #if defined(MBEDTLS_NIST_KW_C)
-    if(
+    if (
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
         ctx->psa_enabled == 0 &&
 #endif
-        ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ||
-          MBEDTLS_MODE_KWP == ctx->cipher_info->mode ) )
-    {
-        mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ?
-                                        MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP;
+        (MBEDTLS_MODE_KW == ctx->cipher_info->mode ||
+         MBEDTLS_MODE_KWP == ctx->cipher_info->mode)) {
+        mbedtls_nist_kw_mode_t mode = (MBEDTLS_MODE_KW == ctx->cipher_info->mode) ?
+                                      MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP;
 
         /* There is no iv, tag or ad associated with KW and KWP,
          * so these length should be 0 as documented. */
-        if( iv_len != 0 || tag_len != 0 || ad_len != 0 )
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        if (iv_len != 0 || tag_len != 0 || ad_len != 0) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+        }
 
         (void) iv;
         (void) ad;
 
-        return( mbedtls_nist_kw_wrap( ctx->cipher_ctx, mode, input, ilen,
-                                      output, olen, output_len ) );
+        return mbedtls_nist_kw_wrap(ctx->cipher_ctx, mode, input, ilen,
+                                    output, olen, output_len);
     }
 #endif /* MBEDTLS_NIST_KW_C */
 
 #if defined(MBEDTLS_CIPHER_MODE_AEAD)
     /* AEAD case: check length before passing on to shared function */
-    if( output_len < ilen + tag_len )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (output_len < ilen + tag_len) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
-    int ret = mbedtls_cipher_aead_encrypt( ctx, iv, iv_len, ad, ad_len,
-                                       input, ilen, output, olen,
-                                       output + ilen, tag_len );
+    int ret = mbedtls_cipher_aead_encrypt(ctx, iv, iv_len, ad, ad_len,
+                                          input, ilen, output, olen,
+                                          output + ilen, tag_len);
     *olen += tag_len;
-    return( ret );
+    return ret;
 #else
-    return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
 #endif /* MBEDTLS_CIPHER_MODE_AEAD */
 }
 
 /*
  * Packet-oriented decryption for AEAD/NIST_KW: public function.
  */
-int mbedtls_cipher_auth_decrypt_ext( mbedtls_cipher_context_t *ctx,
-                         const unsigned char *iv, size_t iv_len,
-                         const unsigned char *ad, size_t ad_len,
-                         const unsigned char *input, size_t ilen,
-                         unsigned char *output, size_t output_len,
-                         size_t *olen, size_t tag_len )
+int mbedtls_cipher_auth_decrypt_ext(mbedtls_cipher_context_t *ctx,
+                                    const unsigned char *iv, size_t iv_len,
+                                    const unsigned char *ad, size_t ad_len,
+                                    const unsigned char *input, size_t ilen,
+                                    unsigned char *output, size_t output_len,
+                                    size_t *olen, size_t tag_len)
 {
-    CIPHER_VALIDATE_RET( ctx != NULL );
-    CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
-    CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
-    CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
-    CIPHER_VALIDATE_RET( output_len == 0 || output != NULL );
-    CIPHER_VALIDATE_RET( olen != NULL );
-
 #if defined(MBEDTLS_NIST_KW_C)
-    if(
+    if (
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
         ctx->psa_enabled == 0 &&
 #endif
-        ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ||
-          MBEDTLS_MODE_KWP == ctx->cipher_info->mode ) )
-    {
-        mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ?
-                                        MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP;
+        (MBEDTLS_MODE_KW == ctx->cipher_info->mode ||
+         MBEDTLS_MODE_KWP == ctx->cipher_info->mode)) {
+        mbedtls_nist_kw_mode_t mode = (MBEDTLS_MODE_KW == ctx->cipher_info->mode) ?
+                                      MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP;
 
         /* There is no iv, tag or ad associated with KW and KWP,
          * so these length should be 0 as documented. */
-        if( iv_len != 0 || tag_len != 0 || ad_len != 0 )
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        if (iv_len != 0 || tag_len != 0 || ad_len != 0) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+        }
 
         (void) iv;
         (void) ad;
 
-        return( mbedtls_nist_kw_unwrap( ctx->cipher_ctx, mode, input, ilen,
-                                        output, olen, output_len ) );
+        return mbedtls_nist_kw_unwrap(ctx->cipher_ctx, mode, input, ilen,
+                                      output, olen, output_len);
     }
 #endif /* MBEDTLS_NIST_KW_C */
 
 #if defined(MBEDTLS_CIPHER_MODE_AEAD)
     /* AEAD case: check length before passing on to shared function */
-    if( ilen < tag_len || output_len < ilen - tag_len )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (ilen < tag_len || output_len < ilen - tag_len) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
-    return( mbedtls_cipher_aead_decrypt( ctx, iv, iv_len, ad, ad_len,
-                                         input, ilen - tag_len, output, olen,
-                                         input + ilen - tag_len, tag_len ) );
+    return mbedtls_cipher_aead_decrypt(ctx, iv, iv_len, ad, ad_len,
+                                       input, ilen - tag_len, output, olen,
+                                       input + ilen - tag_len, tag_len);
 #else
-    return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
 #endif /* MBEDTLS_CIPHER_MODE_AEAD */
 }
 #endif /* MBEDTLS_CIPHER_MODE_AEAD || MBEDTLS_NIST_KW_C */
diff --git a/lib/libmbedtls/mbedtls/library/cipher_wrap.c b/lib/libmbedtls/mbedtls/library/cipher_wrap.c
index f05fa15..fb36314 100644
--- a/lib/libmbedtls/mbedtls/library/cipher_wrap.c
+++ b/lib/libmbedtls/mbedtls/library/cipher_wrap.c
@@ -27,7 +27,7 @@
 
 #if defined(MBEDTLS_CIPHER_C)
 
-#include "mbedtls/cipher_internal.h"
+#include "cipher_wrap.h"
 #include "mbedtls/error.h"
 
 #if defined(MBEDTLS_CHACHAPOLY_C)
@@ -38,10 +38,6 @@
 #include "mbedtls/aes.h"
 #endif
 
-#if defined(MBEDTLS_ARC4_C)
-#include "mbedtls/arc4.h"
-#endif
-
 #if defined(MBEDTLS_CAMELLIA_C)
 #include "mbedtls/camellia.h"
 #endif
@@ -54,10 +50,6 @@
 #include "mbedtls/des.h"
 #endif
 
-#if defined(MBEDTLS_BLOWFISH_C)
-#include "mbedtls/blowfish.h"
-#endif
-
 #if defined(MBEDTLS_CHACHA20_C)
 #include "mbedtls/chacha20.h"
 #endif
@@ -78,120 +70,115 @@
 #include <string.h>
 #endif
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free       free
-#endif
 
 #if defined(MBEDTLS_GCM_C)
 /* shared by all GCM ciphers */
-static void *gcm_ctx_alloc( void )
+static void *gcm_ctx_alloc(void)
 {
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_gcm_context ) );
+    void *ctx = mbedtls_calloc(1, sizeof(mbedtls_gcm_context));
 
-    if( ctx != NULL )
-        mbedtls_gcm_init( (mbedtls_gcm_context *) ctx );
+    if (ctx != NULL) {
+        mbedtls_gcm_init((mbedtls_gcm_context *) ctx);
+    }
 
-    return( ctx );
+    return ctx;
 }
 
-static void gcm_ctx_clone( void *dst, const void *src )
+static void gcm_ctx_clone(void *dst, const void *src)
 {
-    memcpy( dst, src, sizeof( mbedtls_gcm_context ) );
+    memcpy(dst, src, sizeof(mbedtls_gcm_context));
 }
 
-static void gcm_ctx_free( void *ctx )
+static void gcm_ctx_free(void *ctx)
 {
-    mbedtls_gcm_free( ctx );
-    mbedtls_free( ctx );
+    mbedtls_gcm_free(ctx);
+    mbedtls_free(ctx);
 }
 #endif /* MBEDTLS_GCM_C */
 
 #if defined(MBEDTLS_CCM_C)
 /* shared by all CCM ciphers */
-static void *ccm_ctx_alloc( void )
+static void *ccm_ctx_alloc(void)
 {
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ccm_context ) );
+    void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ccm_context));
 
-    if( ctx != NULL )
-        mbedtls_ccm_init( (mbedtls_ccm_context *) ctx );
+    if (ctx != NULL) {
+        mbedtls_ccm_init((mbedtls_ccm_context *) ctx);
+    }
 
-    return( ctx );
+    return ctx;
 }
 
-static void ccm_ctx_clone( void *dst, const void *src )
+static void ccm_ctx_clone(void *dst, const void *src)
 {
-    memcpy( dst, src, sizeof( mbedtls_ccm_context ) );
+    memcpy(dst, src, sizeof(mbedtls_ccm_context));
 }
 
-static void ccm_ctx_free( void *ctx )
+static void ccm_ctx_free(void *ctx)
 {
-    mbedtls_ccm_free( ctx );
-    mbedtls_free( ctx );
+    mbedtls_ccm_free(ctx);
+    mbedtls_free(ctx);
 }
 #endif /* MBEDTLS_CCM_C */
 
 #if defined(MBEDTLS_AES_C)
 
-static int aes_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation,
-        const unsigned char *input, unsigned char *output )
+static int aes_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation,
+                              const unsigned char *input, unsigned char *output)
 {
-    return mbedtls_aes_crypt_ecb( (mbedtls_aes_context *) ctx, operation, input, output );
+    return mbedtls_aes_crypt_ecb((mbedtls_aes_context *) ctx, operation, input, output);
 }
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-static int aes_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length,
-        unsigned char *iv, const unsigned char *input, unsigned char *output )
+static int aes_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation, size_t length,
+                              unsigned char *iv, const unsigned char *input, unsigned char *output)
 {
-    return mbedtls_aes_crypt_cbc( (mbedtls_aes_context *) ctx, operation, length, iv, input,
-                          output );
+    return mbedtls_aes_crypt_cbc((mbedtls_aes_context *) ctx, operation, length, iv, input,
+                                 output);
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
-static int aes_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation,
-        size_t length, size_t *iv_off, unsigned char *iv,
-        const unsigned char *input, unsigned char *output )
+static int aes_crypt_cfb128_wrap(void *ctx, mbedtls_operation_t operation,
+                                 size_t length, size_t *iv_off, unsigned char *iv,
+                                 const unsigned char *input, unsigned char *output)
 {
-    return mbedtls_aes_crypt_cfb128( (mbedtls_aes_context *) ctx, operation, length, iv_off, iv,
-                             input, output );
+    return mbedtls_aes_crypt_cfb128((mbedtls_aes_context *) ctx, operation, length, iv_off, iv,
+                                    input, output);
 }
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_OFB)
-static int aes_crypt_ofb_wrap( void *ctx, size_t length, size_t *iv_off,
-        unsigned char *iv, const unsigned char *input, unsigned char *output )
+static int aes_crypt_ofb_wrap(void *ctx, size_t length, size_t *iv_off,
+                              unsigned char *iv, const unsigned char *input, unsigned char *output)
 {
-    return mbedtls_aes_crypt_ofb( (mbedtls_aes_context *) ctx, length, iv_off,
-                                    iv, input, output );
+    return mbedtls_aes_crypt_ofb((mbedtls_aes_context *) ctx, length, iv_off,
+                                 iv, input, output);
 }
 #endif /* MBEDTLS_CIPHER_MODE_OFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
-static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
-        unsigned char *nonce_counter, unsigned char *stream_block,
-        const unsigned char *input, unsigned char *output )
+static int aes_crypt_ctr_wrap(void *ctx, size_t length, size_t *nc_off,
+                              unsigned char *nonce_counter, unsigned char *stream_block,
+                              const unsigned char *input, unsigned char *output)
 {
-    return mbedtls_aes_crypt_ctr( (mbedtls_aes_context *) ctx, length, nc_off, nonce_counter,
-                          stream_block, input, output );
+    return mbedtls_aes_crypt_ctr((mbedtls_aes_context *) ctx, length, nc_off, nonce_counter,
+                                 stream_block, input, output);
 }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
 #if defined(MBEDTLS_CIPHER_MODE_XTS)
-static int aes_crypt_xts_wrap( void *ctx, mbedtls_operation_t operation,
-                               size_t length,
-                               const unsigned char data_unit[16],
-                               const unsigned char *input,
-                               unsigned char *output )
+static int aes_crypt_xts_wrap(void *ctx, mbedtls_operation_t operation,
+                              size_t length,
+                              const unsigned char data_unit[16],
+                              const unsigned char *input,
+                              unsigned char *output)
 {
     mbedtls_aes_xts_context *xts_ctx = ctx;
     int mode;
 
-    switch( operation )
-    {
+    switch (operation) {
         case MBEDTLS_ENCRYPT:
             mode = MBEDTLS_AES_ENCRYPT;
             break;
@@ -202,44 +189,45 @@
             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
-    return mbedtls_aes_crypt_xts( xts_ctx, mode, length,
-                                  data_unit, input, output );
+    return mbedtls_aes_crypt_xts(xts_ctx, mode, length,
+                                 data_unit, input, output);
 }
 #endif /* MBEDTLS_CIPHER_MODE_XTS */
 
-static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key,
-                                unsigned int key_bitlen )
+static int aes_setkey_dec_wrap(void *ctx, const unsigned char *key,
+                               unsigned int key_bitlen)
 {
-    return mbedtls_aes_setkey_dec( (mbedtls_aes_context *) ctx, key, key_bitlen );
+    return mbedtls_aes_setkey_dec((mbedtls_aes_context *) ctx, key, key_bitlen);
 }
 
-static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key,
-                                unsigned int key_bitlen )
+static int aes_setkey_enc_wrap(void *ctx, const unsigned char *key,
+                               unsigned int key_bitlen)
 {
-    return mbedtls_aes_setkey_enc( (mbedtls_aes_context *) ctx, key, key_bitlen );
+    return mbedtls_aes_setkey_enc((mbedtls_aes_context *) ctx, key, key_bitlen);
 }
 
-static void * aes_ctx_alloc( void )
+static void *aes_ctx_alloc(void)
 {
-    mbedtls_aes_context *aes = mbedtls_calloc( 1, sizeof( mbedtls_aes_context ) );
+    mbedtls_aes_context *aes = mbedtls_calloc(1, sizeof(mbedtls_aes_context));
 
-    if( aes == NULL )
-        return( NULL );
+    if (aes == NULL) {
+        return NULL;
+    }
 
-    mbedtls_aes_init( aes );
+    mbedtls_aes_init(aes);
 
-    return( aes );
+    return aes;
 }
 
-static void aes_ctx_clone( void *dst, const void *src )
+static void aes_ctx_clone(void *dst, const void *src)
 {
-    memcpy( dst, src, sizeof( mbedtls_aes_context ) );
+    memcpy(dst, src, sizeof(mbedtls_aes_context));
 }
 
-static void aes_ctx_free( void *ctx )
+static void aes_ctx_free(void *ctx)
 {
-    mbedtls_aes_free( (mbedtls_aes_context *) ctx );
-    mbedtls_free( ctx );
+    mbedtls_aes_free((mbedtls_aes_context *) ctx);
+    mbedtls_free(ctx);
 }
 
 static const mbedtls_cipher_base_t aes_info = {
@@ -444,39 +432,41 @@
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
 #if defined(MBEDTLS_CIPHER_MODE_XTS)
-static int xts_aes_setkey_enc_wrap( void *ctx, const unsigned char *key,
-                                    unsigned int key_bitlen )
+static int xts_aes_setkey_enc_wrap(void *ctx, const unsigned char *key,
+                                   unsigned int key_bitlen)
 {
     mbedtls_aes_xts_context *xts_ctx = ctx;
-    return( mbedtls_aes_xts_setkey_enc( xts_ctx, key, key_bitlen ) );
+    return mbedtls_aes_xts_setkey_enc(xts_ctx, key, key_bitlen);
 }
 
-static int xts_aes_setkey_dec_wrap( void *ctx, const unsigned char *key,
-                                    unsigned int key_bitlen )
+static int xts_aes_setkey_dec_wrap(void *ctx, const unsigned char *key,
+                                   unsigned int key_bitlen)
 {
     mbedtls_aes_xts_context *xts_ctx = ctx;
-    return( mbedtls_aes_xts_setkey_dec( xts_ctx, key, key_bitlen ) );
+    return mbedtls_aes_xts_setkey_dec(xts_ctx, key, key_bitlen);
 }
 
-static void *xts_aes_ctx_alloc( void )
+static void *xts_aes_ctx_alloc(void)
 {
-    mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc( 1, sizeof( *xts_ctx ) );
+    mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc(1, sizeof(*xts_ctx));
 
-    if( xts_ctx != NULL )
-        mbedtls_aes_xts_init( xts_ctx );
+    if (xts_ctx != NULL) {
+        mbedtls_aes_xts_init(xts_ctx);
+    }
 
-    return( xts_ctx );
+    return xts_ctx;
 }
 
-static void xts_aes_ctx_free( void *ctx )
+static void xts_aes_ctx_free(void *ctx)
 {
     mbedtls_aes_xts_context *xts_ctx = ctx;
 
-    if( xts_ctx == NULL )
+    if (xts_ctx == NULL) {
         return;
+    }
 
-    mbedtls_aes_xts_free( xts_ctx );
-    mbedtls_free( xts_ctx );
+    mbedtls_aes_xts_free(xts_ctx);
+    mbedtls_free(xts_ctx);
 }
 
 static const mbedtls_cipher_base_t xts_aes_info = {
@@ -530,11 +520,11 @@
 #endif /* MBEDTLS_CIPHER_MODE_XTS */
 
 #if defined(MBEDTLS_GCM_C)
-static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key,
-                                unsigned int key_bitlen )
+static int gcm_aes_setkey_wrap(void *ctx, const unsigned char *key,
+                               unsigned int key_bitlen)
 {
-    return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES,
-                     key, key_bitlen );
+    return mbedtls_gcm_setkey((mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES,
+                              key, key_bitlen);
 }
 
 static const mbedtls_cipher_base_t gcm_aes_info = {
@@ -600,11 +590,11 @@
 #endif /* MBEDTLS_GCM_C */
 
 #if defined(MBEDTLS_CCM_C)
-static int ccm_aes_setkey_wrap( void *ctx, const unsigned char *key,
-                                unsigned int key_bitlen )
+static int ccm_aes_setkey_wrap(void *ctx, const unsigned char *key,
+                               unsigned int key_bitlen)
 {
-    return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES,
-                     key, key_bitlen );
+    return mbedtls_ccm_setkey((mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES,
+                              key, key_bitlen);
 }
 
 static const mbedtls_cipher_base_t ccm_aes_info = {
@@ -667,83 +657,117 @@
     16,
     &ccm_aes_info
 };
+
+static const mbedtls_cipher_info_t aes_128_ccm_star_no_tag_info = {
+    MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    128,
+    "AES-128-CCM*-NO-TAG",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_aes_info
+};
+
+static const mbedtls_cipher_info_t aes_192_ccm_star_no_tag_info = {
+    MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    192,
+    "AES-192-CCM*-NO-TAG",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_aes_info
+};
+
+static const mbedtls_cipher_info_t aes_256_ccm_star_no_tag_info = {
+    MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    256,
+    "AES-256-CCM*-NO-TAG",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_aes_info
+};
 #endif /* MBEDTLS_CCM_C */
 
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_CAMELLIA_C)
 
-static int camellia_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation,
-        const unsigned char *input, unsigned char *output )
+static int camellia_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation,
+                                   const unsigned char *input, unsigned char *output)
 {
-    return mbedtls_camellia_crypt_ecb( (mbedtls_camellia_context *) ctx, operation, input,
-                               output );
+    return mbedtls_camellia_crypt_ecb((mbedtls_camellia_context *) ctx, operation, input,
+                                      output);
 }
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-static int camellia_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation,
-        size_t length, unsigned char *iv,
-        const unsigned char *input, unsigned char *output )
+static int camellia_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation,
+                                   size_t length, unsigned char *iv,
+                                   const unsigned char *input, unsigned char *output)
 {
-    return mbedtls_camellia_crypt_cbc( (mbedtls_camellia_context *) ctx, operation, length, iv,
-                               input, output );
+    return mbedtls_camellia_crypt_cbc((mbedtls_camellia_context *) ctx, operation, length, iv,
+                                      input, output);
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
-static int camellia_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation,
-        size_t length, size_t *iv_off, unsigned char *iv,
-        const unsigned char *input, unsigned char *output )
+static int camellia_crypt_cfb128_wrap(void *ctx, mbedtls_operation_t operation,
+                                      size_t length, size_t *iv_off, unsigned char *iv,
+                                      const unsigned char *input, unsigned char *output)
 {
-    return mbedtls_camellia_crypt_cfb128( (mbedtls_camellia_context *) ctx, operation, length,
-                                  iv_off, iv, input, output );
+    return mbedtls_camellia_crypt_cfb128((mbedtls_camellia_context *) ctx, operation, length,
+                                         iv_off, iv, input, output);
 }
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
-static int camellia_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
-        unsigned char *nonce_counter, unsigned char *stream_block,
-        const unsigned char *input, unsigned char *output )
+static int camellia_crypt_ctr_wrap(void *ctx, size_t length, size_t *nc_off,
+                                   unsigned char *nonce_counter, unsigned char *stream_block,
+                                   const unsigned char *input, unsigned char *output)
 {
-    return mbedtls_camellia_crypt_ctr( (mbedtls_camellia_context *) ctx, length, nc_off,
-                               nonce_counter, stream_block, input, output );
+    return mbedtls_camellia_crypt_ctr((mbedtls_camellia_context *) ctx, length, nc_off,
+                                      nonce_counter, stream_block, input, output);
 }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
-static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key,
-                                     unsigned int key_bitlen )
+static int camellia_setkey_dec_wrap(void *ctx, const unsigned char *key,
+                                    unsigned int key_bitlen)
 {
-    return mbedtls_camellia_setkey_dec( (mbedtls_camellia_context *) ctx, key, key_bitlen );
+    return mbedtls_camellia_setkey_dec((mbedtls_camellia_context *) ctx, key, key_bitlen);
 }
 
-static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key,
-                                     unsigned int key_bitlen )
+static int camellia_setkey_enc_wrap(void *ctx, const unsigned char *key,
+                                    unsigned int key_bitlen)
 {
-    return mbedtls_camellia_setkey_enc( (mbedtls_camellia_context *) ctx, key, key_bitlen );
+    return mbedtls_camellia_setkey_enc((mbedtls_camellia_context *) ctx, key, key_bitlen);
 }
 
-static void * camellia_ctx_alloc( void )
+static void *camellia_ctx_alloc(void)
 {
     mbedtls_camellia_context *ctx;
-    ctx = mbedtls_calloc( 1, sizeof( mbedtls_camellia_context ) );
+    ctx = mbedtls_calloc(1, sizeof(mbedtls_camellia_context));
 
-    if( ctx == NULL )
-        return( NULL );
+    if (ctx == NULL) {
+        return NULL;
+    }
 
-    mbedtls_camellia_init( ctx );
+    mbedtls_camellia_init(ctx);
 
-    return( ctx );
+    return ctx;
 }
 
-static void camellia_ctx_clone( void *dst, const void *src )
+static void camellia_ctx_clone(void *dst, const void *src)
 {
-    memcpy( dst, src, sizeof( mbedtls_camellia_context ) );
+    memcpy(dst, src, sizeof(mbedtls_camellia_context));
 }
 
-static void camellia_ctx_free( void *ctx )
+static void camellia_ctx_free(void *ctx)
 {
-    mbedtls_camellia_free( (mbedtls_camellia_context *) ctx );
-    mbedtls_free( ctx );
+    mbedtls_camellia_free((mbedtls_camellia_context *) ctx);
+    mbedtls_free(ctx);
 }
 
 static const mbedtls_cipher_base_t camellia_info = {
@@ -913,11 +937,11 @@
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
 #if defined(MBEDTLS_GCM_C)
-static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key,
-                                     unsigned int key_bitlen )
+static int gcm_camellia_setkey_wrap(void *ctx, const unsigned char *key,
+                                    unsigned int key_bitlen)
 {
-    return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA,
-                     key, key_bitlen );
+    return mbedtls_gcm_setkey((mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA,
+                              key, key_bitlen);
 }
 
 static const mbedtls_cipher_base_t gcm_camellia_info = {
@@ -983,11 +1007,11 @@
 #endif /* MBEDTLS_GCM_C */
 
 #if defined(MBEDTLS_CCM_C)
-static int ccm_camellia_setkey_wrap( void *ctx, const unsigned char *key,
-                                     unsigned int key_bitlen )
+static int ccm_camellia_setkey_wrap(void *ctx, const unsigned char *key,
+                                    unsigned int key_bitlen)
 {
-    return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA,
-                     key, key_bitlen );
+    return mbedtls_ccm_setkey((mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA,
+                              key, key_bitlen);
 }
 
 static const mbedtls_cipher_base_t ccm_camellia_info = {
@@ -1050,79 +1074,113 @@
     16,
     &ccm_camellia_info
 };
+
+static const mbedtls_cipher_info_t camellia_128_ccm_star_no_tag_info = {
+    MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    128,
+    "CAMELLIA-128-CCM*-NO-TAG",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_camellia_info
+};
+
+static const mbedtls_cipher_info_t camellia_192_ccm_star_no_tag_info = {
+    MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    192,
+    "CAMELLIA-192-CCM*-NO-TAG",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_camellia_info
+};
+
+static const mbedtls_cipher_info_t camellia_256_ccm_star_no_tag_info = {
+    MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    256,
+    "CAMELLIA-256-CCM*-NO-TAG",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_camellia_info
+};
 #endif /* MBEDTLS_CCM_C */
 
 #endif /* MBEDTLS_CAMELLIA_C */
 
 #if defined(MBEDTLS_ARIA_C)
 
-static int aria_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation,
-        const unsigned char *input, unsigned char *output )
+static int aria_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation,
+                               const unsigned char *input, unsigned char *output)
 {
     (void) operation;
-    return mbedtls_aria_crypt_ecb( (mbedtls_aria_context *) ctx, input,
-                               output );
+    return mbedtls_aria_crypt_ecb((mbedtls_aria_context *) ctx, input,
+                                  output);
 }
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-static int aria_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation,
-        size_t length, unsigned char *iv,
-        const unsigned char *input, unsigned char *output )
+static int aria_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation,
+                               size_t length, unsigned char *iv,
+                               const unsigned char *input, unsigned char *output)
 {
-    return mbedtls_aria_crypt_cbc( (mbedtls_aria_context *) ctx, operation, length, iv,
-                               input, output );
+    return mbedtls_aria_crypt_cbc((mbedtls_aria_context *) ctx, operation, length, iv,
+                                  input, output);
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
-static int aria_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation,
-        size_t length, size_t *iv_off, unsigned char *iv,
-        const unsigned char *input, unsigned char *output )
+static int aria_crypt_cfb128_wrap(void *ctx, mbedtls_operation_t operation,
+                                  size_t length, size_t *iv_off, unsigned char *iv,
+                                  const unsigned char *input, unsigned char *output)
 {
-    return mbedtls_aria_crypt_cfb128( (mbedtls_aria_context *) ctx, operation, length,
-                                  iv_off, iv, input, output );
+    return mbedtls_aria_crypt_cfb128((mbedtls_aria_context *) ctx, operation, length,
+                                     iv_off, iv, input, output);
 }
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
-static int aria_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
-        unsigned char *nonce_counter, unsigned char *stream_block,
-        const unsigned char *input, unsigned char *output )
+static int aria_crypt_ctr_wrap(void *ctx, size_t length, size_t *nc_off,
+                               unsigned char *nonce_counter, unsigned char *stream_block,
+                               const unsigned char *input, unsigned char *output)
 {
-    return mbedtls_aria_crypt_ctr( (mbedtls_aria_context *) ctx, length, nc_off,
-                               nonce_counter, stream_block, input, output );
+    return mbedtls_aria_crypt_ctr((mbedtls_aria_context *) ctx, length, nc_off,
+                                  nonce_counter, stream_block, input, output);
 }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
-static int aria_setkey_dec_wrap( void *ctx, const unsigned char *key,
-                                     unsigned int key_bitlen )
+static int aria_setkey_dec_wrap(void *ctx, const unsigned char *key,
+                                unsigned int key_bitlen)
 {
-    return mbedtls_aria_setkey_dec( (mbedtls_aria_context *) ctx, key, key_bitlen );
+    return mbedtls_aria_setkey_dec((mbedtls_aria_context *) ctx, key, key_bitlen);
 }
 
-static int aria_setkey_enc_wrap( void *ctx, const unsigned char *key,
-                                     unsigned int key_bitlen )
+static int aria_setkey_enc_wrap(void *ctx, const unsigned char *key,
+                                unsigned int key_bitlen)
 {
-    return mbedtls_aria_setkey_enc( (mbedtls_aria_context *) ctx, key, key_bitlen );
+    return mbedtls_aria_setkey_enc((mbedtls_aria_context *) ctx, key, key_bitlen);
 }
 
-static void * aria_ctx_alloc( void )
+static void *aria_ctx_alloc(void)
 {
     mbedtls_aria_context *ctx;
-    ctx = mbedtls_calloc( 1, sizeof( mbedtls_aria_context ) );
+    ctx = mbedtls_calloc(1, sizeof(mbedtls_aria_context));
 
-    if( ctx == NULL )
-        return( NULL );
+    if (ctx == NULL) {
+        return NULL;
+    }
 
-    mbedtls_aria_init( ctx );
+    mbedtls_aria_init(ctx);
 
-    return( ctx );
+    return ctx;
 }
 
-static void aria_ctx_free( void *ctx )
+static void aria_ctx_free(void *ctx)
 {
-    mbedtls_aria_free( (mbedtls_aria_context *) ctx );
-    mbedtls_free( ctx );
+    mbedtls_aria_free((mbedtls_aria_context *) ctx);
+    mbedtls_free(ctx);
 }
 
 static const mbedtls_cipher_base_t aria_info = {
@@ -1291,11 +1349,11 @@
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
 #if defined(MBEDTLS_GCM_C)
-static int gcm_aria_setkey_wrap( void *ctx, const unsigned char *key,
-                                     unsigned int key_bitlen )
+static int gcm_aria_setkey_wrap(void *ctx, const unsigned char *key,
+                                unsigned int key_bitlen)
 {
-    return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA,
-                     key, key_bitlen );
+    return mbedtls_gcm_setkey((mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA,
+                              key, key_bitlen);
 }
 
 static const mbedtls_cipher_base_t gcm_aria_info = {
@@ -1360,11 +1418,11 @@
 #endif /* MBEDTLS_GCM_C */
 
 #if defined(MBEDTLS_CCM_C)
-static int ccm_aria_setkey_wrap( void *ctx, const unsigned char *key,
-                                     unsigned int key_bitlen )
+static int ccm_aria_setkey_wrap(void *ctx, const unsigned char *key,
+                                unsigned int key_bitlen)
 {
-    return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA,
-                     key, key_bitlen );
+    return mbedtls_ccm_setkey((mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA,
+                              key, key_bitlen);
 }
 
 static const mbedtls_cipher_base_t ccm_aria_info = {
@@ -1426,137 +1484,172 @@
     16,
     &ccm_aria_info
 };
+
+static const mbedtls_cipher_info_t aria_128_ccm_star_no_tag_info = {
+    MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    128,
+    "ARIA-128-CCM*-NO-TAG",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_aria_info
+};
+
+static const mbedtls_cipher_info_t aria_192_ccm_star_no_tag_info = {
+    MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    192,
+    "ARIA-192-CCM*-NO-TAG",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_aria_info
+};
+
+static const mbedtls_cipher_info_t aria_256_ccm_star_no_tag_info = {
+    MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    256,
+    "ARIA-256-CCM*-NO-TAG",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_aria_info
+};
 #endif /* MBEDTLS_CCM_C */
 
 #endif /* MBEDTLS_ARIA_C */
 
 #if defined(MBEDTLS_DES_C)
 
-static int des_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation,
-        const unsigned char *input, unsigned char *output )
+static int des_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation,
+                              const unsigned char *input, unsigned char *output)
 {
     ((void) operation);
-    return mbedtls_des_crypt_ecb( (mbedtls_des_context *) ctx, input, output );
+    return mbedtls_des_crypt_ecb((mbedtls_des_context *) ctx, input, output);
 }
 
-static int des3_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation,
-        const unsigned char *input, unsigned char *output )
+static int des3_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation,
+                               const unsigned char *input, unsigned char *output)
 {
     ((void) operation);
-    return mbedtls_des3_crypt_ecb( (mbedtls_des3_context *) ctx, input, output );
+    return mbedtls_des3_crypt_ecb((mbedtls_des3_context *) ctx, input, output);
 }
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-static int des_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length,
-        unsigned char *iv, const unsigned char *input, unsigned char *output )
+static int des_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation, size_t length,
+                              unsigned char *iv, const unsigned char *input, unsigned char *output)
 {
-    return mbedtls_des_crypt_cbc( (mbedtls_des_context *) ctx, operation, length, iv, input,
-                          output );
+    return mbedtls_des_crypt_cbc((mbedtls_des_context *) ctx, operation, length, iv, input,
+                                 output);
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-static int des3_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length,
-        unsigned char *iv, const unsigned char *input, unsigned char *output )
+static int des3_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation, size_t length,
+                               unsigned char *iv, const unsigned char *input, unsigned char *output)
 {
-    return mbedtls_des3_crypt_cbc( (mbedtls_des3_context *) ctx, operation, length, iv, input,
-                           output );
+    return mbedtls_des3_crypt_cbc((mbedtls_des3_context *) ctx, operation, length, iv, input,
+                                  output);
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
-static int des_setkey_dec_wrap( void *ctx, const unsigned char *key,
-                                unsigned int key_bitlen )
+static int des_setkey_dec_wrap(void *ctx, const unsigned char *key,
+                               unsigned int key_bitlen)
 {
     ((void) key_bitlen);
 
-    return mbedtls_des_setkey_dec( (mbedtls_des_context *) ctx, key );
+    return mbedtls_des_setkey_dec((mbedtls_des_context *) ctx, key);
 }
 
-static int des_setkey_enc_wrap( void *ctx, const unsigned char *key,
-                                unsigned int key_bitlen )
+static int des_setkey_enc_wrap(void *ctx, const unsigned char *key,
+                               unsigned int key_bitlen)
 {
     ((void) key_bitlen);
 
-    return mbedtls_des_setkey_enc( (mbedtls_des_context *) ctx, key );
+    return mbedtls_des_setkey_enc((mbedtls_des_context *) ctx, key);
 }
 
-static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key,
-                                  unsigned int key_bitlen )
+static int des3_set2key_dec_wrap(void *ctx, const unsigned char *key,
+                                 unsigned int key_bitlen)
 {
     ((void) key_bitlen);
 
-    return mbedtls_des3_set2key_dec( (mbedtls_des3_context *) ctx, key );
+    return mbedtls_des3_set2key_dec((mbedtls_des3_context *) ctx, key);
 }
 
-static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key,
-                                  unsigned int key_bitlen )
+static int des3_set2key_enc_wrap(void *ctx, const unsigned char *key,
+                                 unsigned int key_bitlen)
 {
     ((void) key_bitlen);
 
-    return mbedtls_des3_set2key_enc( (mbedtls_des3_context *) ctx, key );
+    return mbedtls_des3_set2key_enc((mbedtls_des3_context *) ctx, key);
 }
 
-static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key,
-                                  unsigned int key_bitlen )
+static int des3_set3key_dec_wrap(void *ctx, const unsigned char *key,
+                                 unsigned int key_bitlen)
 {
     ((void) key_bitlen);
 
-    return mbedtls_des3_set3key_dec( (mbedtls_des3_context *) ctx, key );
+    return mbedtls_des3_set3key_dec((mbedtls_des3_context *) ctx, key);
 }
 
-static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key,
-                                  unsigned int key_bitlen )
+static int des3_set3key_enc_wrap(void *ctx, const unsigned char *key,
+                                 unsigned int key_bitlen)
 {
     ((void) key_bitlen);
 
-    return mbedtls_des3_set3key_enc( (mbedtls_des3_context *) ctx, key );
+    return mbedtls_des3_set3key_enc((mbedtls_des3_context *) ctx, key);
 }
 
-static void * des_ctx_alloc( void )
+static void *des_ctx_alloc(void)
 {
-    mbedtls_des_context *des = mbedtls_calloc( 1, sizeof( mbedtls_des_context ) );
+    mbedtls_des_context *des = mbedtls_calloc(1, sizeof(mbedtls_des_context));
 
-    if( des == NULL )
-        return( NULL );
+    if (des == NULL) {
+        return NULL;
+    }
 
-    mbedtls_des_init( des );
+    mbedtls_des_init(des);
 
-    return( des );
+    return des;
 }
 
-static void des_ctx_clone( void *dst, const void *src )
+static void des_ctx_clone(void *dst, const void *src)
 {
-    memcpy( dst, src, sizeof( mbedtls_des_context ) );
+    memcpy(dst, src, sizeof(mbedtls_des_context));
 }
 
-static void des_ctx_free( void *ctx )
+static void des_ctx_free(void *ctx)
 {
-    mbedtls_des_free( (mbedtls_des_context *) ctx );
-    mbedtls_free( ctx );
+    mbedtls_des_free((mbedtls_des_context *) ctx);
+    mbedtls_free(ctx);
 }
 
-static void * des3_ctx_alloc( void )
+static void *des3_ctx_alloc(void)
 {
     mbedtls_des3_context *des3;
-    des3 = mbedtls_calloc( 1, sizeof( mbedtls_des3_context ) );
+    des3 = mbedtls_calloc(1, sizeof(mbedtls_des3_context));
 
-    if( des3 == NULL )
-        return( NULL );
+    if (des3 == NULL) {
+        return NULL;
+    }
 
-    mbedtls_des3_init( des3 );
+    mbedtls_des3_init(des3);
 
-    return( des3 );
+    return des3;
 }
 
-static void des3_ctx_clone( void *dst, const void *src )
+static void des3_ctx_clone(void *dst, const void *src)
 {
-    memcpy( dst, src, sizeof( mbedtls_des3_context ) );
+    memcpy(dst, src, sizeof(mbedtls_des3_context));
 }
 
-static void des3_ctx_free( void *ctx )
+static void des3_ctx_free(void *ctx)
 {
-    mbedtls_des3_free( (mbedtls_des3_context *) ctx );
-    mbedtls_free( ctx );
+    mbedtls_des3_free((mbedtls_des3_context *) ctx);
+    mbedtls_free(ctx);
 }
 
 static const mbedtls_cipher_base_t des_info = {
@@ -1715,286 +1808,59 @@
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #endif /* MBEDTLS_DES_C */
 
-#if defined(MBEDTLS_BLOWFISH_C)
-
-static int blowfish_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation,
-        const unsigned char *input, unsigned char *output )
-{
-    return mbedtls_blowfish_crypt_ecb( (mbedtls_blowfish_context *) ctx, operation, input,
-                               output );
-}
-
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-static int blowfish_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation,
-        size_t length, unsigned char *iv, const unsigned char *input,
-        unsigned char *output )
-{
-    return mbedtls_blowfish_crypt_cbc( (mbedtls_blowfish_context *) ctx, operation, length, iv,
-                               input, output );
-}
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-
-#if defined(MBEDTLS_CIPHER_MODE_CFB)
-static int blowfish_crypt_cfb64_wrap( void *ctx, mbedtls_operation_t operation,
-        size_t length, size_t *iv_off, unsigned char *iv,
-        const unsigned char *input, unsigned char *output )
-{
-    return mbedtls_blowfish_crypt_cfb64( (mbedtls_blowfish_context *) ctx, operation, length,
-                                 iv_off, iv, input, output );
-}
-#endif /* MBEDTLS_CIPHER_MODE_CFB */
-
-#if defined(MBEDTLS_CIPHER_MODE_CTR)
-static int blowfish_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off,
-        unsigned char *nonce_counter, unsigned char *stream_block,
-        const unsigned char *input, unsigned char *output )
-{
-    return mbedtls_blowfish_crypt_ctr( (mbedtls_blowfish_context *) ctx, length, nc_off,
-                               nonce_counter, stream_block, input, output );
-}
-#endif /* MBEDTLS_CIPHER_MODE_CTR */
-
-static int blowfish_setkey_wrap( void *ctx, const unsigned char *key,
-                                 unsigned int key_bitlen )
-{
-    return mbedtls_blowfish_setkey( (mbedtls_blowfish_context *) ctx, key, key_bitlen );
-}
-
-static void * blowfish_ctx_alloc( void )
-{
-    mbedtls_blowfish_context *ctx;
-    ctx = mbedtls_calloc( 1, sizeof( mbedtls_blowfish_context ) );
-
-    if( ctx == NULL )
-        return( NULL );
-
-    mbedtls_blowfish_init( ctx );
-
-    return( ctx );
-}
-
-static void blowfish_ctx_clone( void *dst, const void *src )
-{
-    memcpy( dst, src, sizeof( mbedtls_blowfish_context ) );
-}
-
-static void blowfish_ctx_free( void *ctx )
-{
-    mbedtls_blowfish_free( (mbedtls_blowfish_context *) ctx );
-    mbedtls_free( ctx );
-}
-
-static const mbedtls_cipher_base_t blowfish_info = {
-    MBEDTLS_CIPHER_ID_BLOWFISH,
-    blowfish_crypt_ecb_wrap,
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-    blowfish_crypt_cbc_wrap,
-#endif
-#if defined(MBEDTLS_CIPHER_MODE_CFB)
-    blowfish_crypt_cfb64_wrap,
-#endif
-#if defined(MBEDTLS_CIPHER_MODE_OFB)
-    NULL,
-#endif
-#if defined(MBEDTLS_CIPHER_MODE_CTR)
-    blowfish_crypt_ctr_wrap,
-#endif
-#if defined(MBEDTLS_CIPHER_MODE_XTS)
-    NULL,
-#endif
-#if defined(MBEDTLS_CIPHER_MODE_STREAM)
-    NULL,
-#endif
-    blowfish_setkey_wrap,
-    blowfish_setkey_wrap,
-    blowfish_ctx_alloc,
-    blowfish_ctx_clone,
-    blowfish_ctx_free
-};
-
-static const mbedtls_cipher_info_t blowfish_ecb_info = {
-    MBEDTLS_CIPHER_BLOWFISH_ECB,
-    MBEDTLS_MODE_ECB,
-    128,
-    "BLOWFISH-ECB",
-    0,
-    MBEDTLS_CIPHER_VARIABLE_KEY_LEN,
-    8,
-    &blowfish_info
-};
-
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-static const mbedtls_cipher_info_t blowfish_cbc_info = {
-    MBEDTLS_CIPHER_BLOWFISH_CBC,
-    MBEDTLS_MODE_CBC,
-    128,
-    "BLOWFISH-CBC",
-    8,
-    MBEDTLS_CIPHER_VARIABLE_KEY_LEN,
-    8,
-    &blowfish_info
-};
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-
-#if defined(MBEDTLS_CIPHER_MODE_CFB)
-static const mbedtls_cipher_info_t blowfish_cfb64_info = {
-    MBEDTLS_CIPHER_BLOWFISH_CFB64,
-    MBEDTLS_MODE_CFB,
-    128,
-    "BLOWFISH-CFB64",
-    8,
-    MBEDTLS_CIPHER_VARIABLE_KEY_LEN,
-    8,
-    &blowfish_info
-};
-#endif /* MBEDTLS_CIPHER_MODE_CFB */
-
-#if defined(MBEDTLS_CIPHER_MODE_CTR)
-static const mbedtls_cipher_info_t blowfish_ctr_info = {
-    MBEDTLS_CIPHER_BLOWFISH_CTR,
-    MBEDTLS_MODE_CTR,
-    128,
-    "BLOWFISH-CTR",
-    8,
-    MBEDTLS_CIPHER_VARIABLE_KEY_LEN,
-    8,
-    &blowfish_info
-};
-#endif /* MBEDTLS_CIPHER_MODE_CTR */
-#endif /* MBEDTLS_BLOWFISH_C */
-
-#if defined(MBEDTLS_ARC4_C)
-static int arc4_crypt_stream_wrap( void *ctx, size_t length,
-                                   const unsigned char *input,
-                                   unsigned char *output )
-{
-    return( mbedtls_arc4_crypt( (mbedtls_arc4_context *) ctx, length, input, output ) );
-}
-
-static int arc4_setkey_wrap( void *ctx, const unsigned char *key,
-                             unsigned int key_bitlen )
-{
-    /* we get key_bitlen in bits, arc4 expects it in bytes */
-    if( key_bitlen % 8 != 0 )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
-
-    mbedtls_arc4_setup( (mbedtls_arc4_context *) ctx, key, key_bitlen / 8 );
-    return( 0 );
-}
-
-static void * arc4_ctx_alloc( void )
-{
-    mbedtls_arc4_context *ctx;
-    ctx = mbedtls_calloc( 1, sizeof( mbedtls_arc4_context ) );
-
-    if( ctx == NULL )
-        return( NULL );
-
-    mbedtls_arc4_init( ctx );
-
-    return( ctx );
-}
-
-static void arc4_ctx_clone( void *dst, const void *src )
-{
-    memcpy( dst, src, sizeof( mbedtls_arc4_context ) );
-}
-
-static void arc4_ctx_free( void *ctx )
-{
-    mbedtls_arc4_free( (mbedtls_arc4_context *) ctx );
-    mbedtls_free( ctx );
-}
-
-static const mbedtls_cipher_base_t arc4_base_info = {
-    MBEDTLS_CIPHER_ID_ARC4,
-    NULL,
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-    NULL,
-#endif
-#if defined(MBEDTLS_CIPHER_MODE_CFB)
-    NULL,
-#endif
-#if defined(MBEDTLS_CIPHER_MODE_OFB)
-    NULL,
-#endif
-#if defined(MBEDTLS_CIPHER_MODE_CTR)
-    NULL,
-#endif
-#if defined(MBEDTLS_CIPHER_MODE_XTS)
-    NULL,
-#endif
-#if defined(MBEDTLS_CIPHER_MODE_STREAM)
-    arc4_crypt_stream_wrap,
-#endif
-    arc4_setkey_wrap,
-    arc4_setkey_wrap,
-    arc4_ctx_alloc,
-    arc4_ctx_clone,
-    arc4_ctx_free
-};
-
-static const mbedtls_cipher_info_t arc4_128_info = {
-    MBEDTLS_CIPHER_ARC4_128,
-    MBEDTLS_MODE_STREAM,
-    128,
-    "ARC4-128",
-    0,
-    0,
-    1,
-    &arc4_base_info
-};
-#endif /* MBEDTLS_ARC4_C */
-
 #if defined(MBEDTLS_CHACHA20_C)
 
-static int chacha20_setkey_wrap( void *ctx, const unsigned char *key,
-                                 unsigned int key_bitlen )
+static int chacha20_setkey_wrap(void *ctx, const unsigned char *key,
+                                unsigned int key_bitlen)
 {
-    if( key_bitlen != 256U )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (key_bitlen != 256U) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
-    if ( 0 != mbedtls_chacha20_setkey( (mbedtls_chacha20_context*)ctx, key ) )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (0 != mbedtls_chacha20_setkey((mbedtls_chacha20_context *) ctx, key)) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
-    return( 0 );
+    return 0;
 }
 
-static int chacha20_stream_wrap( void *ctx,  size_t length,
-                                 const unsigned char *input,
-                                 unsigned char *output )
+static int chacha20_stream_wrap(void *ctx,  size_t length,
+                                const unsigned char *input,
+                                unsigned char *output)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    ret = mbedtls_chacha20_update( ctx, length, input, output );
-    if( ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    ret = mbedtls_chacha20_update(ctx, length, input, output);
+    if (ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
-    return( ret );
+    return ret;
 }
 
-static void * chacha20_ctx_alloc( void )
+static void *chacha20_ctx_alloc(void)
 {
     mbedtls_chacha20_context *ctx;
-    ctx = mbedtls_calloc( 1, sizeof( mbedtls_chacha20_context ) );
+    ctx = mbedtls_calloc(1, sizeof(mbedtls_chacha20_context));
 
-    if( ctx == NULL )
-        return( NULL );
+    if (ctx == NULL) {
+        return NULL;
+    }
 
-    mbedtls_chacha20_init( ctx );
+    mbedtls_chacha20_init(ctx);
 
-    return( ctx );
+    return ctx;
 }
 
-static void chacha20_ctx_clone( void *dst, const void *src )
+static void chacha20_ctx_clone(void *dst, const void *src)
 {
-    memcpy( dst, src, sizeof( mbedtls_chacha20_context ) );
+    memcpy(dst, src, sizeof(mbedtls_chacha20_context));
 }
 
-static void chacha20_ctx_free( void *ctx )
+static void chacha20_ctx_free(void *ctx)
 {
-    mbedtls_chacha20_free( (mbedtls_chacha20_context *) ctx );
-    mbedtls_free( ctx );
+    mbedtls_chacha20_free((mbedtls_chacha20_context *) ctx);
+    mbedtls_free(ctx);
 }
 
 static const mbedtls_cipher_base_t chacha20_base_info = {
@@ -2038,41 +1904,44 @@
 
 #if defined(MBEDTLS_CHACHAPOLY_C)
 
-static int chachapoly_setkey_wrap( void *ctx,
-                                   const unsigned char *key,
-                                   unsigned int key_bitlen )
+static int chachapoly_setkey_wrap(void *ctx,
+                                  const unsigned char *key,
+                                  unsigned int key_bitlen)
 {
-    if( key_bitlen != 256U )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (key_bitlen != 256U) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
-    if ( 0 != mbedtls_chachapoly_setkey( (mbedtls_chachapoly_context*)ctx, key ) )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (0 != mbedtls_chachapoly_setkey((mbedtls_chachapoly_context *) ctx, key)) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
-    return( 0 );
+    return 0;
 }
 
-static void * chachapoly_ctx_alloc( void )
+static void *chachapoly_ctx_alloc(void)
 {
     mbedtls_chachapoly_context *ctx;
-    ctx = mbedtls_calloc( 1, sizeof( mbedtls_chachapoly_context ) );
+    ctx = mbedtls_calloc(1, sizeof(mbedtls_chachapoly_context));
 
-    if( ctx == NULL )
-        return( NULL );
+    if (ctx == NULL) {
+        return NULL;
+    }
 
-    mbedtls_chachapoly_init( ctx );
+    mbedtls_chachapoly_init(ctx);
 
-    return( ctx );
+    return ctx;
 }
 
-static void chachapoly_ctx_clone( void *dst, const void *src )
+static void chachapoly_ctx_clone(void *dst, const void *src)
 {
-    memcpy( dst, src, sizeof( mbedtls_chachapoly_context ) );
+    memcpy(dst, src, sizeof(mbedtls_chachapoly_context));
 }
 
-static void chachapoly_ctx_free( void *ctx )
+static void chachapoly_ctx_free(void *ctx)
 {
-    mbedtls_chachapoly_free( (mbedtls_chachapoly_context *) ctx );
-    mbedtls_free( ctx );
+    mbedtls_chachapoly_free((mbedtls_chachapoly_context *) ctx);
+    mbedtls_free(ctx);
 }
 
 static const mbedtls_cipher_base_t chachapoly_base_info = {
@@ -2115,37 +1984,37 @@
 #endif /* MBEDTLS_CHACHAPOLY_C */
 
 #if defined(MBEDTLS_CIPHER_NULL_CIPHER)
-static int null_crypt_stream( void *ctx, size_t length,
-                              const unsigned char *input,
-                              unsigned char *output )
+static int null_crypt_stream(void *ctx, size_t length,
+                             const unsigned char *input,
+                             unsigned char *output)
 {
     ((void) ctx);
-    memmove( output, input, length );
-    return( 0 );
+    memmove(output, input, length);
+    return 0;
 }
 
-static int null_setkey( void *ctx, const unsigned char *key,
-                        unsigned int key_bitlen )
+static int null_setkey(void *ctx, const unsigned char *key,
+                       unsigned int key_bitlen)
 {
     ((void) ctx);
     ((void) key);
     ((void) key_bitlen);
 
-    return( 0 );
+    return 0;
 }
 
-static void * null_ctx_alloc( void )
+static void *null_ctx_alloc(void)
 {
-    return( (void *) 1 );
+    return (void *) 1;
 }
 
-static void null_ctx_clone( void *dst, const void *src )
+static void null_ctx_clone(void *dst, const void *src)
 {
     ((void) dst);
     ((void) src);
 }
 
-static void null_ctx_free( void *ctx )
+static void null_ctx_free(void *ctx)
 {
     ((void) ctx);
 }
@@ -2191,39 +2060,40 @@
 #endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */
 
 #if defined(MBEDTLS_NIST_KW_C)
-static void *kw_ctx_alloc( void )
+static void *kw_ctx_alloc(void)
 {
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_nist_kw_context ) );
+    void *ctx = mbedtls_calloc(1, sizeof(mbedtls_nist_kw_context));
 
-    if( ctx != NULL )
-        mbedtls_nist_kw_init( (mbedtls_nist_kw_context *) ctx );
+    if (ctx != NULL) {
+        mbedtls_nist_kw_init((mbedtls_nist_kw_context *) ctx);
+    }
 
-    return( ctx );
+    return ctx;
 }
 
-static void kw_ctx_clone( void *dst, const void *src )
+static void kw_ctx_clone(void *dst, const void *src)
 {
-    memcpy( dst, src, sizeof( mbedtls_nist_kw_context ) );
+    memcpy(dst, src, sizeof(mbedtls_nist_kw_context));
 }
 
-static void kw_ctx_free( void *ctx )
+static void kw_ctx_free(void *ctx)
 {
-    mbedtls_nist_kw_free( ctx );
-    mbedtls_free( ctx );
+    mbedtls_nist_kw_free(ctx);
+    mbedtls_free(ctx);
 }
 
-static int kw_aes_setkey_wrap( void *ctx, const unsigned char *key,
-                                unsigned int key_bitlen )
+static int kw_aes_setkey_wrap(void *ctx, const unsigned char *key,
+                              unsigned int key_bitlen)
 {
-    return mbedtls_nist_kw_setkey( (mbedtls_nist_kw_context *) ctx,
-                                   MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 1 );
+    return mbedtls_nist_kw_setkey((mbedtls_nist_kw_context *) ctx,
+                                  MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 1);
 }
 
-static int kw_aes_setkey_unwrap( void *ctx, const unsigned char *key,
-                                unsigned int key_bitlen )
+static int kw_aes_setkey_unwrap(void *ctx, const unsigned char *key,
+                                unsigned int key_bitlen)
 {
-   return mbedtls_nist_kw_setkey( (mbedtls_nist_kw_context *) ctx,
-                                  MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 0 );
+    return mbedtls_nist_kw_setkey((mbedtls_nist_kw_context *) ctx,
+                                  MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 0);
 }
 
 static const mbedtls_cipher_base_t kw_aes_info = {
@@ -2360,26 +2230,12 @@
     { MBEDTLS_CIPHER_AES_128_CCM,          &aes_128_ccm_info },
     { MBEDTLS_CIPHER_AES_192_CCM,          &aes_192_ccm_info },
     { MBEDTLS_CIPHER_AES_256_CCM,          &aes_256_ccm_info },
+    { MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG,          &aes_128_ccm_star_no_tag_info },
+    { MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG,          &aes_192_ccm_star_no_tag_info },
+    { MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG,          &aes_256_ccm_star_no_tag_info },
 #endif
 #endif /* MBEDTLS_AES_C */
 
-#if defined(MBEDTLS_ARC4_C)
-    { MBEDTLS_CIPHER_ARC4_128,             &arc4_128_info },
-#endif
-
-#if defined(MBEDTLS_BLOWFISH_C)
-    { MBEDTLS_CIPHER_BLOWFISH_ECB,         &blowfish_ecb_info },
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-    { MBEDTLS_CIPHER_BLOWFISH_CBC,         &blowfish_cbc_info },
-#endif
-#if defined(MBEDTLS_CIPHER_MODE_CFB)
-    { MBEDTLS_CIPHER_BLOWFISH_CFB64,       &blowfish_cfb64_info },
-#endif
-#if defined(MBEDTLS_CIPHER_MODE_CTR)
-    { MBEDTLS_CIPHER_BLOWFISH_CTR,         &blowfish_ctr_info },
-#endif
-#endif /* MBEDTLS_BLOWFISH_C */
-
 #if defined(MBEDTLS_CAMELLIA_C)
     { MBEDTLS_CIPHER_CAMELLIA_128_ECB,     &camellia_128_ecb_info },
     { MBEDTLS_CIPHER_CAMELLIA_192_ECB,     &camellia_192_ecb_info },
@@ -2408,6 +2264,9 @@
     { MBEDTLS_CIPHER_CAMELLIA_128_CCM,     &camellia_128_ccm_info },
     { MBEDTLS_CIPHER_CAMELLIA_192_CCM,     &camellia_192_ccm_info },
     { MBEDTLS_CIPHER_CAMELLIA_256_CCM,     &camellia_256_ccm_info },
+    { MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG,     &camellia_128_ccm_star_no_tag_info },
+    { MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG,     &camellia_192_ccm_star_no_tag_info },
+    { MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG,     &camellia_256_ccm_star_no_tag_info },
 #endif
 #endif /* MBEDTLS_CAMELLIA_C */
 
@@ -2439,6 +2298,9 @@
     { MBEDTLS_CIPHER_ARIA_128_CCM,     &aria_128_ccm_info },
     { MBEDTLS_CIPHER_ARIA_192_CCM,     &aria_192_ccm_info },
     { MBEDTLS_CIPHER_ARIA_256_CCM,     &aria_256_ccm_info },
+    { MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG,     &aria_128_ccm_star_no_tag_info },
+    { MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG,     &aria_192_ccm_star_no_tag_info },
+    { MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG,     &aria_256_ccm_star_no_tag_info },
 #endif
 #endif /* MBEDTLS_ARIA_C */
 
@@ -2477,8 +2339,8 @@
     { MBEDTLS_CIPHER_NONE, NULL }
 };
 
-#define NUM_CIPHERS ( sizeof(mbedtls_cipher_definitions) /      \
-                      sizeof(mbedtls_cipher_definitions[0]) )
+#define NUM_CIPHERS (sizeof(mbedtls_cipher_definitions) /      \
+                     sizeof(mbedtls_cipher_definitions[0]))
 int mbedtls_cipher_supported[NUM_CIPHERS];
 
 #endif /* MBEDTLS_CIPHER_C */
diff --git a/lib/libmbedtls/mbedtls/library/cipher_wrap.h b/lib/libmbedtls/mbedtls/library/cipher_wrap.h
new file mode 100644
index 0000000..49f5ff1
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/cipher_wrap.h
@@ -0,0 +1,145 @@
+/**
+ * \file cipher_wrap.h
+ *
+ * \brief Cipher wrappers.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ */
+/*
+ *  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_CIPHER_WRAP_H
+#define MBEDTLS_CIPHER_WRAP_H
+
+#include "mbedtls/build_info.h"
+
+#include "mbedtls/cipher.h"
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "psa/crypto.h"
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Base cipher information. The non-mode specific functions and values.
+ */
+struct mbedtls_cipher_base_t {
+    /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */
+    mbedtls_cipher_id_t cipher;
+
+    /** Encrypt using ECB */
+    int (*ecb_func)(void *ctx, mbedtls_operation_t mode,
+                    const unsigned char *input, unsigned char *output);
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    /** Encrypt using CBC */
+    int (*cbc_func)(void *ctx, mbedtls_operation_t mode, size_t length,
+                    unsigned char *iv, const unsigned char *input,
+                    unsigned char *output);
+#endif
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    /** Encrypt using CFB (Full length) */
+    int (*cfb_func)(void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off,
+                    unsigned char *iv, const unsigned char *input,
+                    unsigned char *output);
+#endif
+
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    /** Encrypt using OFB (Full length) */
+    int (*ofb_func)(void *ctx, size_t length, size_t *iv_off,
+                    unsigned char *iv,
+                    const unsigned char *input,
+                    unsigned char *output);
+#endif
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    /** Encrypt using CTR */
+    int (*ctr_func)(void *ctx, size_t length, size_t *nc_off,
+                    unsigned char *nonce_counter, unsigned char *stream_block,
+                    const unsigned char *input, unsigned char *output);
+#endif
+
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    /** Encrypt or decrypt using XTS. */
+    int (*xts_func)(void *ctx, mbedtls_operation_t mode, size_t length,
+                    const unsigned char data_unit[16],
+                    const unsigned char *input, unsigned char *output);
+#endif
+
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+    /** Encrypt using STREAM */
+    int (*stream_func)(void *ctx, size_t length,
+                       const unsigned char *input, unsigned char *output);
+#endif
+
+    /** Set key for encryption purposes */
+    int (*setkey_enc_func)(void *ctx, const unsigned char *key,
+                           unsigned int key_bitlen);
+
+    /** Set key for decryption purposes */
+    int (*setkey_dec_func)(void *ctx, const unsigned char *key,
+                           unsigned int key_bitlen);
+
+    /** Allocate a new context */
+    void * (*ctx_alloc_func)(void);
+
+    /** Clone context **/
+    void (*ctx_clone_func)( void *dst, const void *src );
+
+    /** Free the given context */
+    void (*ctx_free_func)(void *ctx);
+
+};
+
+typedef struct {
+    mbedtls_cipher_type_t type;
+    const mbedtls_cipher_info_t *info;
+} mbedtls_cipher_definition_t;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+typedef enum {
+    MBEDTLS_CIPHER_PSA_KEY_UNSET = 0,
+    MBEDTLS_CIPHER_PSA_KEY_OWNED, /* Used for PSA-based cipher contexts which */
+                                  /* use raw key material internally imported */
+                                  /* as a volatile key, and which hence need  */
+                                  /* to destroy that key when the context is  */
+                                  /* freed.                                   */
+    MBEDTLS_CIPHER_PSA_KEY_NOT_OWNED, /* Used for PSA-based cipher contexts   */
+                                      /* which use a key provided by the      */
+                                      /* user, and which hence will not be    */
+                                      /* destroyed when the context is freed. */
+} mbedtls_cipher_psa_key_ownership;
+
+typedef struct {
+    psa_algorithm_t alg;
+    mbedtls_svc_key_id_t slot;
+    mbedtls_cipher_psa_key_ownership slot_state;
+} mbedtls_cipher_context_psa;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[];
+
+extern int mbedtls_cipher_supported[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_CIPHER_WRAP_H */
diff --git a/lib/libmbedtls/mbedtls/library/cmac.c b/lib/libmbedtls/mbedtls/library/cmac.c
index 8dd7fab..17c7e49 100644
--- a/lib/libmbedtls/mbedtls/library/cmac.c
+++ b/lib/libmbedtls/mbedtls/library/cmac.c
@@ -63,9 +63,9 @@
  * Input and output MUST NOT point to the same buffer
  * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES.
  */
-static int cmac_multiply_by_u( unsigned char *output,
-                               const unsigned char *input,
-                               size_t blocksize )
+static int cmac_multiply_by_u(unsigned char *output,
+                              const unsigned char *input,
+                              size_t blocksize)
 {
     const unsigned char R_128 = 0x87;
     const unsigned char R_64 = 0x1B;
@@ -73,21 +73,15 @@
     unsigned char overflow = 0x00;
     int i;
 
-    if( blocksize == MBEDTLS_AES_BLOCK_SIZE )
-    {
+    if (blocksize == MBEDTLS_AES_BLOCK_SIZE) {
         R_n = R_128;
-    }
-    else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE )
-    {
+    } else if (blocksize == MBEDTLS_DES3_BLOCK_SIZE) {
         R_n = R_64;
-    }
-    else
-    {
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    } else {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
-    for( i = (int)blocksize - 1; i >= 0; i-- )
-    {
+    for (i = (int) blocksize - 1; i >= 0; i--) {
         output[i] = input[i] << 1 | overflow;
         overflow = input[i] >> 7;
     }
@@ -101,14 +95,14 @@
 #pragma warning( push )
 #pragma warning( disable : 4146 )
 #endif
-    mask = - ( input[0] >> 7 );
+    mask = -(input[0] >> 7);
 #if defined(_MSC_VER)
 #pragma warning( pop )
 #endif
 
-    output[ blocksize - 1 ] ^= R_n & mask;
+    output[blocksize - 1] ^= R_n & mask;
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -116,47 +110,41 @@
  *
  * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm
  */
-static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx,
-                                  unsigned char* K1, unsigned char* K2 )
+static int cmac_generate_subkeys(mbedtls_cipher_context_t *ctx,
+                                 unsigned char *K1, unsigned char *K2)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX];
     size_t olen, block_size;
 
-    mbedtls_platform_zeroize( L, sizeof( L ) );
+    mbedtls_platform_zeroize(L, sizeof(L));
 
     block_size = ctx->cipher_info->block_size;
 
     /* Calculate Ek(0) */
-    if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 )
+    if ((ret = mbedtls_cipher_update(ctx, L, block_size, L, &olen)) != 0) {
         goto exit;
+    }
 
     /*
      * Generate K1 and K2
      */
-    if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 )
+    if ((ret = cmac_multiply_by_u(K1, L, block_size)) != 0) {
         goto exit;
+    }
 
-    if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 )
+    if ((ret = cmac_multiply_by_u(K2, K1, block_size)) != 0) {
         goto exit;
+    }
 
 exit:
-    mbedtls_platform_zeroize( L, sizeof( L ) );
+    mbedtls_platform_zeroize(L, sizeof(L));
 
-    return( ret );
+    return ret;
 }
 #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.
@@ -164,21 +152,21 @@
  * We can't use the padding option from the cipher layer, as it only works for
  * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
  */
-static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX],
-                      size_t padded_block_len,
-                      const unsigned char *last_block,
-                      size_t last_block_len )
+static void cmac_pad(unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX],
+                     size_t padded_block_len,
+                     const unsigned char *last_block,
+                     size_t last_block_len)
 {
     size_t j;
 
-    for( j = 0; j < padded_block_len; j++ )
-    {
-        if( j < last_block_len )
+    for (j = 0; j < padded_block_len; j++) {
+        if (j < last_block_len) {
             padded_block[j] = last_block[j];
-        else if( j == last_block_len )
+        } else if (j == last_block_len) {
             padded_block[j] = 0x80;
-        else
+        } else {
             padded_block[j] = 0x00;
+        }
     }
 }
 
@@ -188,40 +176,41 @@
 
     /* Allocated and initialise in the cipher context memory for the CMAC
      * context */
-    cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) );
-    if( cmac_ctx == NULL )
-        return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
+    cmac_ctx = mbedtls_calloc(1, sizeof(mbedtls_cmac_context_t));
+    if (cmac_ctx == NULL)
+        return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
 
     ctx->cmac_ctx = cmac_ctx;
 
-    mbedtls_platform_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) );
+    mbedtls_platform_zeroize(cmac_ctx->state, sizeof(cmac_ctx->state));
     return 0;
 }
 
-int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx,
-                                const unsigned char *key, size_t keybits )
+int mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx,
+                               const unsigned char *key, size_t keybits)
 {
     mbedtls_cipher_type_t type;
     int retval;
 
-    if( ctx == NULL || ctx->cipher_info == NULL || key == NULL )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (ctx == NULL || ctx->cipher_info == NULL || key == NULL) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
-    if( ( retval = mbedtls_cipher_setkey( ctx, key, (int)keybits,
-                                          MBEDTLS_ENCRYPT ) ) != 0 )
-        return( retval );
+    if ((retval = mbedtls_cipher_setkey(ctx, key, (int) keybits,
+                                        MBEDTLS_ENCRYPT)) != 0) {
+        return retval;
+    }
 
     type = ctx->cipher_info->type;
 
-    switch( type )
-    {
+    switch (type) {
         case MBEDTLS_CIPHER_AES_128_ECB:
         case MBEDTLS_CIPHER_AES_192_ECB:
         case MBEDTLS_CIPHER_AES_256_ECB:
         case MBEDTLS_CIPHER_DES_EDE3_ECB:
             break;
         default:
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
     /* Check if cmac ctx had been allocated by mbedtls_cipher_cmac_setup() */
@@ -231,17 +220,18 @@
     return mbedtls_cipher_cmac_setup( ctx );
 }
 
-int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx,
-                                const unsigned char *input, size_t ilen )
+int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx,
+                               const unsigned char *input, size_t ilen)
 {
-    mbedtls_cmac_context_t* cmac_ctx;
+    mbedtls_cmac_context_t *cmac_ctx;
     unsigned char *state;
     int ret = 0;
     size_t n, j, olen, block_size;
 
-    if( ctx == NULL || ctx->cipher_info == NULL || input == NULL ||
-        ctx->cmac_ctx == NULL )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (ctx == NULL || ctx->cipher_info == NULL || input == NULL ||
+        ctx->cmac_ctx == NULL) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
     cmac_ctx = ctx->cmac_ctx;
     block_size = ctx->cipher_info->block_size;
@@ -249,19 +239,17 @@
 
     /* Is there data still to process from the last call, that's greater in
      * size than a block? */
-    if( cmac_ctx->unprocessed_len > 0 &&
-        ilen > block_size - cmac_ctx->unprocessed_len )
-    {
-        memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
-                input,
-                block_size - cmac_ctx->unprocessed_len );
+    if (cmac_ctx->unprocessed_len > 0 &&
+        ilen > block_size - cmac_ctx->unprocessed_len) {
+        memcpy(&cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
+               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 )
-        {
-           goto exit;
+        if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,
+                                         &olen)) != 0) {
+            goto exit;
         }
 
         input += block_size - cmac_ctx->unprocessed_len;
@@ -270,39 +258,38 @@
     }
 
     /* n is the number of blocks including any final partial block */
-    n = ( ilen + block_size - 1 ) / block_size;
+    n = (ilen + block_size - 1) / block_size;
 
     /* Iterate across the input data in block sized chunks, excluding any
      * final partial or complete block */
-    for( j = 1; j < n; j++ )
-    {
-        cmac_xor_block( state, input, state, block_size );
+    for (j = 1; j < n; j++) {
+        mbedtls_xor(state, input, state, block_size);
 
-        if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
-                                           &olen ) ) != 0 )
-           goto exit;
+        if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,
+                                         &olen)) != 0) {
+            goto exit;
+        }
 
         ilen -= block_size;
         input += block_size;
     }
 
     /* If there is data left over that wasn't aligned to a block */
-    if( ilen > 0 )
-    {
-        memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
-                input,
-                ilen );
+    if (ilen > 0) {
+        memcpy(&cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
+               input,
+               ilen);
         cmac_ctx->unprocessed_len += ilen;
     }
 
 exit:
-    return( ret );
+    return ret;
 }
 
-int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx,
-                                unsigned char *output )
+int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx,
+                               unsigned char *output)
 {
-    mbedtls_cmac_context_t* cmac_ctx;
+    mbedtls_cmac_context_t *cmac_ctx;
     unsigned char *state, *last_block;
     unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
     unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
@@ -310,153 +297,153 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t olen, block_size;
 
-    if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||
-        output == NULL )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||
+        output == NULL) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
     cmac_ctx = ctx->cmac_ctx;
     block_size = ctx->cipher_info->block_size;
     state = cmac_ctx->state;
 
-    mbedtls_platform_zeroize( K1, sizeof( K1 ) );
-    mbedtls_platform_zeroize( K2, sizeof( K2 ) );
-    cmac_generate_subkeys( ctx, K1, K2 );
+    mbedtls_platform_zeroize(K1, sizeof(K1));
+    mbedtls_platform_zeroize(K2, sizeof(K2));
+    cmac_generate_subkeys(ctx, K1, K2);
 
     last_block = cmac_ctx->unprocessed_block;
 
     /* Calculate last block */
-    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 );
-    }
-    else
-    {
+    if (cmac_ctx->unprocessed_len < block_size) {
+        cmac_pad(M_last, block_size, last_block, cmac_ctx->unprocessed_len);
+        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 );
-    if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
-                                       &olen ) ) != 0 )
-    {
+    mbedtls_xor(state, M_last, state, block_size);
+    if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,
+                                     &olen)) != 0) {
         goto exit;
     }
 
-    memcpy( output, state, block_size );
+    memcpy(output, state, block_size);
 
 exit:
     /* Wipe the generated keys on the stack, and any other transients to avoid
      * side channel leakage */
-    mbedtls_platform_zeroize( K1, sizeof( K1 ) );
-    mbedtls_platform_zeroize( K2, sizeof( K2 ) );
+    mbedtls_platform_zeroize(K1, sizeof(K1));
+    mbedtls_platform_zeroize(K2, sizeof(K2));
 
     cmac_ctx->unprocessed_len = 0;
-    mbedtls_platform_zeroize( cmac_ctx->unprocessed_block,
-                              sizeof( cmac_ctx->unprocessed_block ) );
+    mbedtls_platform_zeroize(cmac_ctx->unprocessed_block,
+                             sizeof(cmac_ctx->unprocessed_block));
 
-    mbedtls_platform_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX );
-    return( ret );
+    mbedtls_platform_zeroize(state, MBEDTLS_CIPHER_BLKSIZE_MAX);
+    return ret;
 }
 
-int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx )
+int mbedtls_cipher_cmac_reset(mbedtls_cipher_context_t *ctx)
 {
-    mbedtls_cmac_context_t* cmac_ctx;
+    mbedtls_cmac_context_t *cmac_ctx;
 
-    if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
     cmac_ctx = ctx->cmac_ctx;
 
     /* Reset the internal state */
     cmac_ctx->unprocessed_len = 0;
-    mbedtls_platform_zeroize( cmac_ctx->unprocessed_block,
-                              sizeof( cmac_ctx->unprocessed_block ) );
-    mbedtls_platform_zeroize( cmac_ctx->state,
-                              sizeof( cmac_ctx->state ) );
+    mbedtls_platform_zeroize(cmac_ctx->unprocessed_block,
+                             sizeof(cmac_ctx->unprocessed_block));
+    mbedtls_platform_zeroize(cmac_ctx->state,
+                             sizeof(cmac_ctx->state));
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info,
-                         const unsigned char *key, size_t keylen,
-                         const unsigned char *input, size_t ilen,
-                         unsigned char *output )
+int mbedtls_cipher_cmac(const mbedtls_cipher_info_t *cipher_info,
+                        const unsigned char *key, size_t keylen,
+                        const unsigned char *input, size_t ilen,
+                        unsigned char *output)
 {
     mbedtls_cipher_context_t ctx;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( cipher_info == NULL || key == NULL || input == NULL || output == NULL )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (cipher_info == NULL || key == NULL || input == NULL || output == NULL) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
-    mbedtls_cipher_init( &ctx );
+    mbedtls_cipher_init(&ctx);
 
-    if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
+    if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) {
         goto exit;
+    }
 
-    ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen );
-    if( ret != 0 )
+    ret = mbedtls_cipher_cmac_starts(&ctx, key, keylen);
+    if (ret != 0) {
         goto exit;
+    }
 
-    ret = mbedtls_cipher_cmac_update( &ctx, input, ilen );
-    if( ret != 0 )
+    ret = mbedtls_cipher_cmac_update(&ctx, input, ilen);
+    if (ret != 0) {
         goto exit;
+    }
 
-    ret = mbedtls_cipher_cmac_finish( &ctx, output );
+    ret = mbedtls_cipher_cmac_finish(&ctx, output);
 
 exit:
-    mbedtls_cipher_free( &ctx );
+    mbedtls_cipher_free(&ctx);
 
-    return( ret );
+    return ret;
 }
 
 #if defined(MBEDTLS_AES_C)
 /*
  * Implementation of AES-CMAC-PRF-128 defined in RFC 4615
  */
-int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
-                              const unsigned char *input, size_t in_len,
-                              unsigned char output[16] )
+int mbedtls_aes_cmac_prf_128(const unsigned char *key, size_t key_length,
+                             const unsigned char *input, size_t in_len,
+                             unsigned char output[16])
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const mbedtls_cipher_info_t *cipher_info;
     unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE];
     unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE];
 
-    if( key == NULL || input == NULL || output == NULL )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (key == NULL || input == NULL || output == NULL) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
-    cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB );
-    if( cipher_info == NULL )
-    {
+    cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
+    if (cipher_info == NULL) {
         /* Failing at this point must be due to a build issue */
         ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
         goto exit;
     }
 
-    if( key_length == MBEDTLS_AES_BLOCK_SIZE )
-    {
+    if (key_length == MBEDTLS_AES_BLOCK_SIZE) {
         /* Use key as is */
-        memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE );
-    }
-    else
-    {
-        memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE );
+        memcpy(int_key, key, MBEDTLS_AES_BLOCK_SIZE);
+    } else {
+        memset(zero_key, 0, MBEDTLS_AES_BLOCK_SIZE);
 
-        ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key,
-                                   key_length, int_key );
-        if( ret != 0 )
+        ret = mbedtls_cipher_cmac(cipher_info, zero_key, 128, key,
+                                  key_length, int_key);
+        if (ret != 0) {
             goto exit;
+        }
     }
 
-    ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len,
-                               output );
+    ret = mbedtls_cipher_cmac(cipher_info, int_key, 128, input, in_len,
+                              output);
 
 exit:
-    mbedtls_platform_zeroize( int_key, sizeof( int_key ) );
+    mbedtls_platform_zeroize(int_key, sizeof(int_key));
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_AES_C */
 
@@ -517,7 +504,8 @@
         0xf9, 0x0b, 0xc1, 0x1e,     0xe4, 0x6d, 0x51, 0x3b
     }
 };
-static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
+static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] =
+{
     {
         /* Example #1 */
         0xbb, 0x1d, 0x69, 0x29,     0xe9, 0x59, 0x37, 0x28,
@@ -558,7 +546,8 @@
         0x7d, 0xcc, 0x87, 0x3b,     0xa9, 0xb5, 0x45, 0x2c
     }
 };
-static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
+static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] =
+{
     {
         /* Example #1 */
         0xd1, 0x7d, 0xdf, 0x46,     0xad, 0xaa, 0xcd, 0xe5,
@@ -600,7 +589,8 @@
         0x5d, 0x35, 0x33, 0x01,     0x0c, 0x42, 0xa0, 0xd9
     }
 };
-static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
+static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] =
+{
     {
         /* Example #1 */
         0x02, 0x89, 0x62, 0xf6,     0x1b, 0x7b, 0xf8, 0x9e,
@@ -652,7 +642,8 @@
         0x1b, 0xa5, 0x96, 0xf4,     0x7b, 0x11, 0x11, 0xb2
     }
 };
-static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
+static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE]
+    = {
     {
         /* Sample #1 */
         0x79, 0xce, 0x52, 0xa7,     0xf7, 0x86, 0xa9, 0x60
@@ -669,7 +660,7 @@
         /* Sample #4 */
         0x9c, 0xd3, 0x35, 0x80,     0xf9, 0xb6, 0x4d, 0xfb
     }
-};
+    };
 
 /* CMAC-TDES (Generation) - 3 Key Test Data */
 static const unsigned char des3_3key_key[24] = {
@@ -690,7 +681,8 @@
         0x3a, 0xe9, 0xce, 0x72,     0x66, 0x2f, 0x2d, 0x9b
     }
 };
-static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
+static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE]
+    = {
     {
         /* Sample #1 */
         0x7d, 0xb0, 0xd3, 0x7d,     0xf9, 0x36, 0xc5, 0x50
@@ -707,7 +699,7 @@
         /* Sample #4 */
         0x99, 0x42, 0x9b, 0xd0,     0xbF, 0x79, 0x04, 0xe5
     }
-};
+    };
 
 #endif /* MBEDTLS_DES_C */
 
@@ -750,14 +742,14 @@
 };
 #endif /* MBEDTLS_AES_C */
 
-static int cmac_test_subkeys( int verbose,
-                              const char* testname,
-                              const unsigned char* key,
-                              int keybits,
-                              const unsigned char* subkeys,
-                              mbedtls_cipher_type_t cipher_type,
-                              int block_size,
-                              int num_tests )
+static int cmac_test_subkeys(int verbose,
+                             const char *testname,
+                             const unsigned char *key,
+                             int keybits,
+                             const unsigned char *subkeys,
+                             mbedtls_cipher_type_t cipher_type,
+                             int block_size,
+                             int num_tests)
 {
     int i, ret = 0;
     mbedtls_cipher_context_t ctx;
@@ -765,330 +757,321 @@
     unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
     unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
 
-    cipher_info = mbedtls_cipher_info_from_type( cipher_type );
-    if( cipher_info == NULL )
-    {
+    cipher_info = mbedtls_cipher_info_from_type(cipher_type);
+    if (cipher_info == NULL) {
         /* Failing at this point must be due to a build issue */
-        return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
 
-    for( i = 0; i < num_tests; i++ )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "  %s CMAC subkey #%d: ", testname, i + 1 );
+    for (i = 0; i < num_tests; i++) {
+        if (verbose != 0) {
+            mbedtls_printf("  %s CMAC subkey #%d: ", testname, i + 1);
+        }
 
-        mbedtls_cipher_init( &ctx );
+        mbedtls_cipher_init(&ctx);
 
-        if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "test execution failed\n" );
+        if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) {
+            if (verbose != 0) {
+                mbedtls_printf("test execution failed\n");
+            }
 
             goto cleanup;
         }
 
-        if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits,
-                                       MBEDTLS_ENCRYPT ) ) != 0 )
-        {
+        if ((ret = mbedtls_cipher_setkey(&ctx, key, keybits,
+                                         MBEDTLS_ENCRYPT)) != 0) {
             /* When CMAC is implemented by an alternative implementation, or
              * the underlying primitive itself is implemented alternatively,
              * AES-192 may be unavailable. This should not cause the selftest
              * function to fail. */
-            if( ( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||
-                  ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) &&
-                  cipher_type == MBEDTLS_CIPHER_AES_192_ECB ) {
-                if( verbose != 0 )
-                    mbedtls_printf( "skipped\n" );
+            if ((ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||
+                 ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) &&
+                cipher_type == MBEDTLS_CIPHER_AES_192_ECB) {
+                if (verbose != 0) {
+                    mbedtls_printf("skipped\n");
+                }
                 goto next_test;
             }
 
-            if( verbose != 0 )
-                mbedtls_printf( "test execution failed\n" );
+            if (verbose != 0) {
+                mbedtls_printf("test execution failed\n");
+            }
 
             goto cleanup;
         }
 
-        ret = cmac_generate_subkeys( &ctx, K1, K2 );
-        if( ret != 0 )
-        {
-           if( verbose != 0 )
-                mbedtls_printf( "failed\n" );
+        ret = cmac_generate_subkeys(&ctx, K1, K2);
+        if (ret != 0) {
+            if (verbose != 0) {
+                mbedtls_printf("failed\n");
+            }
 
             goto cleanup;
         }
 
-        if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0  ||
-            ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "failed\n" );
+        if ((ret = memcmp(K1, subkeys, block_size)) != 0  ||
+            (ret = memcmp(K2, &subkeys[block_size], block_size)) != 0) {
+            if (verbose != 0) {
+                mbedtls_printf("failed\n");
+            }
 
             goto cleanup;
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
 
 next_test:
-        mbedtls_cipher_free( &ctx );
+        mbedtls_cipher_free(&ctx);
     }
 
     ret = 0;
     goto exit;
 
 cleanup:
-    mbedtls_cipher_free( &ctx );
+    mbedtls_cipher_free(&ctx);
 
 exit:
-    return( ret );
+    return ret;
 }
 
-static int cmac_test_wth_cipher( int verbose,
-                                 const char* testname,
-                                 const unsigned char* key,
-                                 int keybits,
-                                 const unsigned char* messages,
-                                 const unsigned int message_lengths[4],
-                                 const unsigned char* expected_result,
-                                 mbedtls_cipher_type_t cipher_type,
-                                 int block_size,
-                                 int num_tests )
+static int cmac_test_wth_cipher(int verbose,
+                                const char *testname,
+                                const unsigned char *key,
+                                int keybits,
+                                const unsigned char *messages,
+                                const unsigned int message_lengths[4],
+                                const unsigned char *expected_result,
+                                mbedtls_cipher_type_t cipher_type,
+                                int block_size,
+                                int num_tests)
 {
     const mbedtls_cipher_info_t *cipher_info;
     int i, ret = 0;
     unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX];
 
-    cipher_info = mbedtls_cipher_info_from_type( cipher_type );
-    if( cipher_info == NULL )
-    {
+    cipher_info = mbedtls_cipher_info_from_type(cipher_type);
+    if (cipher_info == NULL) {
         /* Failing at this point must be due to a build issue */
         ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
         goto exit;
     }
 
-    for( i = 0; i < num_tests; i++ )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "  %s CMAC #%d: ", testname, i + 1 );
+    for (i = 0; i < num_tests; i++) {
+        if (verbose != 0) {
+            mbedtls_printf("  %s CMAC #%d: ", testname, i + 1);
+        }
 
-        if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages,
-                                         message_lengths[i], output ) ) != 0 )
-        {
+        if ((ret = mbedtls_cipher_cmac(cipher_info, key, keybits, messages,
+                                       message_lengths[i], output)) != 0) {
             /* When CMAC is implemented by an alternative implementation, or
              * the underlying primitive itself is implemented alternatively,
              * AES-192 and/or 3DES may be unavailable. This should not cause
              * the selftest function to fail. */
-            if( ( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||
-                  ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) &&
-                ( cipher_type == MBEDTLS_CIPHER_AES_192_ECB ||
-                  cipher_type == MBEDTLS_CIPHER_DES_EDE3_ECB ) ) {
-                if( verbose != 0 )
-                    mbedtls_printf( "skipped\n" );
+            if ((ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ||
+                 ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) &&
+                (cipher_type == MBEDTLS_CIPHER_AES_192_ECB ||
+                 cipher_type == MBEDTLS_CIPHER_DES_EDE3_ECB)) {
+                if (verbose != 0) {
+                    mbedtls_printf("skipped\n");
+                }
                 continue;
             }
 
-            if( verbose != 0 )
-                mbedtls_printf( "failed\n" );
+            if (verbose != 0) {
+                mbedtls_printf("failed\n");
+            }
             goto exit;
         }
 
-        if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "failed\n" );
+        if ((ret = memcmp(output, &expected_result[i * block_size], block_size)) != 0) {
+            if (verbose != 0) {
+                mbedtls_printf("failed\n");
+            }
             goto exit;
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
     ret = 0;
 
 exit:
-    return( ret );
+    return ret;
 }
 
 #if defined(MBEDTLS_AES_C)
-static int test_aes128_cmac_prf( int verbose )
+static int test_aes128_cmac_prf(int verbose)
 {
     int i;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char output[MBEDTLS_AES_BLOCK_SIZE];
 
-    for( i = 0; i < NB_PRF_TESTS; i++ )
-    {
-        mbedtls_printf( "  AES CMAC 128 PRF #%d: ", i );
-        ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output );
-        if( ret != 0 ||
-            memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 )
-        {
+    for (i = 0; i < NB_PRF_TESTS; i++) {
+        mbedtls_printf("  AES CMAC 128 PRF #%d: ", i);
+        ret = mbedtls_aes_cmac_prf_128(PRFK, PRFKlen[i], PRFM, 20, output);
+        if (ret != 0 ||
+            memcmp(output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE) != 0) {
 
-            if( verbose != 0 )
-                mbedtls_printf( "failed\n" );
+            if (verbose != 0) {
+                mbedtls_printf("failed\n");
+            }
 
-            return( ret );
-        }
-        else if( verbose != 0 )
-        {
-            mbedtls_printf( "passed\n" );
+            return ret;
+        } else if (verbose != 0) {
+            mbedtls_printf("passed\n");
         }
     }
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_AES_C */
 
-int mbedtls_cmac_self_test( int verbose )
+int mbedtls_cmac_self_test(int verbose)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
 #if defined(MBEDTLS_AES_C)
     /* AES-128 */
-    if( ( ret = cmac_test_subkeys( verbose,
-                                   "AES 128",
-                                   aes_128_key,
-                                   128,
-                                   (const unsigned char*)aes_128_subkeys,
-                                   MBEDTLS_CIPHER_AES_128_ECB,
-                                   MBEDTLS_AES_BLOCK_SIZE,
-                                   NB_CMAC_TESTS_PER_KEY ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = cmac_test_subkeys(verbose,
+                                 "AES 128",
+                                 aes_128_key,
+                                 128,
+                                 (const unsigned char *) aes_128_subkeys,
+                                 MBEDTLS_CIPHER_AES_128_ECB,
+                                 MBEDTLS_AES_BLOCK_SIZE,
+                                 NB_CMAC_TESTS_PER_KEY)) != 0) {
+        return ret;
     }
 
-    if( ( ret = cmac_test_wth_cipher( verbose,
-                                      "AES 128",
-                                      aes_128_key,
-                                      128,
-                                      test_message,
-                                      aes_message_lengths,
-                                      (const unsigned char*)aes_128_expected_result,
-                                      MBEDTLS_CIPHER_AES_128_ECB,
-                                      MBEDTLS_AES_BLOCK_SIZE,
-                                      NB_CMAC_TESTS_PER_KEY ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = cmac_test_wth_cipher(verbose,
+                                    "AES 128",
+                                    aes_128_key,
+                                    128,
+                                    test_message,
+                                    aes_message_lengths,
+                                    (const unsigned char *) aes_128_expected_result,
+                                    MBEDTLS_CIPHER_AES_128_ECB,
+                                    MBEDTLS_AES_BLOCK_SIZE,
+                                    NB_CMAC_TESTS_PER_KEY)) != 0) {
+        return ret;
     }
 
     /* AES-192 */
-    if( ( ret = cmac_test_subkeys( verbose,
-                                   "AES 192",
-                                   aes_192_key,
-                                   192,
-                                   (const unsigned char*)aes_192_subkeys,
-                                   MBEDTLS_CIPHER_AES_192_ECB,
-                                   MBEDTLS_AES_BLOCK_SIZE,
-                                   NB_CMAC_TESTS_PER_KEY ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = cmac_test_subkeys(verbose,
+                                 "AES 192",
+                                 aes_192_key,
+                                 192,
+                                 (const unsigned char *) aes_192_subkeys,
+                                 MBEDTLS_CIPHER_AES_192_ECB,
+                                 MBEDTLS_AES_BLOCK_SIZE,
+                                 NB_CMAC_TESTS_PER_KEY)) != 0) {
+        return ret;
     }
 
-    if( ( ret = cmac_test_wth_cipher( verbose,
-                                      "AES 192",
-                                      aes_192_key,
-                                      192,
-                                      test_message,
-                                      aes_message_lengths,
-                                      (const unsigned char*)aes_192_expected_result,
-                                      MBEDTLS_CIPHER_AES_192_ECB,
-                                      MBEDTLS_AES_BLOCK_SIZE,
-                                      NB_CMAC_TESTS_PER_KEY ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = cmac_test_wth_cipher(verbose,
+                                    "AES 192",
+                                    aes_192_key,
+                                    192,
+                                    test_message,
+                                    aes_message_lengths,
+                                    (const unsigned char *) aes_192_expected_result,
+                                    MBEDTLS_CIPHER_AES_192_ECB,
+                                    MBEDTLS_AES_BLOCK_SIZE,
+                                    NB_CMAC_TESTS_PER_KEY)) != 0) {
+        return ret;
     }
 
     /* AES-256 */
-    if( ( ret = cmac_test_subkeys( verbose,
-                                   "AES 256",
-                                   aes_256_key,
-                                   256,
-                                   (const unsigned char*)aes_256_subkeys,
-                                   MBEDTLS_CIPHER_AES_256_ECB,
-                                   MBEDTLS_AES_BLOCK_SIZE,
-                                   NB_CMAC_TESTS_PER_KEY ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = cmac_test_subkeys(verbose,
+                                 "AES 256",
+                                 aes_256_key,
+                                 256,
+                                 (const unsigned char *) aes_256_subkeys,
+                                 MBEDTLS_CIPHER_AES_256_ECB,
+                                 MBEDTLS_AES_BLOCK_SIZE,
+                                 NB_CMAC_TESTS_PER_KEY)) != 0) {
+        return ret;
     }
 
-    if( ( ret = cmac_test_wth_cipher ( verbose,
-                                       "AES 256",
-                                       aes_256_key,
-                                       256,
-                                       test_message,
-                                       aes_message_lengths,
-                                       (const unsigned char*)aes_256_expected_result,
-                                       MBEDTLS_CIPHER_AES_256_ECB,
-                                       MBEDTLS_AES_BLOCK_SIZE,
-                                       NB_CMAC_TESTS_PER_KEY ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = cmac_test_wth_cipher(verbose,
+                                    "AES 256",
+                                    aes_256_key,
+                                    256,
+                                    test_message,
+                                    aes_message_lengths,
+                                    (const unsigned char *) aes_256_expected_result,
+                                    MBEDTLS_CIPHER_AES_256_ECB,
+                                    MBEDTLS_AES_BLOCK_SIZE,
+                                    NB_CMAC_TESTS_PER_KEY)) != 0) {
+        return ret;
     }
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_DES_C)
     /* 3DES 2 key */
-    if( ( ret = cmac_test_subkeys( verbose,
-                                   "3DES 2 key",
-                                   des3_2key_key,
-                                   192,
-                                   (const unsigned char*)des3_2key_subkeys,
-                                   MBEDTLS_CIPHER_DES_EDE3_ECB,
-                                   MBEDTLS_DES3_BLOCK_SIZE,
-                                   NB_CMAC_TESTS_PER_KEY ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = cmac_test_subkeys(verbose,
+                                 "3DES 2 key",
+                                 des3_2key_key,
+                                 192,
+                                 (const unsigned char *) des3_2key_subkeys,
+                                 MBEDTLS_CIPHER_DES_EDE3_ECB,
+                                 MBEDTLS_DES3_BLOCK_SIZE,
+                                 NB_CMAC_TESTS_PER_KEY)) != 0) {
+        return ret;
     }
 
-    if( ( ret = cmac_test_wth_cipher( verbose,
-                                      "3DES 2 key",
-                                      des3_2key_key,
-                                      192,
-                                      test_message,
-                                      des3_message_lengths,
-                                      (const unsigned char*)des3_2key_expected_result,
-                                      MBEDTLS_CIPHER_DES_EDE3_ECB,
-                                      MBEDTLS_DES3_BLOCK_SIZE,
-                                      NB_CMAC_TESTS_PER_KEY ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = cmac_test_wth_cipher(verbose,
+                                    "3DES 2 key",
+                                    des3_2key_key,
+                                    192,
+                                    test_message,
+                                    des3_message_lengths,
+                                    (const unsigned char *) des3_2key_expected_result,
+                                    MBEDTLS_CIPHER_DES_EDE3_ECB,
+                                    MBEDTLS_DES3_BLOCK_SIZE,
+                                    NB_CMAC_TESTS_PER_KEY)) != 0) {
+        return ret;
     }
 
     /* 3DES 3 key */
-    if( ( ret = cmac_test_subkeys( verbose,
-                                   "3DES 3 key",
-                                   des3_3key_key,
-                                   192,
-                                   (const unsigned char*)des3_3key_subkeys,
-                                   MBEDTLS_CIPHER_DES_EDE3_ECB,
-                                   MBEDTLS_DES3_BLOCK_SIZE,
-                                   NB_CMAC_TESTS_PER_KEY ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = cmac_test_subkeys(verbose,
+                                 "3DES 3 key",
+                                 des3_3key_key,
+                                 192,
+                                 (const unsigned char *) des3_3key_subkeys,
+                                 MBEDTLS_CIPHER_DES_EDE3_ECB,
+                                 MBEDTLS_DES3_BLOCK_SIZE,
+                                 NB_CMAC_TESTS_PER_KEY)) != 0) {
+        return ret;
     }
 
-    if( ( ret = cmac_test_wth_cipher( verbose,
-                                      "3DES 3 key",
-                                      des3_3key_key,
-                                      192,
-                                      test_message,
-                                      des3_message_lengths,
-                                      (const unsigned char*)des3_3key_expected_result,
-                                      MBEDTLS_CIPHER_DES_EDE3_ECB,
-                                      MBEDTLS_DES3_BLOCK_SIZE,
-                                      NB_CMAC_TESTS_PER_KEY ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = cmac_test_wth_cipher(verbose,
+                                    "3DES 3 key",
+                                    des3_3key_key,
+                                    192,
+                                    test_message,
+                                    des3_message_lengths,
+                                    (const unsigned char *) des3_3key_expected_result,
+                                    MBEDTLS_CIPHER_DES_EDE3_ECB,
+                                    MBEDTLS_DES3_BLOCK_SIZE,
+                                    NB_CMAC_TESTS_PER_KEY)) != 0) {
+        return ret;
     }
 #endif /* MBEDTLS_DES_C */
 
 #if defined(MBEDTLS_AES_C)
-    if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 )
-        return( ret );
+    if ((ret = test_aes128_cmac_prf(verbose)) != 0) {
+        return ret;
+    }
 #endif /* MBEDTLS_AES_C */
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
-    return( 0 );
+    return 0;
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/lib/libmbedtls/mbedtls/library/common.h b/lib/libmbedtls/mbedtls/library/common.h
index c064724..eb159a7 100644
--- a/lib/libmbedtls/mbedtls/library/common.h
+++ b/lib/libmbedtls/mbedtls/library/common.h
@@ -23,13 +23,13 @@
 #ifndef MBEDTLS_LIBRARY_COMMON_H
 #define MBEDTLS_LIBRARY_COMMON_H
 
-#if defined(MBEDTLS_CONFIG_FILE)
-#include MBEDTLS_CONFIG_FILE
-#else
-#include "mbedtls/config.h"
-#endif
+#include "mbedtls/build_info.h"
+#include "alignment.h"
 
+#include <assert.h>
+#include <stddef.h>
 #include <stdint.h>
+#include <stddef.h>
 
 /** Helper to define a function as static except when building invasive tests.
  *
@@ -52,254 +52,116 @@
 #define MBEDTLS_STATIC_TESTABLE static
 #endif
 
-/** 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 ) )
+#if defined(MBEDTLS_TEST_HOOKS)
+extern void (*mbedtls_test_hook_test_fail)(const char *test, int line, const char *file);
+#define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST) \
+    do { \
+        if ((!(TEST)) && ((*mbedtls_test_hook_test_fail) != NULL)) \
+        { \
+            (*mbedtls_test_hook_test_fail)( #TEST, __LINE__, __FILE__); \
+        } \
+    } while (0)
+#else
+#define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST)
+#endif /* defined(MBEDTLS_TEST_HOOKS) */
 
-/**
- * Get the unsigned 32 bits integer corresponding to four bytes in
- * big-endian order (MSB first).
+/** Allow library to access its structs' private members.
  *
- * \param   data    Base address of the memory to get the four bytes from.
- * \param   offset  Offset from \p base of the first and most significant
- *                  byte of the four bytes to build the 32 bits unsigned
- *                  integer from.
+ * Although structs defined in header files are publicly available,
+ * their members are private and should not be accessed by the user.
  */
-#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
+#define MBEDTLS_ALLOW_PRIVATE_ACCESS
 
-/**
- * Put in memory a 32 bits unsigned integer in big-endian order.
+/** Return an offset into a buffer.
  *
- * \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 base where to put the most significant
- *                  byte of the 32 bits unsigned integer \p n.
+ * This is just the addition of an offset to a pointer, except that this
+ * function also accepts an offset of 0 into a buffer whose pointer is null.
+ * (`p + n` has undefined behavior when `p` is null, even when `n == 0`.
+ * A null pointer is a valid buffer pointer when the size is 0, for example
+ * as the result of `malloc(0)` on some platforms.)
+ *
+ * \param p     Pointer to a buffer of at least n bytes.
+ *              This may be \p NULL if \p n is zero.
+ * \param n     An offset in bytes.
+ * \return      Pointer to offset \p n in the buffer \p p.
+ *              Note that this is only a valid pointer if the size of the
+ *              buffer is at least \p n + 1.
  */
-#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 );             \
+static inline unsigned char *mbedtls_buffer_offset(
+    unsigned char *p, size_t n)
+{
+    return p == NULL ? NULL : p + n;
 }
-#endif
 
-/**
- * Get the unsigned 32 bits integer corresponding to four bytes in
- * little-endian order (LSB first).
+/** Return an offset into a read-only buffer.
  *
- * \param   data    Base address of the memory to get the four bytes from.
- * \param   offset  Offset from \p base 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.
+ * Similar to mbedtls_buffer_offset(), but for const pointers.
  *
- * \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 base where to put the least significant
- *                  byte of the 32 bits unsigned integer \p n.
+ * \param p     Pointer to a buffer of at least n bytes.
+ *              This may be \p NULL if \p n is zero.
+ * \param n     An offset in bytes.
+ * \return      Pointer to offset \p n in the buffer \p p.
+ *              Note that this is only a valid pointer if the size of the
+ *              buffer is at least \p n + 1.
  */
-#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 );             \
+static inline const unsigned char *mbedtls_buffer_offset_const(
+    const unsigned char *p, size_t n)
+{
+    return p == NULL ? NULL : p + n;
 }
-#endif
 
 /**
- * Get the unsigned 16 bits integer corresponding to two bytes in
- * little-endian order (LSB 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 two bytes from.
- * \param   offset  Offset from \p base of the first and least significant
- *                  byte of the two bytes to build the 16 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_UINT16_LE
-#define MBEDTLS_GET_UINT16_LE( data, offset )                   \
-    (                                                           \
-          ( (uint16_t) ( data )[( offset )    ]       )         \
-        | ( (uint16_t) ( data )[( offset ) + 1] <<  8 )         \
-    )
+inline void mbedtls_xor(unsigned char *r, const unsigned char *a, const unsigned char *b, size_t n)
+{
+    size_t i = 0;
+#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
+    for (; (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);
+    }
 #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 base 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 );             \
+    for (; i < n; i++) {
+        r[i] = a[i] ^ b[i];
+    }
 }
+
+/* Fix MSVC C99 compatible issue
+ *      MSVC support __func__ from visual studio 2015( 1900 )
+ *      Use MSVC predefine macro to avoid name check fail.
+ */
+#if (defined(_MSC_VER) && (_MSC_VER <= 1900))
+#define /*no-check-names*/ __func__ __FUNCTION__
 #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 base 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]      )          \
-    )
+/* Define `asm` for compilers which don't define it. */
+/* *INDENT-OFF* */
+#ifndef asm
+#define asm __asm__
 #endif
+/* *INDENT-ON* */
 
-/**
- * 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 base where to put the most significant
- *                  byte of the 16 bits unsigned integer \p n.
+/* Always provide a static assert macro, so it can be used unconditionally.
+ * It will expand to nothing on some systems.
+ * Can be used outside functions (but don't add a trailing ';' in that case:
+ * the semicolon is included here to avoid triggering -Wextra-semi when
+ * MBEDTLS_STATIC_ASSERT() expands to nothing).
+ * Can't use the C11-style `defined(static_assert)` on FreeBSD, since it
+ * defines static_assert even with -std=c99, but then complains about it.
  */
-#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 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 base 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 base 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 base 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 base 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 );             \
-}
+#if defined(static_assert) && !defined(__FreeBSD__)
+#define MBEDTLS_STATIC_ASSERT(expr, msg)    static_assert(expr, msg);
+#else
+#define MBEDTLS_STATIC_ASSERT(expr, msg)
 #endif
 
 #endif /* MBEDTLS_LIBRARY_COMMON_H */
diff --git a/lib/libmbedtls/mbedtls/library/constant_time.c b/lib/libmbedtls/mbedtls/library/constant_time.c
index e276d23..552a918 100644
--- a/lib/libmbedtls/mbedtls/library/constant_time.c
+++ b/lib/libmbedtls/mbedtls/library/constant_time.c
@@ -17,7 +17,7 @@
  *  limitations under the License.
  */
 
- /*
+/*
  * The following functions are implemented without using comparison operators, as those
  * might be translated to branches by some compilers on some platforms.
  */
@@ -30,10 +30,11 @@
 
 #if defined(MBEDTLS_BIGNUM_C)
 #include "mbedtls/bignum.h"
+#include "bignum_core.h"
 #endif
 
 #if defined(MBEDTLS_SSL_TLS_C)
-#include "mbedtls/ssl_internal.h"
+#include "ssl_misc.h"
 #endif
 
 #if defined(MBEDTLS_RSA_C)
@@ -45,18 +46,69 @@
 #endif
 
 #include <string.h>
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,    \
+                                                           psa_to_ssl_errors,              \
+                                                           psa_generic_status_to_mbedtls)
+#endif
 
-int mbedtls_ct_memcmp( const void *a,
-                       const void *b,
-                       size_t n )
+/*
+ * Define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS where assembly is present to
+ * perform fast unaligned access to volatile data.
+ *
+ * This is needed because mbedtls_get_unaligned_uintXX etc don't support volatile
+ * memory accesses.
+ *
+ * Some of these definitions could be moved into alignment.h but for now they are
+ * only used here.
+ */
+#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) && defined(MBEDTLS_HAVE_ASM)
+#if defined(__arm__) || defined(__thumb__) || defined(__thumb2__) || defined(__aarch64__)
+#define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS
+#endif
+#endif
+
+#if defined(MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS)
+static inline uint32_t mbedtls_get_unaligned_volatile_uint32(volatile const unsigned char *p)
 {
-    size_t i;
+    /* This is UB, even where it's safe:
+     *    return *((volatile uint32_t*)p);
+     * so instead the same thing is expressed in assembly below.
+     */
+    uint32_t r;
+#if defined(__arm__) || defined(__thumb__) || defined(__thumb2__)
+    asm volatile ("ldr %0, [%1]" : "=r" (r) : "r" (p) :);
+#elif defined(__aarch64__)
+    asm volatile ("ldr %w0, [%1]" : "=r" (r) : "r" (p) :);
+#endif
+    return r;
+}
+#endif /* MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS */
+
+int mbedtls_ct_memcmp(const void *a,
+                      const void *b,
+                      size_t n)
+{
+    size_t i = 0;
+    /*
+     * `A` and `B` are cast to volatile to ensure that the compiler
+     * generates code that always fully reads both buffers.
+     * Otherwise it could generate a test to exit early if `diff` has all
+     * bits set early in the loop.
+     */
     volatile const unsigned char *A = (volatile const unsigned char *) a;
     volatile const unsigned char *B = (volatile const unsigned char *) b;
-    volatile unsigned char diff = 0;
+    uint32_t diff = 0;
 
-    for( i = 0; i < n; i++ )
-    {
+#if defined(MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS)
+    for (; (i + 4) <= n; i += 4) {
+        uint32_t x = mbedtls_get_unaligned_volatile_uint32(A + i);
+        uint32_t y = mbedtls_get_unaligned_volatile_uint32(B + i);
+        diff |= x ^ y;
+    }
+#endif
+
+    for (; i < n; i++) {
         /* Read volatile data in order before computing diff.
          * This avoids IAR compiler warning:
          * 'the order of volatile accesses is undefined ..' */
@@ -64,10 +116,10 @@
         diff |= x ^ y;
     }
 
-    return( (int)diff );
+    return (int) diff;
 }
 
-unsigned mbedtls_ct_uint_mask( unsigned value )
+unsigned mbedtls_ct_uint_mask(unsigned value)
 {
     /* MSVC has a warning about unary minus on unsigned, but this is
      * well-defined and precisely what we want to do here */
@@ -75,15 +127,15 @@
 #pragma warning( push )
 #pragma warning( disable : 4146 )
 #endif
-    return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) );
+    return -((value | -value) >> (sizeof(value) * 8 - 1));
 #if defined(_MSC_VER)
 #pragma warning( pop )
 #endif
 }
 
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
 
-size_t mbedtls_ct_size_mask( size_t value )
+size_t mbedtls_ct_size_mask(size_t value)
 {
     /* MSVC has a warning about unary minus on unsigned integer types,
      * but this is well-defined and precisely what we want to do here. */
@@ -91,17 +143,17 @@
 #pragma warning( push )
 #pragma warning( disable : 4146 )
 #endif
-    return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) );
+    return -((value | -value) >> (sizeof(value) * 8 - 1));
 #if defined(_MSC_VER)
 #pragma warning( pop )
 #endif
 }
 
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
 
 #if defined(MBEDTLS_BIGNUM_C)
 
-mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask( mbedtls_mpi_uint value )
+mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask(mbedtls_mpi_uint value)
 {
     /* MSVC has a warning about unary minus on unsigned, but this is
      * well-defined and precisely what we want to do here */
@@ -109,7 +161,7 @@
 #pragma warning( push )
 #pragma warning( disable : 4146 )
 #endif
-    return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) );
+    return -((value | -value) >> (sizeof(value) * 8 - 1));
 #if defined(_MSC_VER)
 #pragma warning( pop )
 #endif
@@ -131,25 +183,25 @@
  *
  * \return      All-bits-one if \p x is less than \p y, otherwise zero.
  */
-static size_t mbedtls_ct_size_mask_lt( size_t x,
-                                       size_t y )
+static size_t mbedtls_ct_size_mask_lt(size_t x,
+                                      size_t y)
 {
     /* This has the most significant bit set if and only if x < y */
     const size_t sub = x - y;
 
     /* sub1 = (x < y) ? 1 : 0 */
-    const size_t sub1 = sub >> ( sizeof( sub ) * 8 - 1 );
+    const size_t sub1 = sub >> (sizeof(sub) * 8 - 1);
 
     /* mask = (x < y) ? 0xff... : 0x00... */
-    const size_t mask = mbedtls_ct_size_mask( sub1 );
+    const size_t mask = mbedtls_ct_size_mask(sub1);
 
-    return( mask );
+    return mask;
 }
 
-size_t mbedtls_ct_size_mask_ge( size_t x,
-                                size_t y )
+size_t mbedtls_ct_size_mask_ge(size_t x,
+                               size_t y)
 {
-    return( ~mbedtls_ct_size_mask_lt( x, y ) );
+    return ~mbedtls_ct_size_mask_lt(x, y);
 }
 
 #endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
@@ -161,21 +213,21 @@
  * Constant flow with respect to c.
  */
 MBEDTLS_STATIC_TESTABLE
-unsigned char mbedtls_ct_uchar_mask_of_range( unsigned char low,
-                                              unsigned char high,
-                                              unsigned char c )
+unsigned char mbedtls_ct_uchar_mask_of_range(unsigned char low,
+                                             unsigned char high,
+                                             unsigned char c)
 {
     /* low_mask is: 0 if low <= c, 0x...ff if low > c */
-    unsigned low_mask = ( (unsigned) c - low ) >> 8;
+    unsigned low_mask = ((unsigned) c - low) >> 8;
     /* high_mask is: 0 if c <= high, 0x...ff if c > high */
-    unsigned high_mask = ( (unsigned) high - c ) >> 8;
-    return( ~( low_mask | high_mask ) & 0xff );
+    unsigned high_mask = ((unsigned) high - c) >> 8;
+    return ~(low_mask | high_mask) & 0xff;
 }
 
 #endif /* MBEDTLS_BASE64_C */
 
-unsigned mbedtls_ct_size_bool_eq( size_t x,
-                                  size_t y )
+unsigned mbedtls_ct_size_bool_eq(size_t x,
+                                 size_t y)
 {
     /* diff = 0 if x == y, non-zero otherwise */
     const size_t diff = x ^ y;
@@ -188,16 +240,16 @@
 #endif
 
     /* diff_msb's most significant bit is equal to x != y */
-    const size_t diff_msb = ( diff | (size_t) -diff );
+    const size_t diff_msb = (diff | (size_t) -diff);
 
 #if defined(_MSC_VER)
 #pragma warning( pop )
 #endif
 
     /* diff1 = (x != y) ? 1 : 0 */
-    const unsigned diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 );
+    const unsigned diff1 = diff_msb >> (sizeof(diff_msb) * 8 - 1);
 
-    return( 1 ^ diff1 );
+    return 1 ^ diff1;
 }
 
 #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
@@ -213,19 +265,19 @@
  *
  * \return      1 if \p x greater than \p y, otherwise 0.
  */
-static unsigned mbedtls_ct_size_gt( size_t x,
-                                    size_t y )
+static unsigned mbedtls_ct_size_gt(size_t x,
+                                   size_t y)
 {
     /* Return the sign bit (1 for negative) of (y - x). */
-    return( ( y - x ) >> ( sizeof( size_t ) * 8 - 1 ) );
+    return (y - x) >> (sizeof(size_t) * 8 - 1);
 }
 
 #endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
 
 #if defined(MBEDTLS_BIGNUM_C)
 
-unsigned mbedtls_ct_mpi_uint_lt( const mbedtls_mpi_uint x,
-                                 const mbedtls_mpi_uint y )
+unsigned mbedtls_ct_mpi_uint_lt(const mbedtls_mpi_uint x,
+                                const mbedtls_mpi_uint y)
 {
     mbedtls_mpi_uint ret;
     mbedtls_mpi_uint cond;
@@ -233,12 +285,12 @@
     /*
      * Check if the most significant bits (MSB) of the operands are different.
      */
-    cond = ( x ^ y );
+    cond = (x ^ y);
     /*
      * If the MSB are the same then the difference x-y will be negative (and
      * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
      */
-    ret = ( x - y ) & ~cond;
+    ret = (x - y) & ~cond;
     /*
      * If the MSB are different, then the operand with the MSB of 1 is the
      * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
@@ -247,19 +299,19 @@
     ret |= y & cond;
 
 
-    ret = ret >> ( sizeof( mbedtls_mpi_uint ) * 8 - 1 );
+    ret = ret >> (sizeof(mbedtls_mpi_uint) * 8 - 1);
 
     return (unsigned) ret;
 }
 
 #endif /* MBEDTLS_BIGNUM_C */
 
-unsigned mbedtls_ct_uint_if( unsigned condition,
-                             unsigned if1,
-                             unsigned if0 )
+unsigned mbedtls_ct_uint_if(unsigned condition,
+                            unsigned if1,
+                            unsigned if0)
 {
-    unsigned mask = mbedtls_ct_uint_mask( condition );
-    return( ( mask & if1 ) | (~mask & if0 ) );
+    unsigned mask = mbedtls_ct_uint_mask(condition);
+    return (mask & if1) | (~mask & if0);
 }
 
 #if defined(MBEDTLS_BIGNUM_C)
@@ -272,15 +324,15 @@
  * \note if1 and if0 must be either 1 or -1, otherwise the result
  *       is undefined.
  *
- * \param condition     Condition to test.
+ * \param condition     Condition to test; must be either 0 or 1.
  * \param if1           The first sign; must be either +1 or -1.
  * \param if0           The second sign; must be either +1 or -1.
  *
  * \return  \c if1 if \p condition is nonzero, otherwise \c if0.
  * */
-static int mbedtls_ct_cond_select_sign( unsigned char condition,
-                                        int if1,
-                                        int if0 )
+static int mbedtls_ct_cond_select_sign(unsigned char condition,
+                                       int if1,
+                                       int if0)
 {
     /* In order to avoid questions about what we can reasonably assume about
      * the representations of signed integers, move everything to unsigned
@@ -292,16 +344,16 @@
     const unsigned mask = condition << 1;
 
     /* select uif1 or uif0 */
-    unsigned ur = ( uif0 & ~mask ) | ( uif1 & mask );
+    unsigned ur = (uif0 & ~mask) | (uif1 & mask);
 
     /* ur is now 0 or 2, convert back to -1 or +1 */
-    return( (int) ur - 1 );
+    return (int) ur - 1;
 }
 
-void mbedtls_ct_mpi_uint_cond_assign( size_t n,
-                                      mbedtls_mpi_uint *dest,
-                                      const mbedtls_mpi_uint *src,
-                                      unsigned char condition )
+void mbedtls_ct_mpi_uint_cond_assign(size_t n,
+                                     mbedtls_mpi_uint *dest,
+                                     const mbedtls_mpi_uint *src,
+                                     unsigned char condition)
 {
     size_t i;
 
@@ -319,43 +371,44 @@
 #pragma warning( pop )
 #endif
 
-    for( i = 0; i < n; i++ )
-        dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask );
+    for (i = 0; i < n; i++) {
+        dest[i] = (src[i] & mask) | (dest[i] & ~mask);
+    }
 }
 
 #endif /* MBEDTLS_BIGNUM_C */
 
 #if defined(MBEDTLS_BASE64_C)
 
-unsigned char mbedtls_ct_base64_enc_char( unsigned char value )
+unsigned char mbedtls_ct_base64_enc_char(unsigned char value)
 {
     unsigned char digit = 0;
     /* For each range of values, if value is in that range, mask digit with
      * the corresponding value. Since value can only be in a single range,
      * only at most one masking will change digit. */
-    digit |= mbedtls_ct_uchar_mask_of_range(  0, 25, value ) & ( 'A' + value );
-    digit |= mbedtls_ct_uchar_mask_of_range( 26, 51, value ) & ( 'a' + value - 26 );
-    digit |= mbedtls_ct_uchar_mask_of_range( 52, 61, value ) & ( '0' + value - 52 );
-    digit |= mbedtls_ct_uchar_mask_of_range( 62, 62, value ) & '+';
-    digit |= mbedtls_ct_uchar_mask_of_range( 63, 63, value ) & '/';
-    return( digit );
+    digit |= mbedtls_ct_uchar_mask_of_range(0, 25, value) & ('A' + value);
+    digit |= mbedtls_ct_uchar_mask_of_range(26, 51, value) & ('a' + value - 26);
+    digit |= mbedtls_ct_uchar_mask_of_range(52, 61, value) & ('0' + value - 52);
+    digit |= mbedtls_ct_uchar_mask_of_range(62, 62, value) & '+';
+    digit |= mbedtls_ct_uchar_mask_of_range(63, 63, value) & '/';
+    return digit;
 }
 
-signed char mbedtls_ct_base64_dec_value( unsigned char c )
+signed char mbedtls_ct_base64_dec_value(unsigned char c)
 {
     unsigned char val = 0;
     /* For each range of digits, if c is in that range, mask val with
      * the corresponding value. Since c can only be in a single range,
      * only at most one masking will change val. Set val to one plus
      * the desired value so that it stays 0 if c is in none of the ranges. */
-    val |= mbedtls_ct_uchar_mask_of_range( 'A', 'Z', c ) & ( c - 'A' +  0 + 1 );
-    val |= mbedtls_ct_uchar_mask_of_range( 'a', 'z', c ) & ( c - 'a' + 26 + 1 );
-    val |= mbedtls_ct_uchar_mask_of_range( '0', '9', c ) & ( c - '0' + 52 + 1 );
-    val |= mbedtls_ct_uchar_mask_of_range( '+', '+', c ) & ( c - '+' + 62 + 1 );
-    val |= mbedtls_ct_uchar_mask_of_range( '/', '/', c ) & ( c - '/' + 63 + 1 );
+    val |= mbedtls_ct_uchar_mask_of_range('A', 'Z', c) & (c - 'A' +  0 + 1);
+    val |= mbedtls_ct_uchar_mask_of_range('a', 'z', c) & (c - 'a' + 26 + 1);
+    val |= mbedtls_ct_uchar_mask_of_range('0', '9', c) & (c - '0' + 52 + 1);
+    val |= mbedtls_ct_uchar_mask_of_range('+', '+', c) & (c - '+' + 62 + 1);
+    val |= mbedtls_ct_uchar_mask_of_range('/', '/', c) & (c - '/' + 63 + 1);
     /* At this point, val is 0 if c is an invalid digit and v+1 if c is
      * a digit with the value v. */
-    return( val - 1 );
+    return val - 1;
 }
 
 #endif /* MBEDTLS_BASE64_C */
@@ -378,73 +431,214 @@
  * \param total     Total size of the buffer.
  * \param offset    Offset from which to copy \p total - \p offset bytes.
  */
-static void mbedtls_ct_mem_move_to_left( void *start,
-                                         size_t total,
-                                         size_t offset )
+static void mbedtls_ct_mem_move_to_left(void *start,
+                                        size_t total,
+                                        size_t offset)
 {
     volatile unsigned char *buf = start;
     size_t i, n;
-    if( total == 0 )
+    if (total == 0) {
         return;
-    for( i = 0; i < total; i++ )
-    {
-        unsigned no_op = mbedtls_ct_size_gt( total - offset, i );
+    }
+    for (i = 0; i < total; i++) {
+        unsigned no_op = mbedtls_ct_size_gt(total - offset, i);
         /* The first `total - offset` passes are a no-op. The last
          * `offset` passes shift the data one byte to the left and
          * zero out the last byte. */
-        for( n = 0; n < total - 1; n++ )
-        {
+        for (n = 0; n < total - 1; n++) {
             unsigned char current = buf[n];
             unsigned char next = buf[n+1];
-            buf[n] = mbedtls_ct_uint_if( no_op, current, next );
+            buf[n] = mbedtls_ct_uint_if(no_op, current, next);
         }
-        buf[total-1] = mbedtls_ct_uint_if( no_op, buf[total-1], 0 );
+        buf[total-1] = mbedtls_ct_uint_if(no_op, buf[total-1], 0);
     }
 }
 
 #endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
 
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
 
-void mbedtls_ct_memcpy_if_eq( unsigned char *dest,
-                              const unsigned char *src,
-                              size_t len,
-                              size_t c1,
-                              size_t c2 )
+void mbedtls_ct_memcpy_if_eq(unsigned char *dest,
+                             const unsigned char *src,
+                             size_t len,
+                             size_t c1,
+                             size_t c2)
 {
     /* mask = c1 == c2 ? 0xff : 0x00 */
-    const size_t equal = mbedtls_ct_size_bool_eq( c1, c2 );
-    const unsigned char mask = (unsigned char) mbedtls_ct_size_mask( equal );
+    const size_t equal = mbedtls_ct_size_bool_eq(c1, c2);
 
     /* dest[i] = c1 == c2 ? src[i] : dest[i] */
-    for( size_t i = 0; i < len; i++ )
-        dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask );
-}
+    size_t i = 0;
+#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
+    const uint32_t mask32 = (uint32_t) mbedtls_ct_size_mask(equal);
+    const unsigned char mask = (unsigned char) mask32 & 0xff;
 
-void mbedtls_ct_memcpy_offset( unsigned char *dest,
-                               const unsigned char *src,
-                               size_t offset,
-                               size_t offset_min,
-                               size_t offset_max,
-                               size_t len )
-{
-    size_t offsetval;
-
-    for( offsetval = offset_min; offsetval <= offset_max; offsetval++ )
-    {
-        mbedtls_ct_memcpy_if_eq( dest, src + offsetval, len,
-                                 offsetval, offset );
+    for (; (i + 4) <= len; i += 4) {
+        uint32_t a = mbedtls_get_unaligned_uint32(src  + i) &  mask32;
+        uint32_t b = mbedtls_get_unaligned_uint32(dest + i) & ~mask32;
+        mbedtls_put_unaligned_uint32(dest + i, a | b);
+    }
+#else
+    const unsigned char mask = (unsigned char) mbedtls_ct_size_mask(equal);
+#endif /* MBEDTLS_EFFICIENT_UNALIGNED_ACCESS */
+    for (; i < len; i++) {
+        dest[i] = (src[i] & mask) | (dest[i] & ~mask);
     }
 }
 
-int mbedtls_ct_hmac( mbedtls_md_context_t *ctx,
-                     const unsigned char *add_data,
-                     size_t add_data_len,
-                     const unsigned char *data,
-                     size_t data_len_secret,
-                     size_t min_data_len,
-                     size_t max_data_len,
-                     unsigned char *output )
+void mbedtls_ct_memcpy_offset(unsigned char *dest,
+                              const unsigned char *src,
+                              size_t offset,
+                              size_t offset_min,
+                              size_t offset_max,
+                              size_t len)
+{
+    size_t offsetval;
+
+    for (offsetval = offset_min; offsetval <= offset_max; offsetval++) {
+        mbedtls_ct_memcpy_if_eq(dest, src + offsetval, len,
+                                offsetval, offset);
+    }
+}
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+
+#if defined(PSA_WANT_ALG_SHA_384)
+#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_384)
+#elif defined(PSA_WANT_ALG_SHA_256)
+#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_256)
+#else /* See check_config.h */
+#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_1)
+#endif
+
+int mbedtls_ct_hmac(mbedtls_svc_key_id_t key,
+                    psa_algorithm_t mac_alg,
+                    const unsigned char *add_data,
+                    size_t add_data_len,
+                    const unsigned char *data,
+                    size_t data_len_secret,
+                    size_t min_data_len,
+                    size_t max_data_len,
+                    unsigned char *output)
+{
+    /*
+     * This function breaks the HMAC abstraction and uses psa_hash_clone()
+     * extension in order to get constant-flow behaviour.
+     *
+     * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means
+     * concatenation, and okey/ikey are the XOR of the key with some fixed bit
+     * patterns (see RFC 2104, sec. 2).
+     *
+     * We'll first compute ikey/okey, then inner_hash = HASH(ikey + msg) by
+     * hashing up to minlen, then cloning the context, and for each byte up
+     * to maxlen finishing up the hash computation, keeping only the
+     * correct result.
+     *
+     * Then we only need to compute HASH(okey + inner_hash) and we're done.
+     */
+    psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH(mac_alg);
+    const size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
+    unsigned char key_buf[MAX_HASH_BLOCK_LENGTH];
+    const size_t hash_size = PSA_HASH_LENGTH(hash_alg);
+    psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
+    size_t hash_length;
+
+    unsigned char aux_out[PSA_HASH_MAX_SIZE];
+    psa_hash_operation_t aux_operation = PSA_HASH_OPERATION_INIT;
+    size_t offset;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t mac_key_length;
+    size_t i;
+
+#define PSA_CHK(func_call)        \
+    do {                            \
+        status = (func_call);       \
+        if (status != PSA_SUCCESS) \
+        goto cleanup;           \
+    } while (0)
+
+    /* Export MAC key
+     * We assume key length is always exactly the output size
+     * which is never more than the block size, thus we use block_size
+     * as the key buffer size.
+     */
+    PSA_CHK(psa_export_key(key, key_buf, block_size, &mac_key_length));
+
+    /* Calculate ikey */
+    for (i = 0; i < mac_key_length; i++) {
+        key_buf[i] = (unsigned char) (key_buf[i] ^ 0x36);
+    }
+    for (; i < block_size; ++i) {
+        key_buf[i] = 0x36;
+    }
+
+    PSA_CHK(psa_hash_setup(&operation, hash_alg));
+
+    /* Now compute inner_hash = HASH(ikey + msg) */
+    PSA_CHK(psa_hash_update(&operation, key_buf, block_size));
+    PSA_CHK(psa_hash_update(&operation, add_data, add_data_len));
+    PSA_CHK(psa_hash_update(&operation, data, min_data_len));
+
+    /* Fill the hash buffer in advance with something that is
+     * not a valid hash (barring an attack on the hash and
+     * deliberately-crafted input), in case the caller doesn't
+     * check the return status properly. */
+    memset(output, '!', hash_size);
+
+    /* For each possible length, compute the hash up to that point */
+    for (offset = min_data_len; offset <= max_data_len; offset++) {
+        PSA_CHK(psa_hash_clone(&operation, &aux_operation));
+        PSA_CHK(psa_hash_finish(&aux_operation, aux_out,
+                                PSA_HASH_MAX_SIZE, &hash_length));
+        /* Keep only the correct inner_hash in the output buffer */
+        mbedtls_ct_memcpy_if_eq(output, aux_out, hash_size,
+                                offset, data_len_secret);
+
+        if (offset < max_data_len) {
+            PSA_CHK(psa_hash_update(&operation, data + offset, 1));
+        }
+    }
+
+    /* Abort current operation to prepare for final operation */
+    PSA_CHK(psa_hash_abort(&operation));
+
+    /* Calculate okey */
+    for (i = 0; i < mac_key_length; i++) {
+        key_buf[i] = (unsigned char) ((key_buf[i] ^ 0x36) ^ 0x5C);
+    }
+    for (; i < block_size; ++i) {
+        key_buf[i] = 0x5C;
+    }
+
+    /* Now compute HASH(okey + inner_hash) */
+    PSA_CHK(psa_hash_setup(&operation, hash_alg));
+    PSA_CHK(psa_hash_update(&operation, key_buf, block_size));
+    PSA_CHK(psa_hash_update(&operation, output, hash_size));
+    PSA_CHK(psa_hash_finish(&operation, output, hash_size, &hash_length));
+
+#undef PSA_CHK
+
+cleanup:
+    mbedtls_platform_zeroize(key_buf, MAX_HASH_BLOCK_LENGTH);
+    mbedtls_platform_zeroize(aux_out, PSA_HASH_MAX_SIZE);
+
+    psa_hash_abort(&operation);
+    psa_hash_abort(&aux_operation);
+    return PSA_TO_MBEDTLS_ERR(status);
+}
+
+#undef MAX_HASH_BLOCK_LENGTH
+
+#else
+int mbedtls_ct_hmac(mbedtls_md_context_t *ctx,
+                    const unsigned char *add_data,
+                    size_t add_data_len,
+                    const unsigned char *data,
+                    size_t data_len_secret,
+                    size_t min_data_len,
+                    size_t max_data_len,
+                    unsigned char *output)
 {
     /*
      * This function breaks the HMAC abstraction and uses the md_clone()
@@ -460,79 +654,80 @@
      *
      * Then we only need to compute HASH(okey + inner_hash) and we're done.
      */
-    const mbedtls_md_type_t md_alg = mbedtls_md_get_type( ctx->md_info );
-    /* TLS 1.0-1.2 only support SHA-384, SHA-256, SHA-1, MD-5,
+    const mbedtls_md_type_t md_alg = mbedtls_md_get_type(ctx->md_info);
+    /* TLS 1.2 only supports SHA-384, SHA-256, SHA-1, MD-5,
      * all of which have the same block size except SHA-384. */
     const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64;
     const unsigned char * const ikey = ctx->hmac_ctx;
     const unsigned char * const okey = ikey + block_size;
-    const size_t hash_size = mbedtls_md_get_size( ctx->md_info );
+    const size_t hash_size = mbedtls_md_get_size(ctx->md_info);
 
     unsigned char aux_out[MBEDTLS_MD_MAX_SIZE];
     mbedtls_md_context_t aux;
     size_t offset;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    mbedtls_md_init( &aux );
+    mbedtls_md_init(&aux);
 
-#define MD_CHK( func_call ) \
+#define MD_CHK(func_call) \
     do {                    \
         ret = (func_call);  \
-        if( ret != 0 )      \
-            goto cleanup;   \
-    } while( 0 )
+        if (ret != 0)      \
+        goto cleanup;   \
+    } while (0)
 
-    MD_CHK( mbedtls_md_setup( &aux, ctx->md_info, 0 ) );
+    MD_CHK(mbedtls_md_setup(&aux, ctx->md_info, 0));
 
     /* After hmac_start() of hmac_reset(), ikey has already been hashed,
      * so we can start directly with the message */
-    MD_CHK( mbedtls_md_update( ctx, add_data, add_data_len ) );
-    MD_CHK( mbedtls_md_update( ctx, data, min_data_len ) );
+    MD_CHK(mbedtls_md_update(ctx, add_data, add_data_len));
+    MD_CHK(mbedtls_md_update(ctx, data, min_data_len));
 
     /* Fill the hash buffer in advance with something that is
      * not a valid hash (barring an attack on the hash and
      * deliberately-crafted input), in case the caller doesn't
      * check the return status properly. */
-    memset( output, '!', hash_size );
+    memset(output, '!', hash_size);
 
     /* For each possible length, compute the hash up to that point */
-    for( offset = min_data_len; offset <= max_data_len; offset++ )
-    {
-        MD_CHK( mbedtls_md_clone( &aux, ctx ) );
-        MD_CHK( mbedtls_md_finish( &aux, aux_out ) );
+    for (offset = min_data_len; offset <= max_data_len; offset++) {
+        MD_CHK(mbedtls_md_clone(&aux, ctx));
+        MD_CHK(mbedtls_md_finish(&aux, aux_out));
         /* Keep only the correct inner_hash in the output buffer */
-        mbedtls_ct_memcpy_if_eq( output, aux_out, hash_size,
-                                 offset, data_len_secret );
+        mbedtls_ct_memcpy_if_eq(output, aux_out, hash_size,
+                                offset, data_len_secret);
 
-        if( offset < max_data_len )
-            MD_CHK( mbedtls_md_update( ctx, data + offset, 1 ) );
+        if (offset < max_data_len) {
+            MD_CHK(mbedtls_md_update(ctx, data + offset, 1));
+        }
     }
 
     /* The context needs to finish() before it starts() again */
-    MD_CHK( mbedtls_md_finish( ctx, aux_out ) );
+    MD_CHK(mbedtls_md_finish(ctx, aux_out));
 
     /* Now compute HASH(okey + inner_hash) */
-    MD_CHK( mbedtls_md_starts( ctx ) );
-    MD_CHK( mbedtls_md_update( ctx, okey, block_size ) );
-    MD_CHK( mbedtls_md_update( ctx, output, hash_size ) );
-    MD_CHK( mbedtls_md_finish( ctx, output ) );
+    MD_CHK(mbedtls_md_starts(ctx));
+    MD_CHK(mbedtls_md_update(ctx, okey, block_size));
+    MD_CHK(mbedtls_md_update(ctx, output, hash_size));
+    MD_CHK(mbedtls_md_finish(ctx, output));
 
     /* Done, get ready for next time */
-    MD_CHK( mbedtls_md_hmac_reset( ctx ) );
+    MD_CHK(mbedtls_md_hmac_reset(ctx));
 
 #undef MD_CHK
 
 cleanup:
-    mbedtls_md_free( &aux );
-    return( ret );
+    mbedtls_md_free(&aux);
+    return ret;
 }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
 
 #if defined(MBEDTLS_BIGNUM_C)
 
-#define MPI_VALIDATE_RET( cond )                                       \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
+#define MPI_VALIDATE_RET(cond)                                       \
+    MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA)
 
 /*
  * Conditionally assign X = Y, without leaking information
@@ -546,30 +741,29 @@
  */
 __declspec(noinline)
 #endif
-int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X,
-                                  const mbedtls_mpi *Y,
-                                  unsigned char assign )
+int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
+                                 const mbedtls_mpi *Y,
+                                 unsigned char assign)
 {
     int ret = 0;
-    size_t i;
-    mbedtls_mpi_uint limb_mask;
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( Y != NULL );
+    MPI_VALIDATE_RET(X != NULL);
+    MPI_VALIDATE_RET(Y != NULL);
 
     /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
-    limb_mask = mbedtls_ct_mpi_uint_mask( assign );;
+    mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask(assign);
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
 
-    X->s = mbedtls_ct_cond_select_sign( assign, Y->s, X->s );
+    X->s = mbedtls_ct_cond_select_sign(assign, Y->s, X->s);
 
-    mbedtls_ct_mpi_uint_cond_assign( Y->n, X->p, Y->p, assign );
+    mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, assign);
 
-    for( i = Y->n; i < X->n; i++ )
+    for (size_t i = Y->n; i < X->n; i++) {
         X->p[i] &= ~limb_mask;
+    }
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
@@ -578,73 +772,107 @@
  * Here it is not ok to simply swap the pointers, which would lead to
  * different memory access patterns when X and Y are used afterwards.
  */
-int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X,
-                                mbedtls_mpi *Y,
-                                unsigned char swap )
+int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
+                               mbedtls_mpi *Y,
+                               unsigned char swap)
 {
-    int ret, s;
-    size_t i;
-    mbedtls_mpi_uint limb_mask;
-    mbedtls_mpi_uint tmp;
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( Y != NULL );
+    int ret = 0;
+    int s;
+    MPI_VALIDATE_RET(X != NULL);
+    MPI_VALIDATE_RET(Y != NULL);
 
-    if( X == Y )
-        return( 0 );
-
-    /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
-    limb_mask = mbedtls_ct_mpi_uint_mask( swap );
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
-
-    s = X->s;
-    X->s = mbedtls_ct_cond_select_sign( swap, Y->s, X->s );
-    Y->s = mbedtls_ct_cond_select_sign( swap, s, Y->s );
-
-
-    for( i = 0; i < X->n; i++ )
-    {
-        tmp = X->p[i];
-        X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
-        Y->p[i] = ( Y->p[i] & ~limb_mask ) | (     tmp & limb_mask );
+    if (X == Y) {
+        return 0;
     }
 
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
+
+    s = X->s;
+    X->s = mbedtls_ct_cond_select_sign(swap, Y->s, X->s);
+    Y->s = mbedtls_ct_cond_select_sign(swap, s, Y->s);
+
+    mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, swap);
+
 cleanup:
-    return( ret );
+    return ret;
+}
+
+/*
+ * Compare unsigned values in constant time
+ */
+unsigned mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A,
+                                const mbedtls_mpi_uint *B,
+                                size_t limbs)
+{
+    unsigned ret, cond, done;
+
+    /* The value of any of these variables is either 0 or 1 for the rest of
+     * their scope. */
+    ret = cond = done = 0;
+
+    for (size_t i = limbs; i > 0; i--) {
+        /*
+         * If B[i - 1] < A[i - 1] then A < B is false and the result must
+         * remain 0.
+         *
+         * Again even if we can make a decision, we just mark the result and
+         * the fact that we are done and continue looping.
+         */
+        cond = mbedtls_ct_mpi_uint_lt(B[i - 1], A[i - 1]);
+        done |= cond;
+
+        /*
+         * If A[i - 1] < B[i - 1] then A < B is true.
+         *
+         * Again even if we can make a decision, we just mark the result and
+         * the fact that we are done and continue looping.
+         */
+        cond = mbedtls_ct_mpi_uint_lt(A[i - 1], B[i - 1]);
+        ret |= cond & (1 - done);
+        done |= cond;
+    }
+
+    /*
+     * If all the limbs were equal, then the numbers are equal, A < B is false
+     * and leaving the result 0 is correct.
+     */
+
+    return ret;
 }
 
 /*
  * Compare signed values in constant time
  */
-int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X,
-                           const mbedtls_mpi *Y,
-                           unsigned *ret )
+int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
+                          const mbedtls_mpi *Y,
+                          unsigned *ret)
 {
     size_t i;
     /* The value of any of these variables is either 0 or 1 at all times. */
     unsigned cond, done, X_is_negative, Y_is_negative;
 
-    MPI_VALIDATE_RET( X != NULL );
-    MPI_VALIDATE_RET( Y != NULL );
-    MPI_VALIDATE_RET( ret != NULL );
+    MPI_VALIDATE_RET(X != NULL);
+    MPI_VALIDATE_RET(Y != NULL);
+    MPI_VALIDATE_RET(ret != NULL);
 
-    if( X->n != Y->n )
+    if (X->n != Y->n) {
         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
 
     /*
      * Set sign_N to 1 if N >= 0, 0 if N < 0.
      * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
      */
-    X_is_negative = ( X->s & 2 ) >> 1;
-    Y_is_negative = ( Y->s & 2 ) >> 1;
+    X_is_negative = (X->s & 2) >> 1;
+    Y_is_negative = (Y->s & 2) >> 1;
 
     /*
      * If the signs are different, then the positive operand is the bigger.
      * That is if X is negative (X_is_negative == 1), then X < Y is true and it
      * is false if X is positive (X_is_negative == 0).
      */
-    cond = ( X_is_negative ^ Y_is_negative );
+    cond = (X_is_negative ^ Y_is_negative);
     *ret = cond & X_is_negative;
 
     /*
@@ -653,8 +881,7 @@
      */
     done = cond;
 
-    for( i = X->n; i > 0; i-- )
-    {
+    for (i = X->n; i > 0; i--) {
         /*
          * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
          * X and Y are negative.
@@ -662,8 +889,8 @@
          * Again even if we can make a decision, we just mark the result and
          * the fact that we are done and continue looping.
          */
-        cond = mbedtls_ct_mpi_uint_lt( Y->p[i - 1], X->p[i - 1] );
-        *ret |= cond & ( 1 - done ) & X_is_negative;
+        cond = mbedtls_ct_mpi_uint_lt(Y->p[i - 1], X->p[i - 1]);
+        *ret |= cond & (1 - done) & X_is_negative;
         done |= cond;
 
         /*
@@ -673,24 +900,23 @@
          * Again even if we can make a decision, we just mark the result and
          * the fact that we are done and continue looping.
          */
-        cond = mbedtls_ct_mpi_uint_lt( X->p[i - 1], Y->p[i - 1] );
-        *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
+        cond = mbedtls_ct_mpi_uint_lt(X->p[i - 1], Y->p[i - 1]);
+        *ret |= cond & (1 - done) & (1 - X_is_negative);
         done |= cond;
     }
 
-    return( 0 );
+    return 0;
 }
 
 #endif /* MBEDTLS_BIGNUM_C */
 
 #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
 
-int mbedtls_ct_rsaes_pkcs1_v15_unpadding( int mode,
-                                          unsigned char *input,
-                                          size_t ilen,
-                                          unsigned char *output,
-                                          size_t output_max_len,
-                                          size_t *olen )
+int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input,
+                                         size_t ilen,
+                                         unsigned char *output,
+                                         size_t output_max_len,
+                                         size_t *olen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i, plaintext_max_size;
@@ -711,49 +937,31 @@
     size_t plaintext_size = 0;
     unsigned output_too_large;
 
-    plaintext_max_size = ( output_max_len > ilen - 11 ) ? ilen - 11
+    plaintext_max_size = (output_max_len > ilen - 11) ? ilen - 11
                                                         : output_max_len;
 
     /* Check and get padding length in constant time and constant
      * memory trace. The first byte must be 0. */
     bad |= input[0];
 
-    if( mode == MBEDTLS_RSA_PRIVATE )
-    {
-        /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00
-         * where PS must be at least 8 nonzero bytes. */
-        bad |= input[1] ^ MBEDTLS_RSA_CRYPT;
 
-        /* Read the whole buffer. Set pad_done to nonzero if we find
-         * the 0x00 byte and remember the padding length in pad_count. */
-        for( i = 2; i < ilen; i++ )
-        {
-            pad_done  |= ((input[i] | (unsigned char)-input[i]) >> 7) ^ 1;
-            pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1;
-        }
-    }
-    else
-    {
-        /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00
-         * where PS must be at least 8 bytes with the value 0xFF. */
-        bad |= input[1] ^ MBEDTLS_RSA_SIGN;
+    /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00
+     * where PS must be at least 8 nonzero bytes. */
+    bad |= input[1] ^ MBEDTLS_RSA_CRYPT;
 
-        /* Read the whole buffer. Set pad_done to nonzero if we find
-         * the 0x00 byte and remember the padding length in pad_count.
-         * If there's a non-0xff byte in the padding, the padding is bad. */
-        for( i = 2; i < ilen; i++ )
-        {
-            pad_done |= mbedtls_ct_uint_if( input[i], 0, 1 );
-            pad_count += mbedtls_ct_uint_if( pad_done, 0, 1 );
-            bad |= mbedtls_ct_uint_if( pad_done, 0, input[i] ^ 0xFF );
-        }
+    /* Read the whole buffer. Set pad_done to nonzero if we find
+     * the 0x00 byte and remember the padding length in pad_count. */
+    for (i = 2; i < ilen; i++) {
+        pad_done  |= ((input[i] | (unsigned char) -input[i]) >> 7) ^ 1;
+        pad_count += ((pad_done | (unsigned char) -pad_done) >> 7) ^ 1;
     }
 
+
     /* If pad_done is still zero, there's no data, only unfinished padding. */
-    bad |= mbedtls_ct_uint_if( pad_done, 0, 1 );
+    bad |= mbedtls_ct_uint_if(pad_done, 0, 1);
 
     /* There must be at least 8 bytes of padding. */
-    bad |= mbedtls_ct_size_gt( 8, pad_count );
+    bad |= mbedtls_ct_size_gt(8, pad_count);
 
     /* If the padding is valid, set plaintext_size to the number of
      * remaining bytes after stripping the padding. If the padding
@@ -763,24 +971,24 @@
      * validity through timing. RSA keys are small enough that all the
      * size_t values involved fit in unsigned int. */
     plaintext_size = mbedtls_ct_uint_if(
-                        bad, (unsigned) plaintext_max_size,
-                        (unsigned) ( ilen - pad_count - 3 ) );
+        bad, (unsigned) plaintext_max_size,
+        (unsigned) (ilen - pad_count - 3));
 
     /* Set output_too_large to 0 if the plaintext fits in the output
      * buffer and to 1 otherwise. */
-    output_too_large = mbedtls_ct_size_gt( plaintext_size,
-                                           plaintext_max_size );
+    output_too_large = mbedtls_ct_size_gt(plaintext_size,
+                                          plaintext_max_size);
 
     /* Set ret without branches to avoid timing attacks. Return:
      * - INVALID_PADDING if the padding is bad (bad != 0).
      * - OUTPUT_TOO_LARGE if the padding is good but the decrypted
      *   plaintext does not fit in the output buffer.
      * - 0 if the padding is correct. */
-    ret = - (int) mbedtls_ct_uint_if(
-                    bad, - MBEDTLS_ERR_RSA_INVALID_PADDING,
-                    mbedtls_ct_uint_if( output_too_large,
-                                        - MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE,
-                                        0 ) );
+    ret = -(int) mbedtls_ct_uint_if(
+        bad, -MBEDTLS_ERR_RSA_INVALID_PADDING,
+        mbedtls_ct_uint_if(output_too_large,
+                           -MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE,
+                           0));
 
     /* If the padding is bad or the plaintext is too large, zero the
      * data that we're about to copy to the output buffer.
@@ -788,17 +996,18 @@
      * from the same buffer whether the padding is good or not to
      * avoid leaking the padding validity through overall timing or
      * through memory or cache access patterns. */
-    bad = mbedtls_ct_uint_mask( bad | output_too_large );
-    for( i = 11; i < ilen; i++ )
+    bad = mbedtls_ct_uint_mask(bad | output_too_large);
+    for (i = 11; i < ilen; i++) {
         input[i] &= ~bad;
+    }
 
     /* If the plaintext is too large, truncate it to the buffer size.
      * Copy anyway to avoid revealing the length through timing, because
      * revealing the length is as bad as revealing the padding validity
      * for a Bleichenbacher attack. */
-    plaintext_size = mbedtls_ct_uint_if( output_too_large,
-                                         (unsigned) plaintext_max_size,
-                                         (unsigned) plaintext_size );
+    plaintext_size = mbedtls_ct_uint_if(output_too_large,
+                                        (unsigned) plaintext_max_size,
+                                        (unsigned) plaintext_size);
 
     /* Move the plaintext to the leftmost position where it can start in
      * the working buffer, i.e. make it start plaintext_max_size from
@@ -806,9 +1015,9 @@
      * does not depend on the plaintext size. After this move, the
      * starting location of the plaintext is no longer sensitive
      * information. */
-    mbedtls_ct_mem_move_to_left( input + ilen - plaintext_max_size,
-                                 plaintext_max_size,
-                                 plaintext_max_size - plaintext_size );
+    mbedtls_ct_mem_move_to_left(input + ilen - plaintext_max_size,
+                                plaintext_max_size,
+                                plaintext_max_size - plaintext_size);
 
     /* Finally copy the decrypted plaintext plus trailing zeros into the output
      * buffer. If output_max_len is 0, then output may be an invalid pointer
@@ -817,8 +1026,9 @@
      * user-provided output buffer), which is independent from plaintext
      * length, validity of padding, success of the decryption, and other
      * secrets. */
-    if( output_max_len != 0 )
-        memcpy( output, input + ilen - plaintext_max_size, plaintext_max_size );
+    if (output_max_len != 0) {
+        memcpy(output, input + ilen - plaintext_max_size, plaintext_max_size);
+    }
 
     /* Report the amount of data we copied to the output buffer. In case
      * of errors (bad padding or output too large), the value of *olen
@@ -826,7 +1036,7 @@
      * to the good case limits the risks of leaking the padding validity. */
     *olen = plaintext_size;
 
-    return( ret );
+    return ret;
 }
 
 #endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
diff --git a/lib/libmbedtls/mbedtls/library/constant_time_internal.h b/lib/libmbedtls/mbedtls/library/constant_time_internal.h
index a550b38..c4a32c7 100644
--- a/lib/libmbedtls/mbedtls/library/constant_time_internal.h
+++ b/lib/libmbedtls/mbedtls/library/constant_time_internal.h
@@ -27,7 +27,7 @@
 #endif
 
 #if defined(MBEDTLS_SSL_TLS_C)
-#include "mbedtls/ssl_internal.h"
+#include "ssl_misc.h"
 #endif
 
 #include <stddef.h>
@@ -44,9 +44,9 @@
  *
  * \return          Zero if \p value is zero, otherwise all-bits-one.
  */
-unsigned mbedtls_ct_uint_mask( unsigned value );
+unsigned mbedtls_ct_uint_mask(unsigned value);
 
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
 
 /** Turn a value into a mask:
  * - if \p value == 0, return the all-bits 0 mask, aka 0
@@ -59,9 +59,9 @@
  *
  * \return          Zero if \p value is zero, otherwise all-bits-one.
  */
-size_t mbedtls_ct_size_mask( size_t value );
+size_t mbedtls_ct_size_mask(size_t value);
 
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
 
 #if defined(MBEDTLS_BIGNUM_C)
 
@@ -76,7 +76,7 @@
  *
  * \return          Zero if \p value is zero, otherwise all-bits-one.
  */
-mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask( mbedtls_mpi_uint value );
+mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask(mbedtls_mpi_uint value);
 
 #endif /* MBEDTLS_BIGNUM_C */
 
@@ -95,8 +95,8 @@
  * \return      All-bits-one if \p x is greater or equal than \p y,
  *              otherwise zero.
  */
-size_t mbedtls_ct_size_mask_ge( size_t x,
-                                size_t y );
+size_t mbedtls_ct_size_mask_ge(size_t x,
+                               size_t y);
 
 #endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
 
@@ -111,8 +111,8 @@
  *
  * \return      1 if \p x equals to \p y, otherwise 0.
  */
-unsigned mbedtls_ct_size_bool_eq( size_t x,
-                                  size_t y );
+unsigned mbedtls_ct_size_bool_eq(size_t x,
+                                 size_t y);
 
 #if defined(MBEDTLS_BIGNUM_C)
 
@@ -126,9 +126,27 @@
  *
  * \return      1 if \p x is less than \p y, otherwise 0.
  */
-unsigned mbedtls_ct_mpi_uint_lt( const mbedtls_mpi_uint x,
-                                 const mbedtls_mpi_uint y );
+unsigned mbedtls_ct_mpi_uint_lt(const mbedtls_mpi_uint x,
+                                const mbedtls_mpi_uint y);
 
+/**
+ * \brief          Check if one unsigned MPI is less than another in constant
+ *                 time.
+ *
+ * \param A        The left-hand MPI. This must point to an array of limbs
+ *                 with the same allocated length as \p B.
+ * \param B        The right-hand MPI. This must point to an array of limbs
+ *                 with the same allocated length as \p A.
+ * \param limbs    The number of limbs in \p A and \p B.
+ *                 This must not be 0.
+ *
+ * \return         The result of the comparison:
+ *                 \c 1 if \p A is less than \p B.
+ *                 \c 0 if \p A is greater than or equal to \p B.
+ */
+unsigned mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A,
+                                const mbedtls_mpi_uint *B,
+                                size_t limbs);
 #endif /* MBEDTLS_BIGNUM_C */
 
 /** Choose between two integer values without branches.
@@ -142,9 +160,9 @@
  *
  * \return  \c if1 if \p condition is nonzero, otherwise \c if0.
  */
-unsigned mbedtls_ct_uint_if( unsigned condition,
-                             unsigned if1,
-                             unsigned if0 );
+unsigned mbedtls_ct_uint_if(unsigned condition,
+                            unsigned if1,
+                            unsigned if0);
 
 #if defined(MBEDTLS_BIGNUM_C)
 
@@ -160,10 +178,10 @@
  *                      initialized MPI.
  * \param condition     Condition to test, must be 0 or 1.
  */
-void mbedtls_ct_mpi_uint_cond_assign( size_t n,
-                                      mbedtls_mpi_uint *dest,
-                                      const mbedtls_mpi_uint *src,
-                                      unsigned char condition );
+void mbedtls_ct_mpi_uint_cond_assign(size_t n,
+                                     mbedtls_mpi_uint *dest,
+                                     const mbedtls_mpi_uint *src,
+                                     unsigned char condition);
 
 #endif /* MBEDTLS_BIGNUM_C */
 
@@ -178,7 +196,7 @@
  *
  * \return          A base64 digit converted from \p value.
  */
-unsigned char mbedtls_ct_base64_enc_char( unsigned char value );
+unsigned char mbedtls_ct_base64_enc_char(unsigned char value);
 
 /** Given a Base64 digit, return its value.
  *
@@ -192,11 +210,11 @@
  *
  * \return      The value of the base64 digit \p c.
  */
-signed char mbedtls_ct_base64_dec_value( unsigned char c );
+signed char mbedtls_ct_base64_dec_value(unsigned char c);
 
 #endif /* MBEDTLS_BASE64_C */
 
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
 
 /** Conditional memcpy without branches.
  *
@@ -209,10 +227,10 @@
  * \param c1        The first value to analyze in the condition.
  * \param c2        The second value to analyze in the condition.
  */
-void mbedtls_ct_memcpy_if_eq( unsigned char *dest,
-                              const unsigned char *src,
-                              size_t len,
-                              size_t c1, size_t c2 );
+void mbedtls_ct_memcpy_if_eq(unsigned char *dest,
+                             const unsigned char *src,
+                             size_t len,
+                             size_t c1, size_t c2);
 
 /** Copy data from a secret position with constant flow.
  *
@@ -240,12 +258,12 @@
  * \param offset_max    The maximal value of \p offset.
  * \param len           The number of bytes to copy.
  */
-void mbedtls_ct_memcpy_offset( unsigned char *dest,
-                               const unsigned char *src,
-                               size_t offset,
-                               size_t offset_min,
-                               size_t offset_max,
-                               size_t len );
+void mbedtls_ct_memcpy_offset(unsigned char *dest,
+                              const unsigned char *src,
+                              size_t offset,
+                              size_t offset_min,
+                              size_t offset_max,
+                              size_t len);
 
 /** Compute the HMAC of variable-length data with constant flow.
  *
@@ -283,16 +301,28 @@
  * \retval #MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED
  *         The hardware accelerator failed.
  */
-int mbedtls_ct_hmac( mbedtls_md_context_t *ctx,
-                     const unsigned char *add_data,
-                     size_t add_data_len,
-                     const unsigned char *data,
-                     size_t data_len_secret,
-                     size_t min_data_len,
-                     size_t max_data_len,
-                     unsigned char *output );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+int mbedtls_ct_hmac(mbedtls_svc_key_id_t key,
+                    psa_algorithm_t alg,
+                    const unsigned char *add_data,
+                    size_t add_data_len,
+                    const unsigned char *data,
+                    size_t data_len_secret,
+                    size_t min_data_len,
+                    size_t max_data_len,
+                    unsigned char *output);
+#else
+int mbedtls_ct_hmac(mbedtls_md_context_t *ctx,
+                    const unsigned char *add_data,
+                    size_t add_data_len,
+                    const unsigned char *data,
+                    size_t data_len_secret,
+                    size_t min_data_len,
+                    size_t max_data_len,
+                    unsigned char *output);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
 
 #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
 
@@ -305,8 +335,6 @@
  *       is often a situation that an attacker can provoke and leaking which
  *       one is the result is precisely the information the attacker wants.
  *
- * \param mode           The mode of operation. This must be either
- *                       #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated).
  * \param input          The input buffer which is the payload inside PKCS#1v1.5
  *                       encryption padding, called the "encoded message EM"
  *                       by the terminology.
@@ -324,12 +352,11 @@
  * \return      #MBEDTLS_ERR_RSA_INVALID_PADDING
  *              The input doesn't contain properly formatted padding.
  */
-int mbedtls_ct_rsaes_pkcs1_v15_unpadding( int mode,
-                                          unsigned char *input,
-                                          size_t ilen,
-                                          unsigned char *output,
-                                          size_t output_max_len,
-                                          size_t *olen );
+int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input,
+                                         size_t ilen,
+                                         unsigned char *output,
+                                         size_t output_max_len,
+                                         size_t *olen);
 
 #endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
 
diff --git a/lib/libmbedtls/mbedtls/library/constant_time_invasive.h b/lib/libmbedtls/mbedtls/library/constant_time_invasive.h
index 4620ca1..c176b28 100644
--- a/lib/libmbedtls/mbedtls/library/constant_time_invasive.h
+++ b/lib/libmbedtls/mbedtls/library/constant_time_invasive.h
@@ -42,9 +42,9 @@
  *
  * \return      All-bits-one if \p low <= \p c <= \p high, otherwise zero.
  */
-unsigned char mbedtls_ct_uchar_mask_of_range( unsigned char low,
-                                              unsigned char high,
-                                              unsigned char c );
+unsigned char mbedtls_ct_uchar_mask_of_range(unsigned char low,
+                                             unsigned char high,
+                                             unsigned char c);
 
 #endif /* MBEDTLS_TEST_HOOKS */
 
diff --git a/lib/libmbedtls/mbedtls/library/ctr_drbg.c b/lib/libmbedtls/mbedtls/library/ctr_drbg.c
index a00d66c..acc4208 100644
--- a/lib/libmbedtls/mbedtls/library/ctr_drbg.c
+++ b/lib/libmbedtls/mbedtls/library/ctr_drbg.c
@@ -36,21 +36,15 @@
 #include <stdio.h>
 #endif
 
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
 
 /*
  * CTR_DRBG context initialization
  */
-void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
+void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx)
 {
-    memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
+    memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context));
+    mbedtls_aes_init(&ctx->aes_ctx);
     /* Indicate that the entropy nonce length is not set explicitly.
      * See mbedtls_ctr_drbg_set_nonce_len(). */
     ctx->reseed_counter = -1;
@@ -62,68 +56,72 @@
  *  This function resets CTR_DRBG context to the state immediately
  *  after initial call of mbedtls_ctr_drbg_init().
  */
-void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
+void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
 #if defined(MBEDTLS_THREADING_C)
     /* The mutex is initialized iff f_entropy is set. */
-    if( ctx->f_entropy != NULL )
-        mbedtls_mutex_free( &ctx->mutex );
+    if (ctx->f_entropy != NULL) {
+        mbedtls_mutex_free(&ctx->mutex);
+    }
 #endif
-    mbedtls_aes_free( &ctx->aes_ctx );
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
+    mbedtls_aes_free(&ctx->aes_ctx);
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context));
     ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
     ctx->reseed_counter = -1;
 }
 
-void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
-                                                 int resistance )
+void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx,
+                                                int resistance)
 {
     ctx->prediction_resistance = resistance;
 }
 
-void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
-                                       size_t len )
+void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx,
+                                      size_t len)
 {
     ctx->entropy_len = len;
 }
 
-int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
-                                    size_t len )
+int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx,
+                                   size_t len)
 {
     /* If mbedtls_ctr_drbg_seed() has already been called, it's
      * too late. Return the error code that's closest to making sense. */
-    if( ctx->f_entropy != NULL )
-        return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
+    if (ctx->f_entropy != NULL) {
+        return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
+    }
 
-    if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
-        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
-#if SIZE_MAX > INT_MAX
+    if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
+        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
+    }
+
     /* This shouldn't be an issue because
      * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
      * configuration, but make sure anyway. */
-    if( len > INT_MAX )
-        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
-#endif
+    if (len > INT_MAX) {
+        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
+    }
 
     /* For backward compatibility with Mbed TLS <= 2.19, store the
      * entropy nonce length in a field that already exists, but isn't
      * used until after the initial seeding. */
     /* Due to the capping of len above, the value fits in an int. */
     ctx->reseed_counter = (int) len;
-    return( 0 );
+    return 0;
 }
 
-void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
-                                           int interval )
+void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx,
+                                          int interval)
 {
     ctx->reseed_interval = interval;
 }
 
-static int block_cipher_df( unsigned char *output,
-                            const unsigned char *data, size_t data_len )
+static int block_cipher_df(unsigned char *output,
+                           const unsigned char *data, size_t data_len)
 {
     unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
                       MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
@@ -137,12 +135,13 @@
     int i, j;
     size_t buf_len, use_len;
 
-    if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
-        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+    if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
+        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
+    }
 
-    memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
-            MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
-    mbedtls_aes_init( &aes_ctx );
+    memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
+           MBEDTLS_CTR_DRBG_BLOCKSIZE + 16);
+    mbedtls_aes_init(&aes_ctx);
 
     /*
      * Construct IV (16 bytes) and S in buffer
@@ -152,48 +151,44 @@
      *     (Total is padded to a multiple of 16-bytes with zeroes)
      */
     p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
-    MBEDTLS_PUT_UINT32_BE( data_len, p, 0);
+    MBEDTLS_PUT_UINT32_BE(data_len, p, 0);
     p += 4 + 3;
     *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
-    memcpy( p, data, data_len );
+    memcpy(p, data, data_len);
     p[data_len] = 0x80;
 
     buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
 
-    for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
+    for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) {
         key[i] = i;
+    }
 
-    if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
-                                        MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
-    {
+    if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key,
+                                      MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
         goto exit;
     }
 
     /*
      * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
      */
-    for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
-    {
+    for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
         p = buf;
-        memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
+        memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE);
         use_len = buf_len;
 
-        while( use_len > 0 )
-        {
-            for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
-                chain[i] ^= p[i];
+        while (use_len > 0) {
+            mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE);
             p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
-            use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
+            use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ?
                        MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
 
-            if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
-                                               chain, chain ) ) != 0 )
-            {
+            if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
+                                             chain, chain)) != 0) {
                 goto exit;
             }
         }
 
-        memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
+        memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE);
 
         /*
          * Update IV
@@ -204,42 +199,38 @@
     /*
      * Do final encryption with reduced data
      */
-    if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
-                                        MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
-    {
+    if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,
+                                      MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
         goto exit;
     }
     iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
     p = output;
 
-    for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
-    {
-        if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
-                                           iv, iv ) ) != 0 )
-        {
+    for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
+        if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
+                                         iv, iv)) != 0) {
             goto exit;
         }
-        memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
+        memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE);
         p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
     }
 exit:
-    mbedtls_aes_free( &aes_ctx );
+    mbedtls_aes_free(&aes_ctx);
     /*
-    * tidy up the stack
-    */
-    mbedtls_platform_zeroize( buf, sizeof( buf ) );
-    mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
-    mbedtls_platform_zeroize( key, sizeof( key ) );
-    mbedtls_platform_zeroize( chain, sizeof( chain ) );
-    if( 0 != ret )
-    {
+     * tidy up the stack
+     */
+    mbedtls_platform_zeroize(buf, sizeof(buf));
+    mbedtls_platform_zeroize(tmp, sizeof(tmp));
+    mbedtls_platform_zeroize(key, sizeof(key));
+    mbedtls_platform_zeroize(chain, sizeof(chain));
+    if (0 != ret) {
         /*
-        * wipe partial seed from memory
-        */
-        mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
+         * wipe partial seed from memory
+         */
+        mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN);
     }
 
-    return( ret );
+    return ret;
 }
 
 /* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
@@ -250,54 +241,54 @@
  *   ctx->aes_ctx = Key
  *   ctx->counter = V
  */
-static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
-                          const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
+static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
+                                    const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN])
 {
     unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
     unsigned char *p = tmp;
     int i, j;
     int ret = 0;
 
-    memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
+    memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
 
-    for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
-    {
+    for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
         /*
          * Increase counter
          */
-        for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
-            if( ++ctx->counter[i - 1] != 0 )
+        for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
+            if (++ctx->counter[i - 1] != 0) {
                 break;
+            }
+        }
 
         /*
          * Crypt counter block
          */
-        if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
-                                           ctx->counter, p ) ) != 0 )
-        {
+        if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
+                                         ctx->counter, p)) != 0) {
             goto exit;
         }
 
         p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
     }
 
-    for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
+    for (i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++) {
         tmp[i] ^= data[i];
+    }
 
     /*
      * Update key and counter
      */
-    if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
-                                        MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
-    {
+    if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,
+                                      MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
         goto exit;
     }
-    memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
-            MBEDTLS_CTR_DRBG_BLOCKSIZE );
+    memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
+           MBEDTLS_CTR_DRBG_BLOCKSIZE);
 
 exit:
-    mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
-    return( ret );
+    mbedtls_platform_zeroize(tmp, sizeof(tmp));
+    return ret;
 }
 
 /* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
@@ -312,39 +303,29 @@
  * and with outputs
  *   ctx = initial_working_state
  */
-int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
-                                 const unsigned char *additional,
-                                 size_t add_len )
+int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,
+                            const unsigned char *additional,
+                            size_t add_len)
 {
     unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( add_len == 0 )
-        return( 0 );
+    if (add_len == 0) {
+        return 0;
+    }
 
-    if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
+    if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
         goto exit;
-    if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
+    }
+    if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
         goto exit;
+    }
 
 exit:
-    mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
-    return( ret );
+    mbedtls_platform_zeroize(add_input, sizeof(add_input));
+    return ret;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
-                              const unsigned char *additional,
-                              size_t add_len )
-{
-    /* MAX_INPUT would be more logical here, but we have to match
-     * block_cipher_df()'s limits since we can't propagate errors */
-    if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
-        add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
-    (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
-}
-#endif /* MBEDTLS_DEPRECATED_REMOVED */
-
 /* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
  * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
  * implements
@@ -358,66 +339,67 @@
  * and with output
  *   ctx contains new_working_state
  */
-static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
-                                             const unsigned char *additional,
-                                             size_t len,
-                                             size_t nonce_len )
+static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx,
+                                            const unsigned char *additional,
+                                            size_t len,
+                                            size_t nonce_len)
 {
     unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
     size_t seedlen = 0;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
-        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
-    if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
-        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
-    if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
-        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+    if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) {
+        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
+    }
+    if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) {
+        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
+    }
+    if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) {
+        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
+    }
 
-    memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
+    memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT);
 
     /* Gather entropy_len bytes of entropy to seed state. */
-    if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
-    {
-        return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
+    if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) {
+        return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
     }
     seedlen += ctx->entropy_len;
 
     /* Gather entropy for a nonce if requested. */
-    if( nonce_len != 0 )
-    {
-        if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) )
-        {
-            return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
+    if (nonce_len != 0) {
+        if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) {
+            return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
         }
         seedlen += nonce_len;
     }
 
     /* Add additional data if provided. */
-    if( additional != NULL && len != 0 )
-    {
-        memcpy( seed + seedlen, additional, len );
+    if (additional != NULL && len != 0) {
+        memcpy(seed + seedlen, additional, len);
         seedlen += len;
     }
 
     /* Reduce to 384 bits. */
-    if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
+    if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) {
         goto exit;
+    }
 
     /* Update state. */
-    if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
+    if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) {
         goto exit;
+    }
     ctx->reseed_counter = 1;
 
 exit:
-    mbedtls_platform_zeroize( seed, sizeof( seed ) );
-    return( ret );
+    mbedtls_platform_zeroize(seed, sizeof(seed));
+    return ret;
 }
 
-int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
-                             const unsigned char *additional, size_t len )
+int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,
+                            const unsigned char *additional, size_t len)
 {
-    return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
+    return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0);
 }
 
 /* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
@@ -425,12 +407,13 @@
  * size and entropy length. If there is enough entropy in the initial
  * call to the entropy function to serve as both the entropy input and
  * the nonce, don't make a second call to get a nonce. */
-static size_t good_nonce_len( size_t entropy_len )
+static size_t good_nonce_len(size_t entropy_len)
 {
-    if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
-        return( 0 );
-    else
-        return( ( entropy_len + 1 ) / 2 );
+    if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) {
+        return 0;
+    } else {
+        return (entropy_len + 1) / 2;
+    }
 }
 
 /* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
@@ -444,52 +427,49 @@
  * and with outputs
  *   ctx = initial_working_state
  */
-int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
-                           int (*f_entropy)(void *, unsigned char *, size_t),
-                           void *p_entropy,
-                           const unsigned char *custom,
-                           size_t len )
+int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,
+                          int (*f_entropy)(void *, unsigned char *, size_t),
+                          void *p_entropy,
+                          const unsigned char *custom,
+                          size_t len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
     size_t nonce_len;
 
-    memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
+    memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE);
 
     /* The mutex is initialized iff f_entropy is set. */
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_init( &ctx->mutex );
+    mbedtls_mutex_init(&ctx->mutex);
 #endif
 
-    mbedtls_aes_init( &ctx->aes_ctx );
-
     ctx->f_entropy = f_entropy;
     ctx->p_entropy = p_entropy;
 
-    if( ctx->entropy_len == 0 )
+    if (ctx->entropy_len == 0) {
         ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
+    }
     /* ctx->reseed_counter contains the desired amount of entropy to
      * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
      * If it's -1, indicating that the entropy nonce length was not set
      * explicitly, use a sufficiently large nonce for security. */
-    nonce_len = ( ctx->reseed_counter >= 0 ?
-                  (size_t) ctx->reseed_counter :
-                  good_nonce_len( ctx->entropy_len ) );
+    nonce_len = (ctx->reseed_counter >= 0 ?
+                 (size_t) ctx->reseed_counter :
+                 good_nonce_len(ctx->entropy_len));
 
     /* Initialize with an empty key. */
-    if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
-                                        MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
+                                      MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
+        return ret;
     }
 
     /* Do the initial seeding. */
-    if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
-                                                  nonce_len ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len,
+                                                nonce_len)) != 0) {
+        return ret;
     }
-    return( 0 );
+    return 0;
 }
 
 /* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
@@ -511,9 +491,9 @@
  *   returned_bits = output[:output_len]
  *   ctx contains new_working_state
  */
-int mbedtls_ctr_drbg_random_with_add( void *p_rng,
-                              unsigned char *output, size_t output_len,
-                              const unsigned char *additional, size_t add_len )
+int mbedtls_ctr_drbg_random_with_add(void *p_rng,
+                                     unsigned char *output, size_t output_len,
+                                     const unsigned char *additional, size_t add_len)
 {
     int ret = 0;
     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
@@ -523,159 +503,169 @@
     int i;
     size_t use_len;
 
-    if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
-        return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
+    if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) {
+        return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG;
+    }
 
-    if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
-        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+    if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) {
+        return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
+    }
 
-    memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
+    memset(add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
 
-    if( ctx->reseed_counter > ctx->reseed_interval ||
-        ctx->prediction_resistance )
-    {
-        if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
-        {
-            return( ret );
+    if (ctx->reseed_counter > ctx->reseed_interval ||
+        ctx->prediction_resistance) {
+        if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) {
+            return ret;
         }
         add_len = 0;
     }
 
-    if( add_len > 0 )
-    {
-        if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
+    if (add_len > 0) {
+        if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
             goto exit;
-        if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
+        }
+        if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
             goto exit;
+        }
     }
 
-    while( output_len > 0 )
-    {
+    while (output_len > 0) {
         /*
          * Increase counter
          */
-        for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
-            if( ++ctx->counter[i - 1] != 0 )
+        for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
+            if (++ctx->counter[i - 1] != 0) {
                 break;
+            }
+        }
 
         /*
          * Crypt counter block
          */
-        if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
-                                           ctx->counter, tmp ) ) != 0 )
-        {
+        if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
+                                         ctx->counter, tmp)) != 0) {
             goto exit;
         }
 
-        use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
+        use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE)
             ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
         /*
          * Copy random block to destination
          */
-        memcpy( p, tmp, use_len );
+        memcpy(p, tmp, use_len);
         p += use_len;
         output_len -= use_len;
     }
 
-    if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
+    if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
         goto exit;
+    }
 
     ctx->reseed_counter++;
 
 exit:
-    mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
-    mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
-    return( ret );
+    mbedtls_platform_zeroize(add_input, sizeof(add_input));
+    mbedtls_platform_zeroize(tmp, sizeof(tmp));
+    return ret;
 }
 
-int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
-                             size_t output_len )
+int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output,
+                            size_t output_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
 
 #if defined(MBEDTLS_THREADING_C)
-    if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
+        return ret;
+    }
 #endif
 
-    ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
+    ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0);
 
 #if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
-        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
+        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
+    }
 #endif
 
-    return( ret );
+    return ret;
 }
 
 #if defined(MBEDTLS_FS_IO)
-int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
-                                      const char *path )
+int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx,
+                                     const char *path)
 {
     int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
     FILE *f;
-    unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
+    unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
 
-    if( ( f = fopen( path, "wb" ) ) == NULL )
-        return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
-
-    if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
-                                         MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
-        goto exit;
-
-    if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
-        MBEDTLS_CTR_DRBG_MAX_INPUT )
-    {
-        ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
+    if ((f = fopen(path, "wb")) == NULL) {
+        return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
     }
-    else
-    {
+
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf(f, NULL);
+
+    if ((ret = mbedtls_ctr_drbg_random(ctx, buf,
+                                       MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) {
+        goto exit;
+    }
+
+    if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) !=
+        MBEDTLS_CTR_DRBG_MAX_INPUT) {
+        ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
+    } else {
         ret = 0;
     }
 
 exit:
-    mbedtls_platform_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize(buf, sizeof(buf));
 
-    fclose( f );
-    return( ret );
+    fclose(f);
+    return ret;
 }
 
-int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
-                                       const char *path )
+int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx,
+                                      const char *path)
 {
     int ret = 0;
     FILE *f = NULL;
     size_t n;
-    unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
+    unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT];
     unsigned char c;
 
-    if( ( f = fopen( path, "rb" ) ) == NULL )
-        return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
+    if ((f = fopen(path, "rb")) == NULL) {
+        return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
+    }
 
-    n = fread( buf, 1, sizeof( buf ), f );
-    if( fread( &c, 1, 1, f ) != 0 )
-    {
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf(f, NULL);
+
+    n = fread(buf, 1, sizeof(buf), f);
+    if (fread(&c, 1, 1, f) != 0) {
         ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
         goto exit;
     }
-    if( n == 0 || ferror( f ) )
-    {
+    if (n == 0 || ferror(f)) {
         ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
         goto exit;
     }
-    fclose( f );
+    fclose(f);
     f = NULL;
 
-    ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
+    ret = mbedtls_ctr_drbg_update(ctx, buf, n);
 
 exit:
-    mbedtls_platform_zeroize( buf, sizeof( buf ) );
-    if( f != NULL )
-        fclose( f );
-    if( ret != 0 )
-        return( ret );
-    return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
+    mbedtls_platform_zeroize(buf, sizeof(buf));
+    if (f != NULL) {
+        fclose(f);
+    }
+    if (ret != 0) {
+        return ret;
+    }
+    return mbedtls_ctr_drbg_write_seed_file(ctx, path);
 }
 #endif /* MBEDTLS_FS_IO */
 
@@ -706,192 +696,197 @@
 
 #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
 static const unsigned char entropy_source_pr[] =
-    { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
-      0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
-      0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
-      0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
-      0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
-      0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
-      0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
+{ 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb,
+  0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92,
+  0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8,
+  0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20,
+  0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0,
+  0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad,
+  0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 };
 
 static const unsigned char entropy_source_nopr[] =
-    { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
-      0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
-      0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
-      0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
-      0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
+{ 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45,
+  0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9,
+  0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20,
+  0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f,
+  0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c };
 
 static const unsigned char pers_pr[] =
-    { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
-      0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
+{ 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a,
+  0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad };
 
 static const unsigned char pers_nopr[] =
-    { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
-      0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
+{ 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c,
+  0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f };
 
 static const unsigned char result_pr[] =
-    { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
-      0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
-      0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
-      0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
-      0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
-      0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
-      0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
-      0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
+{ 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66,
+  0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff,
+  0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10,
+  0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30,
+  0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4,
+  0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc,
+  0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06,
+  0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf };
 
 static const unsigned char result_nopr[] =
-    { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
-      0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
-      0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
-      0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
-      0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
-      0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
-      0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
-      0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
+{ 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13,
+  0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0,
+  0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf,
+  0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2,
+  0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7,
+  0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2,
+  0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02,
+  0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 };
 #else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
 
 static const unsigned char entropy_source_pr[] =
-    { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
-      0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
-      0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
-      0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
-      0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
-      0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
-      0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
-      0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
-      0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
-      0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
-      0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
-      0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
-      0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
-      0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
+{ 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49,
+  0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a,
+  0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85,
+  0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e,
+  0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15,
+  0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45,
+  0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8,
+  0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c,
+  0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3,
+  0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce,
+  0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e,
+  0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76,
+  0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77,
+  0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe };
 
 static const unsigned char entropy_source_nopr[] =
-    { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
-      0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
-      0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
-      0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
-      0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
-      0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
-      0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
-      0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
-      0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
-      0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
+{ 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d,
+  0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0,
+  0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73,
+  0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c,
+  0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2,
+  0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1,
+  0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a,
+  0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb,
+  0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a,
+  0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 };
 
 static const unsigned char pers_pr[] =
-    { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
-      0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
-      0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
-      0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
+{ 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33,
+  0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e,
+  0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0,
+  0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 };
 
 static const unsigned char pers_nopr[] =
-    { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
-      0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
-      0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
-      0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
+{ 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29,
+  0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf,
+  0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb,
+  0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b };
 
 static const unsigned char result_pr[] =
-    { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
-      0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
-      0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
-      0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
-      0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
-      0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
-      0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
-      0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
+{ 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85,
+  0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d,
+  0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62,
+  0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d,
+  0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb,
+  0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39,
+  0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40,
+  0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 };
 
 static const unsigned char result_nopr[] =
-    { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
-      0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
-      0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
-      0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
-      0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
-      0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
-      0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
-      0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
+{ 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad,
+  0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3,
+  0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b,
+  0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14,
+  0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54,
+  0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30,
+  0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a,
+  0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 };
 #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
 
 static size_t test_offset;
-static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
-                                       size_t len )
+static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf,
+                                      size_t len)
 {
     const unsigned char *p = data;
-    memcpy( buf, p + test_offset, len );
+    memcpy(buf, p + test_offset, len);
     test_offset += len;
-    return( 0 );
+    return 0;
 }
 
-#define CHK( c )    if( (c) != 0 )                          \
-                    {                                       \
-                        if( verbose != 0 )                  \
-                            mbedtls_printf( "failed\n" );  \
-                        return( 1 );                        \
-                    }
+#define CHK(c)    if ((c) != 0)                          \
+    {                                       \
+        if (verbose != 0)                  \
+        mbedtls_printf("failed\n");  \
+        return 1;                        \
+    }
 
 #define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
 
 /*
  * Checkup routine
  */
-int mbedtls_ctr_drbg_self_test( int verbose )
+int mbedtls_ctr_drbg_self_test(int verbose)
 {
     mbedtls_ctr_drbg_context ctx;
-    unsigned char buf[ sizeof( result_pr ) ];
+    unsigned char buf[sizeof(result_pr)];
 
-    mbedtls_ctr_drbg_init( &ctx );
+    mbedtls_ctr_drbg_init(&ctx);
 
     /*
      * Based on a NIST CTR_DRBG test vector (PR = True)
      */
-    if( verbose != 0 )
-        mbedtls_printf( "  CTR_DRBG (PR = TRUE) : " );
+    if (verbose != 0) {
+        mbedtls_printf("  CTR_DRBG (PR = TRUE) : ");
+    }
 
     test_offset = 0;
-    mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE );
-    mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
-    CHK( mbedtls_ctr_drbg_seed( &ctx,
-                                ctr_drbg_self_test_entropy,
-                                (void *) entropy_source_pr,
-                                pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
-    mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
-    CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
-    CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
-    CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
+    mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
+    mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
+    CHK(mbedtls_ctr_drbg_seed(&ctx,
+                              ctr_drbg_self_test_entropy,
+                              (void *) entropy_source_pr,
+                              pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE));
+    mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
+    CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
+    CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr)));
+    CHK(memcmp(buf, result_pr, sizeof(result_pr)));
 
-    mbedtls_ctr_drbg_free( &ctx );
+    mbedtls_ctr_drbg_free(&ctx);
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
 
     /*
      * Based on a NIST CTR_DRBG test vector (PR = FALSE)
      */
-    if( verbose != 0 )
-        mbedtls_printf( "  CTR_DRBG (PR = FALSE): " );
+    if (verbose != 0) {
+        mbedtls_printf("  CTR_DRBG (PR = FALSE): ");
+    }
 
-    mbedtls_ctr_drbg_init( &ctx );
+    mbedtls_ctr_drbg_init(&ctx);
 
     test_offset = 0;
-    mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
-    mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 );
-    CHK( mbedtls_ctr_drbg_seed( &ctx,
-                                ctr_drbg_self_test_entropy,
-                                (void *) entropy_source_nopr,
-                                pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
-    CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
-    CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
-    CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
-    CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
+    mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE);
+    mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2);
+    CHK(mbedtls_ctr_drbg_seed(&ctx,
+                              ctr_drbg_self_test_entropy,
+                              (void *) entropy_source_nopr,
+                              pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE));
+    CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0));
+    CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH));
+    CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr)));
+    CHK(memcmp(buf, result_nopr, sizeof(result_nopr)));
 
-    mbedtls_ctr_drbg_free( &ctx );
+    mbedtls_ctr_drbg_free(&ctx);
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
 
-    if( verbose != 0 )
-            mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_SELF_TEST */
 
diff --git a/lib/libmbedtls/mbedtls/library/debug.c b/lib/libmbedtls/mbedtls/library/debug.c
index e108600..12559af 100644
--- a/lib/libmbedtls/mbedtls/library/debug.c
+++ b/lib/libmbedtls/mbedtls/library/debug.c
@@ -21,16 +21,7 @@
 
 #if defined(MBEDTLS_DEBUG_C)
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc      calloc
-#define mbedtls_free        free
-#define mbedtls_time_t      time_t
-#define mbedtls_snprintf    snprintf
-#define mbedtls_vsnprintf   vsnprintf
-#endif
 
 #include "mbedtls/debug.h"
 #include "mbedtls/error.h"
@@ -39,16 +30,11 @@
 #include <stdio.h>
 #include <string.h>
 
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
-    !defined(inline) && !defined(__cplusplus)
-#define inline __inline
-#endif
-
 #define DEBUG_BUF_SIZE      512
 
 static int debug_threshold = 0;
 
-void mbedtls_debug_set_threshold( int threshold )
+void mbedtls_debug_set_threshold(int threshold)
 {
     debug_threshold = threshold;
 }
@@ -56,9 +42,9 @@
 /*
  * All calls to f_dbg must be made via this function
  */
-static inline void debug_send_line( const mbedtls_ssl_context *ssl, int level,
-                                    const char *file, int line,
-                                    const char *str )
+static inline void debug_send_line(const mbedtls_ssl_context *ssl, int level,
+                                   const char *file, int line,
+                                   const char *str)
 {
     /*
      * If in a threaded environment, we need a thread identifier.
@@ -67,353 +53,334 @@
      */
 #if defined(MBEDTLS_THREADING_C)
     char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */
-    mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", (void*)ssl, str );
-    ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, idstr );
+    mbedtls_snprintf(idstr, sizeof(idstr), "%p: %s", (void *) ssl, str);
+    ssl->conf->f_dbg(ssl->conf->p_dbg, level, file, line, idstr);
 #else
-    ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
+    ssl->conf->f_dbg(ssl->conf->p_dbg, level, file, line, str);
 #endif
 }
 
 MBEDTLS_PRINTF_ATTRIBUTE(5, 6)
-void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level,
-                              const char *file, int line,
-                              const char *format, ... )
+void mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level,
+                             const char *file, int line,
+                             const char *format, ...)
 {
     va_list argp;
     char str[DEBUG_BUF_SIZE];
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( NULL == ssl              ||
+    if (NULL == ssl              ||
         NULL == ssl->conf        ||
         NULL == ssl->conf->f_dbg ||
-        level > debug_threshold )
-    {
+        level > debug_threshold) {
         return;
     }
 
-    va_start( argp, format );
-    ret = mbedtls_vsnprintf( str, DEBUG_BUF_SIZE, format, argp );
-    va_end( argp );
+    va_start(argp, format);
+    ret = mbedtls_vsnprintf(str, DEBUG_BUF_SIZE, format, argp);
+    va_end(argp);
 
-    if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 )
-    {
+    if (ret >= 0 && ret < DEBUG_BUF_SIZE - 1) {
         str[ret]     = '\n';
         str[ret + 1] = '\0';
     }
 
-    debug_send_line( ssl, level, file, line, str );
+    debug_send_line(ssl, level, file, line, str);
 }
 
-void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level,
-                      const char *file, int line,
-                      const char *text, int ret )
+void mbedtls_debug_print_ret(const mbedtls_ssl_context *ssl, int level,
+                             const char *file, int line,
+                             const char *text, int ret)
 {
     char str[DEBUG_BUF_SIZE];
 
-    if( NULL == ssl              ||
+    if (NULL == ssl              ||
         NULL == ssl->conf        ||
         NULL == ssl->conf->f_dbg ||
-        level > debug_threshold )
-    {
+        level > debug_threshold) {
         return;
     }
 
     /*
      * With non-blocking I/O and examples that just retry immediately,
      * the logs would be quickly flooded with WANT_READ, so ignore that.
-     * Don't ignore WANT_WRITE however, since is is usually rare.
+     * Don't ignore WANT_WRITE however, since it is usually rare.
      */
-    if( ret == MBEDTLS_ERR_SSL_WANT_READ )
+    if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
         return;
+    }
 
-    mbedtls_snprintf( str, sizeof( str ), "%s() returned %d (-0x%04x)\n",
-              text, ret, (unsigned int) -ret );
+    mbedtls_snprintf(str, sizeof(str), "%s() returned %d (-0x%04x)\n",
+                     text, ret, (unsigned int) -ret);
 
-    debug_send_line( ssl, level, file, line, str );
+    debug_send_line(ssl, level, file, line, str);
 }
 
-void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level,
-                      const char *file, int line, const char *text,
-                      const unsigned char *buf, size_t len )
+void mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level,
+                             const char *file, int line, const char *text,
+                             const unsigned char *buf, size_t len)
 {
     char str[DEBUG_BUF_SIZE];
     char txt[17];
     size_t i, idx = 0;
 
-    if( NULL == ssl              ||
+    if (NULL == ssl              ||
         NULL == ssl->conf        ||
         NULL == ssl->conf->f_dbg ||
-        level > debug_threshold )
-    {
+        level > debug_threshold) {
         return;
     }
 
-    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "dumping '%s' (%u bytes)\n",
-              text, (unsigned int) len );
+    mbedtls_snprintf(str + idx, sizeof(str) - idx, "dumping '%s' (%u bytes)\n",
+                     text, (unsigned int) len);
 
-    debug_send_line( ssl, level, file, line, str );
+    debug_send_line(ssl, level, file, line, str);
 
     idx = 0;
-    memset( txt, 0, sizeof( txt ) );
-    for( i = 0; i < len; i++ )
-    {
-        if( i >= 4096 )
+    memset(txt, 0, sizeof(txt));
+    for (i = 0; i < len; i++) {
+        if (i >= 4096) {
             break;
+        }
 
-        if( i % 16 == 0 )
-        {
-            if( i > 0 )
-            {
-                mbedtls_snprintf( str + idx, sizeof( str ) - idx, "  %s\n", txt );
-                debug_send_line( ssl, level, file, line, str );
+        if (i % 16 == 0) {
+            if (i > 0) {
+                mbedtls_snprintf(str + idx, sizeof(str) - idx, "  %s\n", txt);
+                debug_send_line(ssl, level, file, line, str);
 
                 idx = 0;
-                memset( txt, 0, sizeof( txt ) );
+                memset(txt, 0, sizeof(txt));
             }
 
-            idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "%04x: ",
-                             (unsigned int) i );
+            idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, "%04x: ",
+                                    (unsigned int) i);
 
         }
 
-        idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x",
-                         (unsigned int) buf[i] );
-        txt[i % 16] = ( buf[i] > 31 && buf[i] < 127 ) ? buf[i] : '.' ;
+        idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x",
+                                (unsigned int) buf[i]);
+        txt[i % 16] = (buf[i] > 31 && buf[i] < 127) ? buf[i] : '.';
     }
 
-    if( len > 0 )
-    {
-        for( /* i = i */; i % 16 != 0; i++ )
-            idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "   " );
+    if (len > 0) {
+        for (/* i = i */; i % 16 != 0; i++) {
+            idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, "   ");
+        }
 
-        mbedtls_snprintf( str + idx, sizeof( str ) - idx, "  %s\n", txt );
-        debug_send_line( ssl, level, file, line, str );
+        mbedtls_snprintf(str + idx, sizeof(str) - idx, "  %s\n", txt);
+        debug_send_line(ssl, level, file, line, str);
     }
 }
 
 #if defined(MBEDTLS_ECP_C)
-void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level,
-                      const char *file, int line,
-                      const char *text, const mbedtls_ecp_point *X )
+void mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level,
+                             const char *file, int line,
+                             const char *text, const mbedtls_ecp_point *X)
 {
     char str[DEBUG_BUF_SIZE];
 
-    if( NULL == ssl              ||
+    if (NULL == ssl              ||
         NULL == ssl->conf        ||
         NULL == ssl->conf->f_dbg ||
-        level > debug_threshold )
-    {
+        level > debug_threshold) {
         return;
     }
 
-    mbedtls_snprintf( str, sizeof( str ), "%s(X)", text );
-    mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->X );
+    mbedtls_snprintf(str, sizeof(str), "%s(X)", text);
+    mbedtls_debug_print_mpi(ssl, level, file, line, str, &X->X);
 
-    mbedtls_snprintf( str, sizeof( str ), "%s(Y)", text );
-    mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->Y );
+    mbedtls_snprintf(str, sizeof(str), "%s(Y)", text);
+    mbedtls_debug_print_mpi(ssl, level, file, line, str, &X->Y);
 }
 #endif /* MBEDTLS_ECP_C */
 
 #if defined(MBEDTLS_BIGNUM_C)
-void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level,
-                      const char *file, int line,
-                      const char *text, const mbedtls_mpi *X )
+void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level,
+                             const char *file, int line,
+                             const char *text, const mbedtls_mpi *X)
 {
     char str[DEBUG_BUF_SIZE];
     size_t bitlen;
     size_t idx = 0;
 
-    if( NULL == ssl              ||
+    if (NULL == ssl              ||
         NULL == ssl->conf        ||
         NULL == ssl->conf->f_dbg ||
         NULL == X                ||
-        level > debug_threshold )
-    {
+        level > debug_threshold) {
         return;
     }
 
-    bitlen = mbedtls_mpi_bitlen( X );
+    bitlen = mbedtls_mpi_bitlen(X);
 
-    mbedtls_snprintf( str, sizeof( str ), "value of '%s' (%u bits) is:\n",
-                      text, (unsigned) bitlen );
-    debug_send_line( ssl, level, file, line, str );
+    mbedtls_snprintf(str, sizeof(str), "value of '%s' (%u bits) is:\n",
+                     text, (unsigned) bitlen);
+    debug_send_line(ssl, level, file, line, str);
 
-    if( bitlen == 0 )
-    {
+    if (bitlen == 0) {
         str[0] = ' '; str[1] = '0'; str[2] = '0';
         idx = 3;
-    }
-    else
-    {
+    } else {
         int n;
-        for( n = (int) ( ( bitlen - 1 ) / 8 ); n >= 0; n-- )
-        {
-            size_t limb_offset = n / sizeof( mbedtls_mpi_uint );
-            size_t offset_in_limb = n % sizeof( mbedtls_mpi_uint );
+        for (n = (int) ((bitlen - 1) / 8); n >= 0; n--) {
+            size_t limb_offset = n / sizeof(mbedtls_mpi_uint);
+            size_t offset_in_limb = n % sizeof(mbedtls_mpi_uint);
             unsigned char octet =
-                ( X->p[limb_offset] >> ( offset_in_limb * 8 ) ) & 0xff;
-            mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", octet );
+                (X->p[limb_offset] >> (offset_in_limb * 8)) & 0xff;
+            mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x", octet);
             idx += 3;
             /* Wrap lines after 16 octets that each take 3 columns */
-            if( idx >= 3 * 16 )
-            {
-                mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
-                debug_send_line( ssl, level, file, line, str );
+            if (idx >= 3 * 16) {
+                mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n");
+                debug_send_line(ssl, level, file, line, str);
                 idx = 0;
             }
         }
     }
 
-    if( idx != 0 )
-    {
-        mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
-        debug_send_line( ssl, level, file, line, str );
+    if (idx != 0) {
+        mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n");
+        debug_send_line(ssl, level, file, line, str);
     }
 }
 #endif /* MBEDTLS_BIGNUM_C */
 
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-static void debug_print_pk( const mbedtls_ssl_context *ssl, int level,
-                            const char *file, int line,
-                            const char *text, const mbedtls_pk_context *pk )
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && !defined(MBEDTLS_X509_REMOVE_INFO)
+static void debug_print_pk(const mbedtls_ssl_context *ssl, int level,
+                           const char *file, int line,
+                           const char *text, const mbedtls_pk_context *pk)
 {
     size_t i;
     mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS];
     char name[16];
 
-    memset( items, 0, sizeof( items ) );
+    memset(items, 0, sizeof(items));
 
-    if( mbedtls_pk_debug( pk, items ) != 0 )
-    {
-        debug_send_line( ssl, level, file, line,
-                          "invalid PK context\n" );
+    if (mbedtls_pk_debug(pk, items) != 0) {
+        debug_send_line(ssl, level, file, line,
+                        "invalid PK context\n");
         return;
     }
 
-    for( i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++ )
-    {
-        if( items[i].type == MBEDTLS_PK_DEBUG_NONE )
+    for (i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++) {
+        if (items[i].type == MBEDTLS_PK_DEBUG_NONE) {
             return;
+        }
 
-        mbedtls_snprintf( name, sizeof( name ), "%s%s", text, items[i].name );
-        name[sizeof( name ) - 1] = '\0';
+        mbedtls_snprintf(name, sizeof(name), "%s%s", text, items[i].name);
+        name[sizeof(name) - 1] = '\0';
 
-        if( items[i].type == MBEDTLS_PK_DEBUG_MPI )
-            mbedtls_debug_print_mpi( ssl, level, file, line, name, items[i].value );
-        else
+        if (items[i].type == MBEDTLS_PK_DEBUG_MPI) {
+            mbedtls_debug_print_mpi(ssl, level, file, line, name, items[i].value);
+        } else
 #if defined(MBEDTLS_ECP_C)
-        if( items[i].type == MBEDTLS_PK_DEBUG_ECP )
-            mbedtls_debug_print_ecp( ssl, level, file, line, name, items[i].value );
-        else
+        if (items[i].type == MBEDTLS_PK_DEBUG_ECP) {
+            mbedtls_debug_print_ecp(ssl, level, file, line, name, items[i].value);
+        } else
 #endif
-            debug_send_line( ssl, level, file, line,
-                              "should not happen\n" );
+        { debug_send_line(ssl, level, file, line,
+                          "should not happen\n"); }
     }
 }
 
-static void debug_print_line_by_line( const mbedtls_ssl_context *ssl, int level,
-                                      const char *file, int line, const char *text )
+static void debug_print_line_by_line(const mbedtls_ssl_context *ssl, int level,
+                                     const char *file, int line, const char *text)
 {
     char str[DEBUG_BUF_SIZE];
     const char *start, *cur;
 
     start = text;
-    for( cur = text; *cur != '\0'; cur++ )
-    {
-        if( *cur == '\n' )
-        {
+    for (cur = text; *cur != '\0'; cur++) {
+        if (*cur == '\n') {
             size_t len = cur - start + 1;
-            if( len > DEBUG_BUF_SIZE - 1 )
+            if (len > DEBUG_BUF_SIZE - 1) {
                 len = DEBUG_BUF_SIZE - 1;
+            }
 
-            memcpy( str, start, len );
+            memcpy(str, start, len);
             str[len] = '\0';
 
-            debug_send_line( ssl, level, file, line, str );
+            debug_send_line(ssl, level, file, line, str);
 
             start = cur + 1;
         }
     }
 }
 
-void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level,
-                      const char *file, int line,
-                      const char *text, const mbedtls_x509_crt *crt )
+void mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level,
+                             const char *file, int line,
+                             const char *text, const mbedtls_x509_crt *crt)
 {
     char str[DEBUG_BUF_SIZE];
     int i = 0;
 
-    if( NULL == ssl              ||
+    if (NULL == ssl              ||
         NULL == ssl->conf        ||
         NULL == ssl->conf->f_dbg ||
         NULL == crt              ||
-        level > debug_threshold )
-    {
+        level > debug_threshold) {
         return;
     }
 
-    while( crt != NULL )
-    {
+    while (crt != NULL) {
         char buf[1024];
 
-        mbedtls_snprintf( str, sizeof( str ), "%s #%d:\n", text, ++i );
-        debug_send_line( ssl, level, file, line, str );
+        mbedtls_snprintf(str, sizeof(str), "%s #%d:\n", text, ++i);
+        debug_send_line(ssl, level, file, line, str);
 
-        mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt );
-        debug_print_line_by_line( ssl, level, file, line, buf );
+        mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt);
+        debug_print_line_by_line(ssl, level, file, line, buf);
 
-        debug_print_pk( ssl, level, file, line, "crt->", &crt->pk );
+        debug_print_pk(ssl, level, file, line, "crt->", &crt->pk);
 
         crt = crt->next;
     }
 }
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_X509_REMOVE_INFO */
 
 #if defined(MBEDTLS_ECDH_C)
-static void mbedtls_debug_printf_ecdh_internal( const mbedtls_ssl_context *ssl,
-                                                int level, const char *file,
-                                                int line,
-                                                const mbedtls_ecdh_context *ecdh,
-                                                mbedtls_debug_ecdh_attr attr )
+static void mbedtls_debug_printf_ecdh_internal(const mbedtls_ssl_context *ssl,
+                                               int level, const char *file,
+                                               int line,
+                                               const mbedtls_ecdh_context *ecdh,
+                                               mbedtls_debug_ecdh_attr attr)
 {
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
-    const mbedtls_ecdh_context* ctx = ecdh;
+    const mbedtls_ecdh_context *ctx = ecdh;
 #else
-    const mbedtls_ecdh_context_mbed* ctx = &ecdh->ctx.mbed_ecdh;
+    const mbedtls_ecdh_context_mbed *ctx = &ecdh->ctx.mbed_ecdh;
 #endif
 
-    switch( attr )
-    {
+    switch (attr) {
         case MBEDTLS_DEBUG_ECDH_Q:
-            mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Q",
-                                     &ctx->Q );
+            mbedtls_debug_print_ecp(ssl, level, file, line, "ECDH: Q",
+                                    &ctx->Q);
             break;
         case MBEDTLS_DEBUG_ECDH_QP:
-            mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Qp",
-                                     &ctx->Qp );
+            mbedtls_debug_print_ecp(ssl, level, file, line, "ECDH: Qp",
+                                    &ctx->Qp);
             break;
         case MBEDTLS_DEBUG_ECDH_Z:
-            mbedtls_debug_print_mpi( ssl, level, file, line, "ECDH: z",
-                                     &ctx->z );
+            mbedtls_debug_print_mpi(ssl, level, file, line, "ECDH: z",
+                                    &ctx->z);
             break;
         default:
             break;
     }
 }
 
-void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level,
-                                const char *file, int line,
-                                const mbedtls_ecdh_context *ecdh,
-                                mbedtls_debug_ecdh_attr attr )
+void mbedtls_debug_printf_ecdh(const mbedtls_ssl_context *ssl, int level,
+                               const char *file, int line,
+                               const mbedtls_ecdh_context *ecdh,
+                               mbedtls_debug_ecdh_attr attr)
 {
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
-    mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh, attr );
+    mbedtls_debug_printf_ecdh_internal(ssl, level, file, line, ecdh, attr);
 #else
-    switch( ecdh->var )
-    {
+    switch (ecdh->var) {
         default:
-            mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh,
-                                                attr );
+            mbedtls_debug_printf_ecdh_internal(ssl, level, file, line, ecdh,
+                                               attr);
     }
 #endif
 }
diff --git a/lib/libmbedtls/mbedtls/library/des.c b/lib/libmbedtls/mbedtls/library/des.c
index 91d22b5..eaddf28 100644
--- a/lib/libmbedtls/mbedtls/library/des.c
+++ b/lib/libmbedtls/mbedtls/library/des.c
@@ -33,14 +33,7 @@
 
 #include <string.h>
 
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
 
 #if !defined(MBEDTLS_DES_ALT)
 
@@ -229,7 +222,7 @@
 /*
  * Initial Permutation macro
  */
-#define DES_IP(X,Y)                                                       \
+#define DES_IP(X, Y)                                                       \
     do                                                                    \
     {                                                                     \
         T = (((X) >>  4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T <<  4); \
@@ -239,12 +232,12 @@
         (Y) = (((Y) << 1) | ((Y) >> 31)) & 0xFFFFFFFF;                    \
         T = ((X) ^ (Y)) & 0xAAAAAAAA; (Y) ^= T; (X) ^= T;                 \
         (X) = (((X) << 1) | ((X) >> 31)) & 0xFFFFFFFF;                    \
-    } while( 0 )
+    } while (0)
 
 /*
  * Final Permutation macro
  */
-#define DES_FP(X,Y)                                                       \
+#define DES_FP(X, Y)                                                       \
     do                                                                    \
     {                                                                     \
         (X) = (((X) << 31) | ((X) >> 1)) & 0xFFFFFFFF;                    \
@@ -254,90 +247,103 @@
         T = (((Y) >>  2) ^ (X)) & 0x33333333; (X) ^= T; (Y) ^= (T <<  2); \
         T = (((X) >> 16) ^ (Y)) & 0x0000FFFF; (Y) ^= T; (X) ^= (T << 16); \
         T = (((X) >>  4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T <<  4); \
-    } while( 0 )
+    } while (0)
 
 /*
  * DES round macro
  */
-#define DES_ROUND(X,Y)                              \
+#define DES_ROUND(X, Y)                              \
     do                                              \
     {                                               \
         T = *SK++ ^ (X);                            \
-        (Y) ^= SB8[ (T      ) & 0x3F ] ^            \
-               SB6[ (T >>  8) & 0x3F ] ^            \
-               SB4[ (T >> 16) & 0x3F ] ^            \
-               SB2[ (T >> 24) & 0x3F ];             \
+        (Y) ^= SB8[(T) & 0x3F] ^            \
+               SB6[(T >>  8) & 0x3F] ^            \
+               SB4[(T >> 16) & 0x3F] ^            \
+               SB2[(T >> 24) & 0x3F];             \
                                                     \
         T = *SK++ ^ (((X) << 28) | ((X) >> 4));     \
-        (Y) ^= SB7[ (T      ) & 0x3F ] ^            \
-               SB5[ (T >>  8) & 0x3F ] ^            \
-               SB3[ (T >> 16) & 0x3F ] ^            \
-               SB1[ (T >> 24) & 0x3F ];             \
-    } while( 0 )
+        (Y) ^= SB7[(T) & 0x3F] ^            \
+               SB5[(T >>  8) & 0x3F] ^            \
+               SB3[(T >> 16) & 0x3F] ^            \
+               SB1[(T >> 24) & 0x3F];             \
+    } while (0)
 
-#define SWAP(a,b)                                       \
+#define SWAP(a, b)                                       \
     do                                                  \
     {                                                   \
         uint32_t t = (a); (a) = (b); (b) = t; t = 0;    \
-    } while( 0 )
+    } while (0)
 
-void mbedtls_des_init( mbedtls_des_context *ctx )
+void mbedtls_des_init(mbedtls_des_context *ctx)
 {
-    memset( ctx, 0, sizeof( mbedtls_des_context ) );
+    memset(ctx, 0, sizeof(mbedtls_des_context));
 }
 
-void mbedtls_des_free( mbedtls_des_context *ctx )
+void mbedtls_des_free(mbedtls_des_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des_context ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_des_context));
 }
 
-void mbedtls_des3_init( mbedtls_des3_context *ctx )
+void mbedtls_des3_init(mbedtls_des3_context *ctx)
 {
-    memset( ctx, 0, sizeof( mbedtls_des3_context ) );
+    memset(ctx, 0, sizeof(mbedtls_des3_context));
 }
 
-void mbedtls_des3_free( mbedtls_des3_context *ctx )
+void mbedtls_des3_free(mbedtls_des3_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des3_context ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_des3_context));
 }
 
 static const unsigned char odd_parity_table[128] = { 1,  2,  4,  7,  8,
-        11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
-        47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
-        82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
-        115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
-        143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
-        171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
-        199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
-        227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
-        254 };
+                                                     11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32,
+                                                     35, 37, 38, 41, 42, 44,
+                                                     47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69,
+                                                     70, 73, 74, 76, 79, 81,
+                                                     82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103,
+                                                     104, 107, 109, 110, 112,
+                                                     115, 117, 118, 121, 122, 124, 127, 128, 131,
+                                                     133, 134, 137, 138, 140,
+                                                     143, 145, 146, 148, 151, 152, 155, 157, 158,
+                                                     161, 162, 164, 167, 168,
+                                                     171, 173, 174, 176, 179, 181, 182, 185, 186,
+                                                     188, 191, 193, 194, 196,
+                                                     199, 200, 203, 205, 206, 208, 211, 213, 214,
+                                                     217, 218, 220, 223, 224,
+                                                     227, 229, 230, 233, 234, 236, 239, 241, 242,
+                                                     244, 247, 248, 251, 253,
+                                                     254 };
 
-void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] )
+void mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE])
 {
     int i;
 
-    for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ )
+    for (i = 0; i < MBEDTLS_DES_KEY_SIZE; i++) {
         key[i] = odd_parity_table[key[i] / 2];
+    }
 }
 
 /*
  * Check the given key's parity, returns 1 on failure, 0 on SUCCESS
  */
-int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
+int mbedtls_des_key_check_key_parity(const unsigned char key[MBEDTLS_DES_KEY_SIZE])
 {
     int i;
 
-    for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ )
-        if( key[i] != odd_parity_table[key[i] / 2] )
-            return( 1 );
+    for (i = 0; i < MBEDTLS_DES_KEY_SIZE; i++) {
+        if (key[i] != odd_parity_table[key[i] / 2]) {
+            return 1;
+        }
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -384,41 +390,43 @@
     { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 }
 };
 
-int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
+int mbedtls_des_key_check_weak(const unsigned char key[MBEDTLS_DES_KEY_SIZE])
 {
     int i;
 
-    for( i = 0; i < WEAK_KEY_COUNT; i++ )
-        if( memcmp( weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0 )
-            return( 1 );
+    for (i = 0; i < WEAK_KEY_COUNT; i++) {
+        if (memcmp(weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0) {
+            return 1;
+        }
+    }
 
-    return( 0 );
+    return 0;
 }
 
 #if !defined(MBEDTLS_DES_SETKEY_ALT)
-void mbedtls_des_setkey( uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
+void mbedtls_des_setkey(uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE])
 {
     int i;
     uint32_t X, Y, T;
 
-    X = MBEDTLS_GET_UINT32_BE( key, 0 );
-    Y = MBEDTLS_GET_UINT32_BE( key, 4 );
+    X = MBEDTLS_GET_UINT32_BE(key, 0);
+    Y = MBEDTLS_GET_UINT32_BE(key, 4);
 
     /*
      * Permuted Choice 1
      */
     T =  ((Y >>  4) ^ X) & 0x0F0F0F0F;  X ^= T; Y ^= (T <<  4);
-    T =  ((Y      ) ^ X) & 0x10101010;  X ^= T; Y ^= (T      );
+    T =  ((Y) ^ X) & 0x10101010;  X ^= T; Y ^= (T);
 
-    X =   (LHs[ (X      ) & 0xF] << 3) | (LHs[ (X >>  8) & 0xF ] << 2)
-        | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ]     )
-        | (LHs[ (X >>  5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6)
-        | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4);
+    X =   (LHs[(X) & 0xF] << 3) | (LHs[(X >>  8) & 0xF] << 2)
+        | (LHs[(X >> 16) & 0xF] << 1) | (LHs[(X >> 24) & 0xF])
+        | (LHs[(X >>  5) & 0xF] << 7) | (LHs[(X >> 13) & 0xF] << 6)
+        | (LHs[(X >> 21) & 0xF] << 5) | (LHs[(X >> 29) & 0xF] << 4);
 
-    Y =   (RHs[ (Y >>  1) & 0xF] << 3) | (RHs[ (Y >>  9) & 0xF ] << 2)
-        | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ]     )
-        | (RHs[ (Y >>  4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6)
-        | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4);
+    Y =   (RHs[(Y >>  1) & 0xF] << 3) | (RHs[(Y >>  9) & 0xF] << 2)
+        | (RHs[(Y >> 17) & 0xF] << 1) | (RHs[(Y >> 25) & 0xF])
+        | (RHs[(Y >>  4) & 0xF] << 7) | (RHs[(Y >> 12) & 0xF] << 6)
+        | (RHs[(Y >> 20) & 0xF] << 5) | (RHs[(Y >> 28) & 0xF] << 4);
 
     X &= 0x0FFFFFFF;
     Y &= 0x0FFFFFFF;
@@ -426,15 +434,11 @@
     /*
      * calculate subkeys
      */
-    for( i = 0; i < 16; i++ )
-    {
-        if( i < 2 || i == 8 || i == 15 )
-        {
+    for (i = 0; i < 16; i++) {
+        if (i < 2 || i == 8 || i == 15) {
             X = ((X <<  1) | (X >> 27)) & 0x0FFFFFFF;
             Y = ((Y <<  1) | (Y >> 27)) & 0x0FFFFFFF;
-        }
-        else
-        {
+        } else {
             X = ((X <<  2) | (X >> 26)) & 0x0FFFFFFF;
             Y = ((Y <<  2) | (Y >> 26)) & 0x0FFFFFFF;
         }
@@ -446,7 +450,7 @@
                 | ((X <<  2) & 0x00020000) | ((X >> 10) & 0x00010000)
                 | ((Y >> 13) & 0x00002000) | ((Y >>  4) & 0x00001000)
                 | ((Y <<  6) & 0x00000800) | ((Y >>  1) & 0x00000400)
-                | ((Y >> 14) & 0x00000200) | ((Y      ) & 0x00000100)
+                | ((Y >> 14) & 0x00000200) | ((Y) & 0x00000100)
                 | ((Y >>  5) & 0x00000020) | ((Y >> 10) & 0x00000010)
                 | ((Y >>  3) & 0x00000008) | ((Y >> 18) & 0x00000004)
                 | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);
@@ -459,7 +463,7 @@
                 | ((X << 15) & 0x00020000) | ((X >>  4) & 0x00010000)
                 | ((Y >>  2) & 0x00002000) | ((Y <<  8) & 0x00001000)
                 | ((Y >> 14) & 0x00000808) | ((Y >>  9) & 0x00000400)
-                | ((Y      ) & 0x00000200) | ((Y <<  7) & 0x00000100)
+                | ((Y) & 0x00000200) | ((Y <<  7) & 0x00000100)
                 | ((Y >>  7) & 0x00000020) | ((Y >>  3) & 0x00000011)
                 | ((Y <<  2) & 0x00000004) | ((Y >> 21) & 0x00000002);
     }
@@ -469,52 +473,50 @@
 /*
  * DES key schedule (56-bit, encryption)
  */
-int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
+int mbedtls_des_setkey_enc(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE])
 {
-    mbedtls_des_setkey( ctx->sk, key );
+    mbedtls_des_setkey(ctx->sk, key);
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * DES key schedule (56-bit, decryption)
  */
-int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
+int mbedtls_des_setkey_dec(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE])
 {
     int i;
 
-    mbedtls_des_setkey( ctx->sk, key );
+    mbedtls_des_setkey(ctx->sk, key);
 
-    for( i = 0; i < 16; i += 2 )
-    {
-        SWAP( ctx->sk[i    ], ctx->sk[30 - i] );
-        SWAP( ctx->sk[i + 1], ctx->sk[31 - i] );
+    for (i = 0; i < 16; i += 2) {
+        SWAP(ctx->sk[i], ctx->sk[30 - i]);
+        SWAP(ctx->sk[i + 1], ctx->sk[31 - i]);
     }
 
-    return( 0 );
+    return 0;
 }
 
-static void des3_set2key( uint32_t esk[96],
-                          uint32_t dsk[96],
-                          const unsigned char key[MBEDTLS_DES_KEY_SIZE*2] )
+static void des3_set2key(uint32_t esk[96],
+                         uint32_t dsk[96],
+                         const unsigned char key[MBEDTLS_DES_KEY_SIZE*2])
 {
     int i;
 
-    mbedtls_des_setkey( esk, key );
-    mbedtls_des_setkey( dsk + 32, key + 8 );
+    mbedtls_des_setkey(esk, key);
+    mbedtls_des_setkey(dsk + 32, key + 8);
 
-    for( i = 0; i < 32; i += 2 )
-    {
-        dsk[i     ] = esk[30 - i];
+    for (i = 0; i < 32; i += 2) {
+        dsk[i] = esk[30 - i];
         dsk[i +  1] = esk[31 - i];
 
         esk[i + 32] = dsk[62 - i];
         esk[i + 33] = dsk[63 - i];
 
-        esk[i + 64] = esk[i    ];
+        esk[i + 64] = esk[i];
         esk[i + 65] = esk[i + 1];
 
-        dsk[i + 64] = dsk[i    ];
+        dsk[i + 64] = dsk[i];
         dsk[i + 65] = dsk[i + 1];
     }
 }
@@ -522,44 +524,43 @@
 /*
  * Triple-DES key schedule (112-bit, encryption)
  */
-int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
-                      const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
+int mbedtls_des3_set2key_enc(mbedtls_des3_context *ctx,
+                             const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2])
 {
     uint32_t sk[96];
 
-    des3_set2key( ctx->sk, sk, key );
-    mbedtls_platform_zeroize( sk,  sizeof( sk ) );
+    des3_set2key(ctx->sk, sk, key);
+    mbedtls_platform_zeroize(sk,  sizeof(sk));
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Triple-DES key schedule (112-bit, decryption)
  */
-int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
-                      const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
+int mbedtls_des3_set2key_dec(mbedtls_des3_context *ctx,
+                             const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2])
 {
     uint32_t sk[96];
 
-    des3_set2key( sk, ctx->sk, key );
-    mbedtls_platform_zeroize( sk,  sizeof( sk ) );
+    des3_set2key(sk, ctx->sk, key);
+    mbedtls_platform_zeroize(sk,  sizeof(sk));
 
-    return( 0 );
+    return 0;
 }
 
-static void des3_set3key( uint32_t esk[96],
-                          uint32_t dsk[96],
-                          const unsigned char key[24] )
+static void des3_set3key(uint32_t esk[96],
+                         uint32_t dsk[96],
+                         const unsigned char key[24])
 {
     int i;
 
-    mbedtls_des_setkey( esk, key );
-    mbedtls_des_setkey( dsk + 32, key +  8 );
-    mbedtls_des_setkey( esk + 64, key + 16 );
+    mbedtls_des_setkey(esk, key);
+    mbedtls_des_setkey(dsk + 32, key +  8);
+    mbedtls_des_setkey(esk + 64, key + 16);
 
-    for( i = 0; i < 32; i += 2 )
-    {
-        dsk[i     ] = esk[94 - i];
+    for (i = 0; i < 32; i += 2) {
+        dsk[i] = esk[94 - i];
         dsk[i +  1] = esk[95 - i];
 
         esk[i + 32] = dsk[62 - i];
@@ -573,61 +574,60 @@
 /*
  * Triple-DES key schedule (168-bit, encryption)
  */
-int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
-                      const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
+int mbedtls_des3_set3key_enc(mbedtls_des3_context *ctx,
+                             const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3])
 {
     uint32_t sk[96];
 
-    des3_set3key( ctx->sk, sk, key );
-    mbedtls_platform_zeroize( sk,  sizeof( sk ) );
+    des3_set3key(ctx->sk, sk, key);
+    mbedtls_platform_zeroize(sk,  sizeof(sk));
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Triple-DES key schedule (168-bit, decryption)
  */
-int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
-                      const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
+int mbedtls_des3_set3key_dec(mbedtls_des3_context *ctx,
+                             const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3])
 {
     uint32_t sk[96];
 
-    des3_set3key( sk, ctx->sk, key );
-    mbedtls_platform_zeroize( sk,  sizeof( sk ) );
+    des3_set3key(sk, ctx->sk, key);
+    mbedtls_platform_zeroize(sk,  sizeof(sk));
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * DES-ECB block encryption/decryption
  */
 #if !defined(MBEDTLS_DES_CRYPT_ECB_ALT)
-int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
-                    const unsigned char input[8],
-                    unsigned char output[8] )
+int mbedtls_des_crypt_ecb(mbedtls_des_context *ctx,
+                          const unsigned char input[8],
+                          unsigned char output[8])
 {
     int i;
     uint32_t X, Y, T, *SK;
 
     SK = ctx->sk;
 
-    X = MBEDTLS_GET_UINT32_BE( input, 0 );
-    Y = MBEDTLS_GET_UINT32_BE( input, 4 );
+    X = MBEDTLS_GET_UINT32_BE(input, 0);
+    Y = MBEDTLS_GET_UINT32_BE(input, 4);
 
-    DES_IP( X, Y );
+    DES_IP(X, Y);
 
-    for( i = 0; i < 8; i++ )
-    {
-        DES_ROUND( Y, X );
-        DES_ROUND( X, Y );
+    for (i = 0; i < 8; i++) {
+        DES_ROUND(Y, X);
+        DES_ROUND(X, Y);
     }
 
-    DES_FP( Y, X );
+    DES_FP(Y, X);
 
-    MBEDTLS_PUT_UINT32_BE( Y, output, 0 );
-    MBEDTLS_PUT_UINT32_BE( X, output, 4 );
+    MBEDTLS_PUT_UINT32_BE(Y, output, 0);
+    MBEDTLS_PUT_UINT32_BE(X, output, 4);
 
-    return( 0 );
+    return 0;
 }
 #endif /* !MBEDTLS_DES_CRYPT_ECB_ALT */
 
@@ -635,50 +635,45 @@
 /*
  * DES-CBC buffer encryption/decryption
  */
-int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
-                    int mode,
-                    size_t length,
-                    unsigned char iv[8],
-                    const unsigned char *input,
-                    unsigned char *output )
+int mbedtls_des_crypt_cbc(mbedtls_des_context *ctx,
+                          int mode,
+                          size_t length,
+                          unsigned char iv[8],
+                          const unsigned char *input,
+                          unsigned char *output)
 {
-    int i;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char temp[8];
 
-    if( length % 8 )
-        return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH );
+    if (length % 8) {
+        return MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH;
+    }
 
-    if( mode == MBEDTLS_DES_ENCRYPT )
-    {
-        while( length > 0 )
-        {
-            for( i = 0; i < 8; i++ )
-                output[i] = (unsigned char)( input[i] ^ iv[i] );
+    if (mode == MBEDTLS_DES_ENCRYPT) {
+        while (length > 0) {
+            mbedtls_xor(output, input, iv, 8);
 
-            ret = mbedtls_des_crypt_ecb( ctx, output, output );
-            if( ret != 0 )
+            ret = mbedtls_des_crypt_ecb(ctx, output, output);
+            if (ret != 0) {
                 goto exit;
-            memcpy( iv, output, 8 );
+            }
+            memcpy(iv, output, 8);
 
             input  += 8;
             output += 8;
             length -= 8;
         }
-    }
-    else /* MBEDTLS_DES_DECRYPT */
-    {
-        while( length > 0 )
-        {
-            memcpy( temp, input, 8 );
-            ret = mbedtls_des_crypt_ecb( ctx, input, output );
-            if( ret != 0 )
+    } else { /* MBEDTLS_DES_DECRYPT */
+        while (length > 0) {
+            memcpy(temp, input, 8);
+            ret = mbedtls_des_crypt_ecb(ctx, input, output);
+            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 );
+            memcpy(iv, temp, 8);
 
             input  += 8;
             output += 8;
@@ -688,7 +683,7 @@
     ret = 0;
 
 exit:
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
@@ -696,44 +691,41 @@
  * 3DES-ECB block encryption/decryption
  */
 #if !defined(MBEDTLS_DES3_CRYPT_ECB_ALT)
-int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
-                     const unsigned char input[8],
-                     unsigned char output[8] )
+int mbedtls_des3_crypt_ecb(mbedtls_des3_context *ctx,
+                           const unsigned char input[8],
+                           unsigned char output[8])
 {
     int i;
     uint32_t X, Y, T, *SK;
 
     SK = ctx->sk;
 
-    X = MBEDTLS_GET_UINT32_BE( input, 0 );
-    Y = MBEDTLS_GET_UINT32_BE( input, 4 );
+    X = MBEDTLS_GET_UINT32_BE(input, 0);
+    Y = MBEDTLS_GET_UINT32_BE(input, 4);
 
-    DES_IP( X, Y );
+    DES_IP(X, Y);
 
-    for( i = 0; i < 8; i++ )
-    {
-        DES_ROUND( Y, X );
-        DES_ROUND( X, Y );
+    for (i = 0; i < 8; i++) {
+        DES_ROUND(Y, X);
+        DES_ROUND(X, Y);
     }
 
-    for( i = 0; i < 8; i++ )
-    {
-        DES_ROUND( X, Y );
-        DES_ROUND( Y, X );
+    for (i = 0; i < 8; i++) {
+        DES_ROUND(X, Y);
+        DES_ROUND(Y, X);
     }
 
-    for( i = 0; i < 8; i++ )
-    {
-        DES_ROUND( Y, X );
-        DES_ROUND( X, Y );
+    for (i = 0; i < 8; i++) {
+        DES_ROUND(Y, X);
+        DES_ROUND(X, Y);
     }
 
-    DES_FP( Y, X );
+    DES_FP(Y, X);
 
-    MBEDTLS_PUT_UINT32_BE( Y, output, 0 );
-    MBEDTLS_PUT_UINT32_BE( X, output, 4 );
+    MBEDTLS_PUT_UINT32_BE(Y, output, 0);
+    MBEDTLS_PUT_UINT32_BE(X, output, 4);
 
-    return( 0 );
+    return 0;
 }
 #endif /* !MBEDTLS_DES3_CRYPT_ECB_ALT */
 
@@ -741,50 +733,45 @@
 /*
  * 3DES-CBC buffer encryption/decryption
  */
-int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
-                     int mode,
-                     size_t length,
-                     unsigned char iv[8],
-                     const unsigned char *input,
-                     unsigned char *output )
+int mbedtls_des3_crypt_cbc(mbedtls_des3_context *ctx,
+                           int mode,
+                           size_t length,
+                           unsigned char iv[8],
+                           const unsigned char *input,
+                           unsigned char *output)
 {
-    int i;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char temp[8];
 
-    if( length % 8 )
-        return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH );
+    if (length % 8) {
+        return MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH;
+    }
 
-    if( mode == MBEDTLS_DES_ENCRYPT )
-    {
-        while( length > 0 )
-        {
-            for( i = 0; i < 8; i++ )
-                output[i] = (unsigned char)( input[i] ^ iv[i] );
+    if (mode == MBEDTLS_DES_ENCRYPT) {
+        while (length > 0) {
+            mbedtls_xor(output, input, iv, 8);
 
-            ret = mbedtls_des3_crypt_ecb( ctx, output, output );
-            if( ret != 0 )
+            ret = mbedtls_des3_crypt_ecb(ctx, output, output);
+            if (ret != 0) {
                 goto exit;
-            memcpy( iv, output, 8 );
+            }
+            memcpy(iv, output, 8);
 
             input  += 8;
             output += 8;
             length -= 8;
         }
-    }
-    else /* MBEDTLS_DES_DECRYPT */
-    {
-        while( length > 0 )
-        {
-            memcpy( temp, input, 8 );
-            ret = mbedtls_des3_crypt_ecb( ctx, input, output );
-            if( ret != 0 )
+    } else { /* MBEDTLS_DES_DECRYPT */
+        while (length > 0) {
+            memcpy(temp, input, 8);
+            ret = mbedtls_des3_crypt_ecb(ctx, input, output);
+            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 );
+            memcpy(iv, temp, 8);
 
             input  += 8;
             output += 8;
@@ -794,7 +781,7 @@
     ret = 0;
 
 exit:
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
@@ -856,7 +843,7 @@
 /*
  * Checkup routine
  */
-int mbedtls_des_self_test( int verbose )
+int mbedtls_des_self_test(int verbose)
 {
     int i, j, u, v, ret = 0;
     mbedtls_des_context ctx;
@@ -867,194 +854,199 @@
     unsigned char iv[8];
 #endif
 
-    mbedtls_des_init( &ctx );
-    mbedtls_des3_init( &ctx3 );
+    mbedtls_des_init(&ctx);
+    mbedtls_des3_init(&ctx3);
     /*
      * ECB mode
      */
-    for( i = 0; i < 6; i++ )
-    {
+    for (i = 0; i < 6; i++) {
         u = i >> 1;
         v = i  & 1;
 
-        if( verbose != 0 )
-            mbedtls_printf( "  DES%c-ECB-%3d (%s): ",
-                             ( u == 0 ) ? ' ' : '3', 56 + u * 56,
-                             ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" );
-
-        memcpy( buf, des3_test_buf, 8 );
-
-        switch( i )
-        {
-        case 0:
-            ret = mbedtls_des_setkey_dec( &ctx, des3_test_keys );
-            break;
-
-        case 1:
-            ret = mbedtls_des_setkey_enc( &ctx, des3_test_keys );
-            break;
-
-        case 2:
-            ret = mbedtls_des3_set2key_dec( &ctx3, des3_test_keys );
-            break;
-
-        case 3:
-            ret = mbedtls_des3_set2key_enc( &ctx3, des3_test_keys );
-            break;
-
-        case 4:
-            ret = mbedtls_des3_set3key_dec( &ctx3, des3_test_keys );
-            break;
-
-        case 5:
-            ret = mbedtls_des3_set3key_enc( &ctx3, des3_test_keys );
-            break;
-
-        default:
-            return( 1 );
+        if (verbose != 0) {
+            mbedtls_printf("  DES%c-ECB-%3d (%s): ",
+                           (u == 0) ? ' ' : '3', 56 + u * 56,
+                           (v == MBEDTLS_DES_DECRYPT) ? "dec" : "enc");
         }
-        if( ret != 0 )
+
+        memcpy(buf, des3_test_buf, 8);
+
+        switch (i) {
+            case 0:
+                ret = mbedtls_des_setkey_dec(&ctx, des3_test_keys);
+                break;
+
+            case 1:
+                ret = mbedtls_des_setkey_enc(&ctx, des3_test_keys);
+                break;
+
+            case 2:
+                ret = mbedtls_des3_set2key_dec(&ctx3, des3_test_keys);
+                break;
+
+            case 3:
+                ret = mbedtls_des3_set2key_enc(&ctx3, des3_test_keys);
+                break;
+
+            case 4:
+                ret = mbedtls_des3_set3key_dec(&ctx3, des3_test_keys);
+                break;
+
+            case 5:
+                ret = mbedtls_des3_set3key_enc(&ctx3, des3_test_keys);
+                break;
+
+            default:
+                return 1;
+        }
+        if (ret != 0) {
             goto exit;
-
-        for( j = 0; j < 100; j++ )
-        {
-            if( u == 0 )
-                ret = mbedtls_des_crypt_ecb( &ctx, buf, buf );
-            else
-                ret = mbedtls_des3_crypt_ecb( &ctx3, buf, buf );
-            if( ret != 0 )
-                goto exit;
         }
 
-        if( ( v == MBEDTLS_DES_DECRYPT &&
-                memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) ||
-            ( v != MBEDTLS_DES_DECRYPT &&
-                memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "failed\n" );
+        for (j = 0; j < 100; j++) {
+            if (u == 0) {
+                ret = mbedtls_des_crypt_ecb(&ctx, buf, buf);
+            } else {
+                ret = mbedtls_des3_crypt_ecb(&ctx3, buf, buf);
+            }
+            if (ret != 0) {
+                goto exit;
+            }
+        }
+
+        if ((v == MBEDTLS_DES_DECRYPT &&
+             memcmp(buf, des3_test_ecb_dec[u], 8) != 0) ||
+            (v != MBEDTLS_DES_DECRYPT &&
+             memcmp(buf, des3_test_ecb_enc[u], 8) != 0)) {
+            if (verbose != 0) {
+                mbedtls_printf("failed\n");
+            }
 
             ret = 1;
             goto exit;
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     /*
      * CBC mode
      */
-    for( i = 0; i < 6; i++ )
-    {
+    for (i = 0; i < 6; i++) {
         u = i >> 1;
         v = i  & 1;
 
-        if( verbose != 0 )
-            mbedtls_printf( "  DES%c-CBC-%3d (%s): ",
-                             ( u == 0 ) ? ' ' : '3', 56 + u * 56,
-                             ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" );
-
-        memcpy( iv,  des3_test_iv,  8 );
-        memcpy( prv, des3_test_iv,  8 );
-        memcpy( buf, des3_test_buf, 8 );
-
-        switch( i )
-        {
-        case 0:
-            ret = mbedtls_des_setkey_dec( &ctx, des3_test_keys );
-            break;
-
-        case 1:
-            ret = mbedtls_des_setkey_enc( &ctx, des3_test_keys );
-            break;
-
-        case 2:
-            ret = mbedtls_des3_set2key_dec( &ctx3, des3_test_keys );
-            break;
-
-        case 3:
-            ret = mbedtls_des3_set2key_enc( &ctx3, des3_test_keys );
-            break;
-
-        case 4:
-            ret = mbedtls_des3_set3key_dec( &ctx3, des3_test_keys );
-            break;
-
-        case 5:
-            ret = mbedtls_des3_set3key_enc( &ctx3, des3_test_keys );
-            break;
-
-        default:
-            return( 1 );
+        if (verbose != 0) {
+            mbedtls_printf("  DES%c-CBC-%3d (%s): ",
+                           (u == 0) ? ' ' : '3', 56 + u * 56,
+                           (v == MBEDTLS_DES_DECRYPT) ? "dec" : "enc");
         }
-        if( ret != 0 )
+
+        memcpy(iv,  des3_test_iv,  8);
+        memcpy(prv, des3_test_iv,  8);
+        memcpy(buf, des3_test_buf, 8);
+
+        switch (i) {
+            case 0:
+                ret = mbedtls_des_setkey_dec(&ctx, des3_test_keys);
+                break;
+
+            case 1:
+                ret = mbedtls_des_setkey_enc(&ctx, des3_test_keys);
+                break;
+
+            case 2:
+                ret = mbedtls_des3_set2key_dec(&ctx3, des3_test_keys);
+                break;
+
+            case 3:
+                ret = mbedtls_des3_set2key_enc(&ctx3, des3_test_keys);
+                break;
+
+            case 4:
+                ret = mbedtls_des3_set3key_dec(&ctx3, des3_test_keys);
+                break;
+
+            case 5:
+                ret = mbedtls_des3_set3key_enc(&ctx3, des3_test_keys);
+                break;
+
+            default:
+                return 1;
+        }
+        if (ret != 0) {
             goto exit;
-
-        if( v == MBEDTLS_DES_DECRYPT )
-        {
-            for( j = 0; j < 100; j++ )
-            {
-                if( u == 0 )
-                    ret = mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
-                else
-                    ret = mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
-                if( ret != 0 )
-                    goto exit;
-            }
         }
-        else
-        {
-            for( j = 0; j < 100; j++ )
-            {
+
+        if (v == MBEDTLS_DES_DECRYPT) {
+            for (j = 0; j < 100; j++) {
+                if (u == 0) {
+                    ret = mbedtls_des_crypt_cbc(&ctx, v, 8, iv, buf, buf);
+                } else {
+                    ret = mbedtls_des3_crypt_cbc(&ctx3, v, 8, iv, buf, buf);
+                }
+                if (ret != 0) {
+                    goto exit;
+                }
+            }
+        } else {
+            for (j = 0; j < 100; j++) {
                 unsigned char tmp[8];
 
-                if( u == 0 )
-                    ret = mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
-                else
-                    ret = mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
-                if( ret != 0 )
+                if (u == 0) {
+                    ret = mbedtls_des_crypt_cbc(&ctx, v, 8, iv, buf, buf);
+                } else {
+                    ret = mbedtls_des3_crypt_cbc(&ctx3, v, 8, iv, buf, buf);
+                }
+                if (ret != 0) {
                     goto exit;
+                }
 
-                memcpy( tmp, prv, 8 );
-                memcpy( prv, buf, 8 );
-                memcpy( buf, tmp, 8 );
+                memcpy(tmp, prv, 8);
+                memcpy(prv, buf, 8);
+                memcpy(buf, tmp, 8);
             }
 
-            memcpy( buf, prv, 8 );
+            memcpy(buf, prv, 8);
         }
 
-        if( ( v == MBEDTLS_DES_DECRYPT &&
-                memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) ||
-            ( v != MBEDTLS_DES_DECRYPT &&
-                memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "failed\n" );
+        if ((v == MBEDTLS_DES_DECRYPT &&
+             memcmp(buf, des3_test_cbc_dec[u], 8) != 0) ||
+            (v != MBEDTLS_DES_DECRYPT &&
+             memcmp(buf, des3_test_cbc_enc[u], 8) != 0)) {
+            if (verbose != 0) {
+                mbedtls_printf("failed\n");
+            }
 
             ret = 1;
             goto exit;
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
 exit:
-    mbedtls_des_free( &ctx );
-    mbedtls_des3_free( &ctx3 );
+    mbedtls_des_free(&ctx);
+    mbedtls_des3_free(&ctx3);
 
-    if( ret != 0 )
+    if (ret != 0) {
         ret = 1;
-    return( ret );
+    }
+    return ret;
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/lib/libmbedtls/mbedtls/library/dhm.c b/lib/libmbedtls/mbedtls/library/dhm.c
index 88e148b..94137a2 100644
--- a/lib/libmbedtls/mbedtls/library/dhm.c
+++ b/lib/libmbedtls/mbedtls/library/dhm.c
@@ -43,47 +43,37 @@
 #include "mbedtls/asn1.h"
 #endif
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#include <stdio.h>
-#define mbedtls_printf     printf
-#define mbedtls_calloc    calloc
-#define mbedtls_free       free
-#endif
 
 #if !defined(MBEDTLS_DHM_ALT)
 
-#define DHM_VALIDATE_RET( cond )    \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA )
-#define DHM_VALIDATE( cond )        \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
-
 /*
  * helper to validate the mbedtls_mpi size and import it
  */
-static int dhm_read_bignum( mbedtls_mpi *X,
-                            unsigned char **p,
-                            const unsigned char *end )
+static int dhm_read_bignum(mbedtls_mpi *X,
+                           unsigned char **p,
+                           const unsigned char *end)
 {
     int ret, n;
 
-    if( end - *p < 2 )
-        return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
+    if (end - *p < 2) {
+        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
+    }
 
-    n = ( (*p)[0] << 8 ) | (*p)[1];
+    n = ((*p)[0] << 8) | (*p)[1];
     (*p) += 2;
 
-    if( (int)( end - *p ) < n )
-        return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
+    if ((int) (end - *p) < n) {
+        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
+    }
 
-    if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret ) );
+    if ((ret = mbedtls_mpi_read_binary(X, *p, n)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret);
+    }
 
     (*p) += n;
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -98,232 +88,261 @@
  *  http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
  *  http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
  */
-static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
+static int dhm_check_range(const mbedtls_mpi *param, const mbedtls_mpi *P)
 {
     mbedtls_mpi U;
     int ret = 0;
 
-    mbedtls_mpi_init( &U );
+    mbedtls_mpi_init(&U);
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&U, P, 2));
 
-    if( mbedtls_mpi_cmp_int( param, 2 ) < 0 ||
-        mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
-    {
+    if (mbedtls_mpi_cmp_int(param, 2) < 0 ||
+        mbedtls_mpi_cmp_mpi(param, &U) > 0) {
         ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
     }
 
 cleanup:
-    mbedtls_mpi_free( &U );
-    return( ret );
+    mbedtls_mpi_free(&U);
+    return ret;
 }
 
-void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
+void mbedtls_dhm_init(mbedtls_dhm_context *ctx)
 {
-    DHM_VALIDATE( ctx != NULL );
-    memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
+    memset(ctx, 0, sizeof(mbedtls_dhm_context));
+}
+
+size_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx)
+{
+    return mbedtls_mpi_bitlen(&ctx->P);
+}
+
+size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx)
+{
+    return mbedtls_mpi_size(&ctx->P);
+}
+
+int mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx,
+                          mbedtls_dhm_parameter param,
+                          mbedtls_mpi *dest)
+{
+    const mbedtls_mpi *src = NULL;
+    switch (param) {
+        case MBEDTLS_DHM_PARAM_P:
+            src = &ctx->P;
+            break;
+        case MBEDTLS_DHM_PARAM_G:
+            src = &ctx->G;
+            break;
+        case MBEDTLS_DHM_PARAM_X:
+            src = &ctx->X;
+            break;
+        case MBEDTLS_DHM_PARAM_GX:
+            src = &ctx->GX;
+            break;
+        case MBEDTLS_DHM_PARAM_GY:
+            src = &ctx->GY;
+            break;
+        case MBEDTLS_DHM_PARAM_K:
+            src = &ctx->K;
+            break;
+        default:
+            return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
+    }
+    return mbedtls_mpi_copy(dest, src);
 }
 
 /*
  * Parse the ServerKeyExchange parameters
  */
-int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
-                     unsigned char **p,
-                     const unsigned char *end )
+int mbedtls_dhm_read_params(mbedtls_dhm_context *ctx,
+                            unsigned char **p,
+                            const unsigned char *end)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    DHM_VALIDATE_RET( ctx != NULL );
-    DHM_VALIDATE_RET( p != NULL && *p != NULL );
-    DHM_VALIDATE_RET( end != NULL );
 
-    if( ( ret = dhm_read_bignum( &ctx->P,  p, end ) ) != 0 ||
-        ( ret = dhm_read_bignum( &ctx->G,  p, end ) ) != 0 ||
-        ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
-        return( ret );
+    if ((ret = dhm_read_bignum(&ctx->P,  p, end)) != 0 ||
+        (ret = dhm_read_bignum(&ctx->G,  p, end)) != 0 ||
+        (ret = dhm_read_bignum(&ctx->GY, p, end)) != 0) {
+        return ret;
+    }
 
-    if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
-        return( ret );
+    if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
+        return ret;
+    }
 
-    ctx->len = mbedtls_mpi_size( &ctx->P );
-
-    return( 0 );
+    return 0;
 }
 
 /*
  * Pick a random R in the range [2, M-2] for blinding or key generation.
  */
-static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
-                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+static int dhm_random_below(mbedtls_mpi *R, const mbedtls_mpi *M,
+                            int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
     int ret;
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_random( R, 3, M, f_rng, p_rng ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( R, R, 1 ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_random(R, 3, M, f_rng, p_rng));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(R, R, 1));
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
-static int dhm_make_common( mbedtls_dhm_context *ctx, int x_size,
-                            int (*f_rng)(void *, unsigned char *, size_t),
-                            void *p_rng )
+static int dhm_make_common(mbedtls_dhm_context *ctx, int x_size,
+                           int (*f_rng)(void *, unsigned char *, size_t),
+                           void *p_rng)
 {
     int ret = 0;
 
-    if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
-        return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
-    if( x_size < 0 )
-        return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
-
-    if( (unsigned) x_size < mbedtls_mpi_size( &ctx->P ) )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
+    if (mbedtls_mpi_cmp_int(&ctx->P, 0) == 0) {
+        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
     }
-    else
-    {
+    if (x_size < 0) {
+        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
+    }
+
+    if ((unsigned) x_size < mbedtls_mpi_size(&ctx->P)) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx->X, x_size, f_rng, p_rng));
+    } else {
         /* Generate X as large as possible ( <= P - 2 ) */
-        ret = dhm_random_below( &ctx->X, &ctx->P, f_rng, p_rng );
-        if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
-            return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
-        if( ret != 0 )
-            return( ret );
+        ret = dhm_random_below(&ctx->X, &ctx->P, f_rng, p_rng);
+        if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
+            return MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED;
+        }
+        if (ret != 0) {
+            return ret;
+        }
     }
 
     /*
      * Calculate GX = G^X mod P
      */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
-                          &ctx->P , &ctx->RP ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->GX, &ctx->G, &ctx->X,
+                                        &ctx->P, &ctx->RP));
 
-    if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
-        return( ret );
+    if ((ret = dhm_check_range(&ctx->GX, &ctx->P)) != 0) {
+        return ret;
+    }
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
  * Setup and write the ServerKeyExchange parameters
  */
-int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
-                     unsigned char *output, size_t *olen,
-                     int (*f_rng)(void *, unsigned char *, size_t),
-                     void *p_rng )
+int mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size,
+                            unsigned char *output, size_t *olen,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng)
 {
     int ret;
     size_t n1, n2, n3;
     unsigned char *p;
-    DHM_VALIDATE_RET( ctx != NULL );
-    DHM_VALIDATE_RET( output != NULL );
-    DHM_VALIDATE_RET( olen != NULL );
-    DHM_VALIDATE_RET( f_rng != NULL );
 
-    ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
-    if( ret != 0 )
+    ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
+    if (ret != 0) {
         goto cleanup;
+    }
 
     /*
      * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
      * not required". We omit leading zeros for compactness.
      */
-#define DHM_MPI_EXPORT( X, n )                                          \
+#define DHM_MPI_EXPORT(X, n)                                          \
     do {                                                                \
-        MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ),               \
-                                                   p + 2,               \
-                                                   ( n ) ) );           \
-        *p++ = MBEDTLS_BYTE_1( n );                                     \
-        *p++ = MBEDTLS_BYTE_0( n );                                     \
-        p += ( n );                                                     \
-    } while( 0 )
+        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary((X),               \
+                                                 p + 2,               \
+                                                 (n)));           \
+        *p++ = MBEDTLS_BYTE_1(n);                                     \
+        *p++ = MBEDTLS_BYTE_0(n);                                     \
+        p += (n);                                                     \
+    } while (0)
 
-    n1 = mbedtls_mpi_size( &ctx->P  );
-    n2 = mbedtls_mpi_size( &ctx->G  );
-    n3 = mbedtls_mpi_size( &ctx->GX );
+    n1 = mbedtls_mpi_size(&ctx->P);
+    n2 = mbedtls_mpi_size(&ctx->G);
+    n3 = mbedtls_mpi_size(&ctx->GX);
 
     p = output;
-    DHM_MPI_EXPORT( &ctx->P , n1 );
-    DHM_MPI_EXPORT( &ctx->G , n2 );
-    DHM_MPI_EXPORT( &ctx->GX, n3 );
+    DHM_MPI_EXPORT(&ctx->P, n1);
+    DHM_MPI_EXPORT(&ctx->G, n2);
+    DHM_MPI_EXPORT(&ctx->GX, n3);
 
     *olen = p - output;
 
-    ctx->len = n1;
-
 cleanup:
-    if( ret != 0 && ret > -128 )
-        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret );
-    return( ret );
+    if (ret != 0 && ret > -128) {
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret);
+    }
+    return ret;
 }
 
 /*
  * Set prime modulus and generator
  */
-int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
-                           const mbedtls_mpi *P,
-                           const mbedtls_mpi *G )
+int mbedtls_dhm_set_group(mbedtls_dhm_context *ctx,
+                          const mbedtls_mpi *P,
+                          const mbedtls_mpi *G)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    DHM_VALIDATE_RET( ctx != NULL );
-    DHM_VALIDATE_RET( P != NULL );
-    DHM_VALIDATE_RET( G != NULL );
 
-    if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
-        ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
-    {
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret ) );
+    if ((ret = mbedtls_mpi_copy(&ctx->P, P)) != 0 ||
+        (ret = mbedtls_mpi_copy(&ctx->G, G)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret);
     }
 
-    ctx->len = mbedtls_mpi_size( &ctx->P );
-    return( 0 );
+    return 0;
 }
 
 /*
  * Import the peer's public value G^Y
  */
-int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
-                     const unsigned char *input, size_t ilen )
+int mbedtls_dhm_read_public(mbedtls_dhm_context *ctx,
+                            const unsigned char *input, size_t ilen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    DHM_VALIDATE_RET( ctx != NULL );
-    DHM_VALIDATE_RET( input != NULL );
 
-    if( ilen < 1 || ilen > ctx->len )
-        return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
+    if (ilen < 1 || ilen > mbedtls_dhm_get_len(ctx)) {
+        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
+    }
 
-    if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret ) );
+    if ((ret = mbedtls_mpi_read_binary(&ctx->GY, input, ilen)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret);
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Create own private value X and export G^X
  */
-int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
-                     unsigned char *output, size_t olen,
-                     int (*f_rng)(void *, unsigned char *, size_t),
-                     void *p_rng )
+int mbedtls_dhm_make_public(mbedtls_dhm_context *ctx, int x_size,
+                            unsigned char *output, size_t olen,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng)
 {
     int ret;
-    DHM_VALIDATE_RET( ctx != NULL );
-    DHM_VALIDATE_RET( output != NULL );
-    DHM_VALIDATE_RET( f_rng != NULL );
 
-    if( olen < 1 || olen > ctx->len )
-        return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
+    if (olen < 1 || olen > mbedtls_dhm_get_len(ctx)) {
+        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
+    }
 
-    ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
-    if( ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED )
-        return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
-    if( ret != 0 )
+    ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
+    if (ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) {
+        return MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED;
+    }
+    if (ret != 0) {
         goto cleanup;
+    }
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->GX, output, olen));
 
 cleanup:
-    if( ret != 0 && ret > -128 )
-        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret );
-    return( ret );
+    if (ret != 0 && ret > -128) {
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret);
+    }
+    return ret;
 }
 
 
@@ -333,40 +352,38 @@
  *  DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
  *  Berlin Heidelberg, 1996. p. 104-113.
  */
-static int dhm_update_blinding( mbedtls_dhm_context *ctx,
-                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+static int dhm_update_blinding(mbedtls_dhm_context *ctx,
+                               int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
     int ret;
     mbedtls_mpi R;
 
-    mbedtls_mpi_init( &R );
+    mbedtls_mpi_init(&R);
 
     /*
      * Don't use any blinding the first time a particular X is used,
      * but remember it to use blinding next time.
      */
-    if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
+    if (mbedtls_mpi_cmp_mpi(&ctx->X, &ctx->pX) != 0) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&ctx->pX, &ctx->X));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vi, 1));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vf, 1));
 
-        return( 0 );
+        return 0;
     }
 
     /*
      * Ok, we need blinding. Can we re-use existing values?
      * If yes, just update them by squaring them.
      */
-    if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
+    if (mbedtls_mpi_cmp_int(&ctx->Vi, 1) != 0) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &ctx->Vi));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->P));
 
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &ctx->Vf));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
 
-        return( 0 );
+        return 0;
     }
 
     /*
@@ -374,111 +391,108 @@
      */
 
     /* Vi = random( 2, P-2 ) */
-    MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
+    MBEDTLS_MPI_CHK(dhm_random_below(&ctx->Vi, &ctx->P, f_rng, p_rng));
 
     /* Vf = Vi^-X mod P
      * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
      * then elevate to the Xth power. */
-    MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
+    MBEDTLS_MPI_CHK(dhm_random_below(&R, &ctx->P, f_rng, p_rng));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vi, &R));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&ctx->Vf, &ctx->Vf, &ctx->P));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &R));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP));
 
 cleanup:
-    mbedtls_mpi_free( &R );
+    mbedtls_mpi_free(&R);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Derive and export the shared secret (G^Y)^X mod P
  */
-int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
-                     unsigned char *output, size_t output_size, size_t *olen,
-                     int (*f_rng)(void *, unsigned char *, size_t),
-                     void *p_rng )
+int mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx,
+                            unsigned char *output, size_t output_size, size_t *olen,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_mpi GYb;
-    DHM_VALIDATE_RET( ctx != NULL );
-    DHM_VALIDATE_RET( output != NULL );
-    DHM_VALIDATE_RET( olen != NULL );
 
-    if( output_size < ctx->len )
-        return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
+    if (f_rng == NULL) {
+        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
+    }
 
-    if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
-        return( ret );
+    if (output_size < mbedtls_dhm_get_len(ctx)) {
+        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
+    }
 
-    mbedtls_mpi_init( &GYb );
+    if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
+        return ret;
+    }
+
+    mbedtls_mpi_init(&GYb);
 
     /* Blind peer's value */
-    if( f_rng != NULL )
-    {
-        MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
-    }
-    else
-        MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
+    MBEDTLS_MPI_CHK(dhm_update_blinding(ctx, f_rng, p_rng));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&GYb, &ctx->GY, &ctx->Vi));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&GYb, &GYb, &ctx->P));
 
     /* Do modular exponentiation */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
-                          &ctx->P, &ctx->RP ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->K, &GYb, &ctx->X,
+                                        &ctx->P, &ctx->RP));
 
     /* Unblind secret value */
-    if( f_rng != NULL )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
-    }
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->K, &ctx->K, &ctx->Vf));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->K, &ctx->K, &ctx->P));
 
     /* Output the secret without any leading zero byte. This is mandatory
      * for TLS per RFC 5246 §8.1.2. */
-    *olen = mbedtls_mpi_size( &ctx->K );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
+    *olen = mbedtls_mpi_size(&ctx->K);
+    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->K, output, *olen));
 
 cleanup:
-    mbedtls_mpi_free( &GYb );
+    mbedtls_mpi_free(&GYb);
 
-    if( ret != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret ) );
+    if (ret != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret);
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Free the components of a DHM key
  */
-void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
+void mbedtls_dhm_free(mbedtls_dhm_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_mpi_free( &ctx->pX );
-    mbedtls_mpi_free( &ctx->Vf );
-    mbedtls_mpi_free( &ctx->Vi );
-    mbedtls_mpi_free( &ctx->RP );
-    mbedtls_mpi_free( &ctx->K  );
-    mbedtls_mpi_free( &ctx->GY );
-    mbedtls_mpi_free( &ctx->GX );
-    mbedtls_mpi_free( &ctx->X  );
-    mbedtls_mpi_free( &ctx->G  );
-    mbedtls_mpi_free( &ctx->P  );
+    mbedtls_mpi_free(&ctx->pX);
+    mbedtls_mpi_free(&ctx->Vf);
+    mbedtls_mpi_free(&ctx->Vi);
+    mbedtls_mpi_free(&ctx->RP);
+    mbedtls_mpi_free(&ctx->K);
+    mbedtls_mpi_free(&ctx->GY);
+    mbedtls_mpi_free(&ctx->GX);
+    mbedtls_mpi_free(&ctx->X);
+    mbedtls_mpi_free(&ctx->G);
+    mbedtls_mpi_free(&ctx->P);
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_dhm_context));
 }
 
 #if defined(MBEDTLS_ASN1_PARSE_C)
 /*
  * Parse DHM parameters
  */
-int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
-                   size_t dhminlen )
+int mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm, const unsigned char *dhmin,
+                          size_t dhminlen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
@@ -487,32 +501,29 @@
     mbedtls_pem_context pem;
 #endif /* MBEDTLS_PEM_PARSE_C */
 
-    DHM_VALIDATE_RET( dhm != NULL );
-    DHM_VALIDATE_RET( dhmin != NULL );
-
 #if defined(MBEDTLS_PEM_PARSE_C)
-    mbedtls_pem_init( &pem );
+    mbedtls_pem_init(&pem);
 
     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
-    if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
+    if (dhminlen == 0 || dhmin[dhminlen - 1] != '\0') {
         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
-    else
-        ret = mbedtls_pem_read_buffer( &pem,
-                               "-----BEGIN DH PARAMETERS-----",
-                               "-----END DH PARAMETERS-----",
-                               dhmin, NULL, 0, &dhminlen );
+    } else {
+        ret = mbedtls_pem_read_buffer(&pem,
+                                      "-----BEGIN DH PARAMETERS-----",
+                                      "-----END DH PARAMETERS-----",
+                                      dhmin, NULL, 0, &dhminlen);
+    }
 
-    if( ret == 0 )
-    {
+    if (ret == 0) {
         /*
          * Was PEM encoded
          */
         dhminlen = pem.buflen;
-    }
-    else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
+    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
         goto exit;
+    }
 
-    p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
+    p = (ret == 0) ? pem.buf : (unsigned char *) dhmin;
 #else
     p = (unsigned char *) dhmin;
 #endif /* MBEDTLS_PEM_PARSE_C */
@@ -525,55 +536,49 @@
      *      privateValueLength INTEGER OPTIONAL
      *  }
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
         goto exit;
     }
 
     end = p + len;
 
-    if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P  ) ) != 0 ||
-        ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
-    {
-        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
+    if ((ret = mbedtls_asn1_get_mpi(&p, end, &dhm->P)) != 0 ||
+        (ret = mbedtls_asn1_get_mpi(&p, end, &dhm->G)) != 0) {
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
         goto exit;
     }
 
-    if( p != end )
-    {
+    if (p != end) {
         /* This might be the optional privateValueLength.
          * If so, we can cleanly discard it */
         mbedtls_mpi rec;
-        mbedtls_mpi_init( &rec );
-        ret = mbedtls_asn1_get_mpi( &p, end, &rec );
-        mbedtls_mpi_free( &rec );
-        if ( ret != 0 )
-        {
-            ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
+        mbedtls_mpi_init(&rec);
+        ret = mbedtls_asn1_get_mpi(&p, end, &rec);
+        mbedtls_mpi_free(&rec);
+        if (ret != 0) {
+            ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
             goto exit;
         }
-        if ( p != end )
-        {
-            ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+        if (p != end) {
+            ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT,
+                                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
             goto exit;
         }
     }
 
     ret = 0;
 
-    dhm->len = mbedtls_mpi_size( &dhm->P );
-
 exit:
 #if defined(MBEDTLS_PEM_PARSE_C)
-    mbedtls_pem_free( &pem );
+    mbedtls_pem_free(&pem);
 #endif
-    if( ret != 0 )
-        mbedtls_dhm_free( dhm );
+    if (ret != 0) {
+        mbedtls_dhm_free(dhm);
+    }
 
-    return( ret );
+    return ret;
 }
 
 #if defined(MBEDTLS_FS_IO)
@@ -584,71 +589,70 @@
  * A terminating null byte is always appended. It is included in the announced
  * length only if the data looks like it is PEM encoded.
  */
-static int load_file( const char *path, unsigned char **buf, size_t *n )
+static int load_file(const char *path, unsigned char **buf, size_t *n)
 {
     FILE *f;
     long size;
 
-    if( ( f = fopen( path, "rb" ) ) == NULL )
-        return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
-
-    fseek( f, 0, SEEK_END );
-    if( ( size = ftell( f ) ) == -1 )
-    {
-        fclose( f );
-        return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
+    if ((f = fopen(path, "rb")) == NULL) {
+        return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
     }
-    fseek( f, 0, SEEK_SET );
+    /* The data loaded here is public, so don't bother disabling buffering. */
+
+    fseek(f, 0, SEEK_END);
+    if ((size = ftell(f)) == -1) {
+        fclose(f);
+        return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
+    }
+    fseek(f, 0, SEEK_SET);
 
     *n = (size_t) size;
 
-    if( *n + 1 == 0 ||
-        ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
-    {
-        fclose( f );
-        return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
+    if (*n + 1 == 0 ||
+        (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
+        fclose(f);
+        return MBEDTLS_ERR_DHM_ALLOC_FAILED;
     }
 
-    if( fread( *buf, 1, *n, f ) != *n )
-    {
-        fclose( f );
+    if (fread(*buf, 1, *n, f) != *n) {
+        fclose(f);
 
-        mbedtls_platform_zeroize( *buf, *n + 1 );
-        mbedtls_free( *buf );
+        mbedtls_platform_zeroize(*buf, *n + 1);
+        mbedtls_free(*buf);
 
-        return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
+        return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
     }
 
-    fclose( f );
+    fclose(f);
 
     (*buf)[*n] = '\0';
 
-    if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
+    if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
         ++*n;
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Load and parse DHM parameters
  */
-int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
+int mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
     unsigned char *buf;
-    DHM_VALIDATE_RET( dhm != NULL );
-    DHM_VALIDATE_RET( path != NULL );
 
-    if( ( ret = load_file( path, &buf, &n ) ) != 0 )
-        return( ret );
+    if ((ret = load_file(path, &buf, &n)) != 0) {
+        return ret;
+    }
 
-    ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
+    ret = mbedtls_dhm_parse_dhm(dhm, buf, n);
 
-    mbedtls_platform_zeroize( buf, n );
-    mbedtls_free( buf );
+    mbedtls_platform_zeroize(buf, n);
+    mbedtls_free(buf);
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_FS_IO */
 #endif /* MBEDTLS_ASN1_PARSE_C */
@@ -658,60 +662,63 @@
 
 #if defined(MBEDTLS_PEM_PARSE_C)
 static const char mbedtls_test_dhm_params[] =
-"-----BEGIN DH PARAMETERS-----\r\n"
-"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
-"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
-"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
-"-----END DH PARAMETERS-----\r\n";
+    "-----BEGIN DH PARAMETERS-----\r\n"
+    "MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
+    "1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
+    "9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
+    "-----END DH PARAMETERS-----\r\n";
 #else /* MBEDTLS_PEM_PARSE_C */
 static const char mbedtls_test_dhm_params[] = {
-  0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
-  0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
-  0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
-  0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
-  0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
-  0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
-  0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
-  0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
-  0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
-  0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
-  0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
-  0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 };
+    0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
+    0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
+    0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
+    0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
+    0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
+    0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
+    0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
+    0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
+    0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
+    0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
+    0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
+    0x49, 0x75, 0xb3, 0x02, 0x01, 0x02
+};
 #endif /* MBEDTLS_PEM_PARSE_C */
 
-static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
+static const size_t mbedtls_test_dhm_params_len = sizeof(mbedtls_test_dhm_params);
 
 /*
  * Checkup routine
  */
-int mbedtls_dhm_self_test( int verbose )
+int mbedtls_dhm_self_test(int verbose)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_dhm_context dhm;
 
-    mbedtls_dhm_init( &dhm );
+    mbedtls_dhm_init(&dhm);
 
-    if( verbose != 0 )
-        mbedtls_printf( "  DHM parameter load: " );
+    if (verbose != 0) {
+        mbedtls_printf("  DHM parameter load: ");
+    }
 
-    if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
-                    (const unsigned char *) mbedtls_test_dhm_params,
-                    mbedtls_test_dhm_params_len ) ) != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
+    if ((ret = mbedtls_dhm_parse_dhm(&dhm,
+                                     (const unsigned char *) mbedtls_test_dhm_params,
+                                     mbedtls_test_dhm_params_len)) != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("failed\n");
+        }
 
         ret = 1;
         goto exit;
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n\n");
+    }
 
 exit:
-    mbedtls_dhm_free( &dhm );
+    mbedtls_dhm_free(&dhm);
 
-    return( ret );
+    return ret;
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/lib/libmbedtls/mbedtls/library/ecdh.c b/lib/libmbedtls/mbedtls/library/ecdh.c
index 60c6e42..b529af5 100644
--- a/lib/libmbedtls/mbedtls/library/ecdh.c
+++ b/lib/libmbedtls/mbedtls/library/ecdh.c
@@ -34,31 +34,25 @@
 
 #include <string.h>
 
-/* Parameter validation macros based on platform_util.h */
-#define ECDH_VALIDATE_RET( cond )    \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
-#define ECDH_VALIDATE( cond )        \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
-
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
 typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
 #endif
 
 static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
-    const mbedtls_ecdh_context *ctx )
+    const mbedtls_ecdh_context *ctx)
 {
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
-    return( ctx->grp.id );
+    return ctx->grp.id;
 #else
-    return( ctx->grp_id );
+    return ctx->grp_id;
 #endif
 }
 
-int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid )
+int mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid)
 {
     /* At this time, all groups support ECDH. */
     (void) gid;
-    return( 1 );
+    return 1;
 }
 
 #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
@@ -69,39 +63,38 @@
  * the output parameter 'd' across continuation calls. This would not be
  * acceptable for a public function but is OK here as we control call sites.
  */
-static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
-                    mbedtls_mpi *d, mbedtls_ecp_point *Q,
-                    int (*f_rng)(void *, unsigned char *, size_t),
-                    void *p_rng,
-                    mbedtls_ecp_restart_ctx *rs_ctx )
+static int ecdh_gen_public_restartable(mbedtls_ecp_group *grp,
+                                       mbedtls_mpi *d, mbedtls_ecp_point *Q,
+                                       int (*f_rng)(void *, unsigned char *, size_t),
+                                       void *p_rng,
+                                       mbedtls_ecp_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    /* If multiplication is in progress, we already generated a privkey */
+    int restarting = 0;
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx == NULL || rs_ctx->rsm == NULL )
+    restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL);
 #endif
-        MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
+    /* If multiplication is in progress, we already generated a privkey */
+    if (!restarting) {
+        MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng));
+    }
 
-    MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G,
-                                                  f_rng, p_rng, rs_ctx ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G,
+                                                f_rng, p_rng, rs_ctx));
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
  * Generate public key
  */
-int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
-                     int (*f_rng)(void *, unsigned char *, size_t),
-                     void *p_rng )
+int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng)
 {
-    ECDH_VALIDATE_RET( grp != NULL );
-    ECDH_VALIDATE_RET( d != NULL );
-    ECDH_VALIDATE_RET( Q != NULL );
-    ECDH_VALIDATE_RET( f_rng != NULL );
-    return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) );
+    return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL);
 }
 #endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
 
@@ -109,79 +102,72 @@
 /*
  * Compute shared secret (SEC1 3.3.1)
  */
-static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp,
-                         mbedtls_mpi *z,
-                         const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
-                         int (*f_rng)(void *, unsigned char *, size_t),
-                         void *p_rng,
-                         mbedtls_ecp_restart_ctx *rs_ctx )
+static int ecdh_compute_shared_restartable(mbedtls_ecp_group *grp,
+                                           mbedtls_mpi *z,
+                                           const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
+                                           int (*f_rng)(void *, unsigned char *, size_t),
+                                           void *p_rng,
+                                           mbedtls_ecp_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecp_point P;
 
-    mbedtls_ecp_point_init( &P );
+    mbedtls_ecp_point_init(&P);
 
-    MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q,
-                                                  f_rng, p_rng, rs_ctx ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &P, d, Q,
+                                                f_rng, p_rng, rs_ctx));
 
-    if( mbedtls_ecp_is_zero( &P ) )
-    {
+    if (mbedtls_ecp_is_zero(&P)) {
         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
         goto cleanup;
     }
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X));
 
 cleanup:
-    mbedtls_ecp_point_free( &P );
+    mbedtls_ecp_point_free(&P);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Compute shared secret (SEC1 3.3.1)
  */
-int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
-                         const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
-                         int (*f_rng)(void *, unsigned char *, size_t),
-                         void *p_rng )
+int mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z,
+                                const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
+                                int (*f_rng)(void *, unsigned char *, size_t),
+                                void *p_rng)
 {
-    ECDH_VALIDATE_RET( grp != NULL );
-    ECDH_VALIDATE_RET( Q != NULL );
-    ECDH_VALIDATE_RET( d != NULL );
-    ECDH_VALIDATE_RET( z != NULL );
-    return( ecdh_compute_shared_restartable( grp, z, Q, d,
-                                             f_rng, p_rng, NULL ) );
+    return ecdh_compute_shared_restartable(grp, z, Q, d,
+                                           f_rng, p_rng, NULL);
 }
 #endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
 
-static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx )
+static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx)
 {
-    mbedtls_ecp_group_init( &ctx->grp );
-    mbedtls_mpi_init( &ctx->d  );
-    mbedtls_ecp_point_init( &ctx->Q   );
-    mbedtls_ecp_point_init( &ctx->Qp  );
-    mbedtls_mpi_init( &ctx->z  );
+    mbedtls_ecp_group_init(&ctx->grp);
+    mbedtls_mpi_init(&ctx->d);
+    mbedtls_ecp_point_init(&ctx->Q);
+    mbedtls_ecp_point_init(&ctx->Qp);
+    mbedtls_mpi_init(&ctx->z);
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    mbedtls_ecp_restart_init( &ctx->rs );
+    mbedtls_ecp_restart_init(&ctx->rs);
 #endif
 }
 
 /*
  * Initialize context
  */
-void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
+void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx)
 {
-    ECDH_VALIDATE( ctx != NULL );
-
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
-    ecdh_init_internal( ctx );
-    mbedtls_ecp_point_init( &ctx->Vi  );
-    mbedtls_ecp_point_init( &ctx->Vf  );
-    mbedtls_mpi_init( &ctx->_d );
+    ecdh_init_internal(ctx);
+    mbedtls_ecp_point_init(&ctx->Vi);
+    mbedtls_ecp_point_init(&ctx->Vf);
+    mbedtls_mpi_init(&ctx->_d);
 #else
-    memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
+    memset(ctx, 0, sizeof(mbedtls_ecdh_context));
 
     ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
 #endif
@@ -191,59 +177,55 @@
 #endif
 }
 
-static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx,
-                                mbedtls_ecp_group_id grp_id )
+static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx,
+                               mbedtls_ecp_group_id grp_id)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    ret = mbedtls_ecp_group_load( &ctx->grp, grp_id );
-    if( ret != 0 )
-    {
-        return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+    ret = mbedtls_ecp_group_load(&ctx->grp, grp_id);
+    if (ret != 0) {
+        return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Setup context
  */
-int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id )
+int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id)
 {
-    ECDH_VALIDATE_RET( ctx != NULL );
-
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
-    return( ecdh_setup_internal( ctx, grp_id ) );
+    return ecdh_setup_internal(ctx, grp_id);
 #else
-    switch( grp_id )
-    {
+    switch (grp_id) {
 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
         case MBEDTLS_ECP_DP_CURVE25519:
             ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
             ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
             ctx->grp_id = grp_id;
-            return( mbedtls_everest_setup( &ctx->ctx.everest_ecdh, grp_id ) );
+            return mbedtls_everest_setup(&ctx->ctx.everest_ecdh, grp_id);
 #endif
         default:
             ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
             ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
             ctx->grp_id = grp_id;
-            ecdh_init_internal( &ctx->ctx.mbed_ecdh );
-            return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) );
+            ecdh_init_internal(&ctx->ctx.mbed_ecdh);
+            return ecdh_setup_internal(&ctx->ctx.mbed_ecdh, grp_id);
     }
 #endif
 }
 
-static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx )
+static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx)
 {
-    mbedtls_ecp_group_free( &ctx->grp );
-    mbedtls_mpi_free( &ctx->d  );
-    mbedtls_ecp_point_free( &ctx->Q   );
-    mbedtls_ecp_point_free( &ctx->Qp  );
-    mbedtls_mpi_free( &ctx->z  );
+    mbedtls_ecp_group_free(&ctx->grp);
+    mbedtls_mpi_free(&ctx->d);
+    mbedtls_ecp_point_free(&ctx->Q);
+    mbedtls_ecp_point_free(&ctx->Qp);
+    mbedtls_mpi_free(&ctx->z);
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    mbedtls_ecp_restart_free( &ctx->rs );
+    mbedtls_ecp_restart_free(&ctx->rs);
 #endif
 }
 
@@ -251,10 +233,8 @@
 /*
  * Enable restartable operations for context
  */
-void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx )
+void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx)
 {
-    ECDH_VALIDATE( ctx != NULL );
-
     ctx->restart_enabled = 1;
 }
 #endif
@@ -262,26 +242,26 @@
 /*
  * Free context
  */
-void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
+void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
-    mbedtls_ecp_point_free( &ctx->Vi );
-    mbedtls_ecp_point_free( &ctx->Vf );
-    mbedtls_mpi_free( &ctx->_d );
-    ecdh_free_internal( ctx );
+    mbedtls_ecp_point_free(&ctx->Vi);
+    mbedtls_ecp_point_free(&ctx->Vf);
+    mbedtls_mpi_free(&ctx->_d);
+    ecdh_free_internal(ctx);
 #else
-    switch( ctx->var )
-    {
+    switch (ctx->var) {
 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
         case MBEDTLS_ECDH_VARIANT_EVEREST:
-            mbedtls_everest_free( &ctx->ctx.everest_ecdh );
+            mbedtls_everest_free(&ctx->ctx.everest_ecdh);
             break;
 #endif
         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
-            ecdh_free_internal( &ctx->ctx.mbed_ecdh );
+            ecdh_free_internal(&ctx->ctx.mbed_ecdh);
             break;
         default:
             break;
@@ -293,14 +273,14 @@
 #endif
 }
 
-static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx,
-                                      size_t *olen, int point_format,
-                                      unsigned char *buf, size_t blen,
-                                      int (*f_rng)(void *,
-                                                   unsigned char *,
-                                                   size_t),
-                                      void *p_rng,
-                                      int restart_enabled )
+static int ecdh_make_params_internal(mbedtls_ecdh_context_mbed *ctx,
+                                     size_t *olen, int point_format,
+                                     unsigned char *buf, size_t blen,
+                                     int (*f_rng)(void *,
+                                                  unsigned char *,
+                                                  size_t),
+                                     void *p_rng,
+                                     int restart_enabled)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t grp_len, pt_len;
@@ -308,40 +288,46 @@
     mbedtls_ecp_restart_ctx *rs_ctx = NULL;
 #endif
 
-    if( ctx->grp.pbits == 0 )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (ctx->grp.pbits == 0) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( restart_enabled )
+    if (restart_enabled) {
         rs_ctx = &ctx->rs;
+    }
 #else
     (void) restart_enabled;
 #endif
 
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
-                                             f_rng, p_rng, rs_ctx ) ) != 0 )
-        return( ret );
+    if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
+                                           f_rng, p_rng, rs_ctx)) != 0) {
+        return ret;
+    }
 #else
-    if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
-                                         f_rng, p_rng ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
+                                       f_rng, p_rng)) != 0) {
+        return ret;
+    }
 #endif /* MBEDTLS_ECP_RESTARTABLE */
 
-    if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf,
-                                             blen ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf,
+                                           blen)) != 0) {
+        return ret;
+    }
 
     buf += grp_len;
     blen -= grp_len;
 
-    if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format,
-                                             &pt_len, buf, blen ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format,
+                                           &pt_len, buf, blen)) != 0) {
+        return ret;
+    }
 
     *olen = grp_len + pt_len;
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -351,17 +337,12 @@
  *          ECPoint         public;
  *      } ServerECDHParams;
  */
-int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
-                              unsigned char *buf, size_t blen,
-                              int (*f_rng)(void *, unsigned char *, size_t),
-                              void *p_rng )
+int mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen,
+                             unsigned char *buf, size_t blen,
+                             int (*f_rng)(void *, unsigned char *, size_t),
+                             void *p_rng)
 {
     int restart_enabled = 0;
-    ECDH_VALIDATE_RET( ctx != NULL );
-    ECDH_VALIDATE_RET( olen != NULL );
-    ECDH_VALIDATE_RET( buf != NULL );
-    ECDH_VALIDATE_RET( f_rng != NULL );
-
 #if defined(MBEDTLS_ECP_RESTARTABLE)
     restart_enabled = ctx->restart_enabled;
 #else
@@ -369,33 +350,32 @@
 #endif
 
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
-    return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen,
-                                       f_rng, p_rng, restart_enabled ) );
+    return ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen,
+                                     f_rng, p_rng, restart_enabled);
 #else
-    switch( ctx->var )
-    {
+    switch (ctx->var) {
 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
         case MBEDTLS_ECDH_VARIANT_EVEREST:
-            return( mbedtls_everest_make_params( &ctx->ctx.everest_ecdh, olen,
-                                                 buf, blen, f_rng, p_rng ) );
+            return mbedtls_everest_make_params(&ctx->ctx.everest_ecdh, olen,
+                                               buf, blen, f_rng, p_rng);
 #endif
         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
-            return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen,
-                                               ctx->point_format, buf, blen,
-                                               f_rng, p_rng,
-                                               restart_enabled ) );
+            return ecdh_make_params_internal(&ctx->ctx.mbed_ecdh, olen,
+                                             ctx->point_format, buf, blen,
+                                             f_rng, p_rng,
+                                             restart_enabled);
         default:
             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
     }
 #endif
 }
 
-static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx,
-                                      const unsigned char **buf,
-                                      const unsigned char *end )
+static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx,
+                                     const unsigned char **buf,
+                                     const unsigned char *end)
 {
-    return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf,
-                                        end - *buf ) );
+    return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf,
+                                      end - *buf);
 }
 
 /*
@@ -405,325 +385,313 @@
  *          ECPoint         public;
  *      } ServerECDHParams;
  */
-int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
-                              const unsigned char **buf,
-                              const unsigned char *end )
+int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,
+                             const unsigned char **buf,
+                             const unsigned char *end)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecp_group_id grp_id;
-    ECDH_VALIDATE_RET( ctx != NULL );
-    ECDH_VALIDATE_RET( buf != NULL );
-    ECDH_VALIDATE_RET( *buf != NULL );
-    ECDH_VALIDATE_RET( end != NULL );
+    if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, end - *buf))
+        != 0) {
+        return ret;
+    }
 
-    if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) )
-            != 0 )
-        return( ret );
-
-    if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0) {
+        return ret;
+    }
 
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
-    return( ecdh_read_params_internal( ctx, buf, end ) );
+    return ecdh_read_params_internal(ctx, buf, end);
 #else
-    switch( ctx->var )
-    {
+    switch (ctx->var) {
 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
         case MBEDTLS_ECDH_VARIANT_EVEREST:
-            return( mbedtls_everest_read_params( &ctx->ctx.everest_ecdh,
-                                                 buf, end) );
+            return mbedtls_everest_read_params(&ctx->ctx.everest_ecdh,
+                                               buf, end);
 #endif
         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
-            return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh,
-                                               buf, end ) );
+            return ecdh_read_params_internal(&ctx->ctx.mbed_ecdh,
+                                             buf, end);
         default:
             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
     }
 #endif
 }
 
-static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx,
-                                     const mbedtls_ecp_keypair *key,
-                                     mbedtls_ecdh_side side )
+static int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx,
+                                    const mbedtls_ecp_keypair *key,
+                                    mbedtls_ecdh_side side)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     /* If it's not our key, just import the public part as Qp */
-    if( side == MBEDTLS_ECDH_THEIRS )
-        return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) );
+    if (side == MBEDTLS_ECDH_THEIRS) {
+        return mbedtls_ecp_copy(&ctx->Qp, &key->Q);
+    }
 
     /* Our key: import public (as Q) and private parts */
-    if( side != MBEDTLS_ECDH_OURS )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (side != MBEDTLS_ECDH_OURS) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
-    if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ||
-        ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 ||
+        (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) {
+        return ret;
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Get parameters from a keypair
  */
-int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx,
-                             const mbedtls_ecp_keypair *key,
-                             mbedtls_ecdh_side side )
+int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx,
+                            const mbedtls_ecp_keypair *key,
+                            mbedtls_ecdh_side side)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    ECDH_VALIDATE_RET( ctx != NULL );
-    ECDH_VALIDATE_RET( key != NULL );
-    ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS ||
-                       side == MBEDTLS_ECDH_THEIRS );
+    if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
-    if( mbedtls_ecdh_grp_id( ctx ) == MBEDTLS_ECP_DP_NONE )
-    {
+    if (mbedtls_ecdh_grp_id(ctx) == MBEDTLS_ECP_DP_NONE) {
         /* This is the first call to get_params(). Set up the context
          * for use with the group. */
-        if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 )
-            return( ret );
-    }
-    else
-    {
+        if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0) {
+            return ret;
+        }
+    } else {
         /* This is not the first call to get_params(). Check that the
          * current key's group is the same as the context's, which was set
          * from the first key's group. */
-        if( mbedtls_ecdh_grp_id( ctx ) != key->grp.id )
-            return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+        if (mbedtls_ecdh_grp_id(ctx) != key->grp.id) {
+            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+        }
     }
 
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
-    return( ecdh_get_params_internal( ctx, key, side ) );
+    return ecdh_get_params_internal(ctx, key, side);
 #else
-    switch( ctx->var )
-    {
+    switch (ctx->var) {
 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
         case MBEDTLS_ECDH_VARIANT_EVEREST:
         {
             mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
-                                                   MBEDTLS_EVEREST_ECDH_OURS :
-                                                   MBEDTLS_EVEREST_ECDH_THEIRS;
-            return( mbedtls_everest_get_params( &ctx->ctx.everest_ecdh,
-                                                key, s) );
+                                          MBEDTLS_EVEREST_ECDH_OURS :
+                                          MBEDTLS_EVEREST_ECDH_THEIRS;
+            return mbedtls_everest_get_params(&ctx->ctx.everest_ecdh,
+                                              key, s);
         }
 #endif
         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
-            return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh,
-                                              key, side ) );
+            return ecdh_get_params_internal(&ctx->ctx.mbed_ecdh,
+                                            key, side);
         default:
             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
     }
 #endif
 }
 
-static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx,
-                                      size_t *olen, int point_format,
-                                      unsigned char *buf, size_t blen,
-                                      int (*f_rng)(void *,
-                                                   unsigned char *,
-                                                   size_t),
-                                      void *p_rng,
-                                      int restart_enabled )
+static int ecdh_make_public_internal(mbedtls_ecdh_context_mbed *ctx,
+                                     size_t *olen, int point_format,
+                                     unsigned char *buf, size_t blen,
+                                     int (*f_rng)(void *,
+                                                  unsigned char *,
+                                                  size_t),
+                                     void *p_rng,
+                                     int restart_enabled)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 #if defined(MBEDTLS_ECP_RESTARTABLE)
     mbedtls_ecp_restart_ctx *rs_ctx = NULL;
 #endif
 
-    if( ctx->grp.pbits == 0 )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (ctx->grp.pbits == 0) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( restart_enabled )
+    if (restart_enabled) {
         rs_ctx = &ctx->rs;
+    }
 #else
     (void) restart_enabled;
 #endif
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
-                                             f_rng, p_rng, rs_ctx ) ) != 0 )
-        return( ret );
+    if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
+                                           f_rng, p_rng, rs_ctx)) != 0) {
+        return ret;
+    }
 #else
-    if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
-                                         f_rng, p_rng ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
+                                       f_rng, p_rng)) != 0) {
+        return ret;
+    }
 #endif /* MBEDTLS_ECP_RESTARTABLE */
 
-    return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen,
-                                        buf, blen );
+    return mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, olen,
+                                       buf, blen);
 }
 
 /*
  * Setup and export the client public value
  */
-int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
-                              unsigned char *buf, size_t blen,
-                              int (*f_rng)(void *, unsigned char *, size_t),
-                              void *p_rng )
+int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen,
+                             unsigned char *buf, size_t blen,
+                             int (*f_rng)(void *, unsigned char *, size_t),
+                             void *p_rng)
 {
     int restart_enabled = 0;
-    ECDH_VALIDATE_RET( ctx != NULL );
-    ECDH_VALIDATE_RET( olen != NULL );
-    ECDH_VALIDATE_RET( buf != NULL );
-    ECDH_VALIDATE_RET( f_rng != NULL );
-
 #if defined(MBEDTLS_ECP_RESTARTABLE)
     restart_enabled = ctx->restart_enabled;
 #endif
 
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
-    return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen,
-                                       f_rng, p_rng, restart_enabled ) );
+    return ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen,
+                                     f_rng, p_rng, restart_enabled);
 #else
-    switch( ctx->var )
-    {
+    switch (ctx->var) {
 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
         case MBEDTLS_ECDH_VARIANT_EVEREST:
-            return( mbedtls_everest_make_public( &ctx->ctx.everest_ecdh, olen,
-                                                 buf, blen, f_rng, p_rng ) );
+            return mbedtls_everest_make_public(&ctx->ctx.everest_ecdh, olen,
+                                               buf, blen, f_rng, p_rng);
 #endif
         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
-            return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen,
-                                               ctx->point_format, buf, blen,
-                                               f_rng, p_rng,
-                                               restart_enabled ) );
+            return ecdh_make_public_internal(&ctx->ctx.mbed_ecdh, olen,
+                                             ctx->point_format, buf, blen,
+                                             f_rng, p_rng,
+                                             restart_enabled);
         default:
             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
     }
 #endif
 }
 
-static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
-                                      const unsigned char *buf, size_t blen )
+static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx,
+                                     const unsigned char *buf, size_t blen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const unsigned char *p = buf;
 
-    if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p,
-                                            blen ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p,
+                                          blen)) != 0) {
+        return ret;
+    }
 
-    if( (size_t)( p - buf ) != blen )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if ((size_t) (p - buf) != blen) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Parse and import the client's public value
  */
-int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
-                              const unsigned char *buf, size_t blen )
+int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx,
+                             const unsigned char *buf, size_t blen)
 {
-    ECDH_VALIDATE_RET( ctx != NULL );
-    ECDH_VALIDATE_RET( buf != NULL );
-
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
-    return( ecdh_read_public_internal( ctx, buf, blen ) );
+    return ecdh_read_public_internal(ctx, buf, blen);
 #else
-    switch( ctx->var )
-    {
+    switch (ctx->var) {
 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
         case MBEDTLS_ECDH_VARIANT_EVEREST:
-            return( mbedtls_everest_read_public( &ctx->ctx.everest_ecdh,
-                                                 buf, blen ) );
+            return mbedtls_everest_read_public(&ctx->ctx.everest_ecdh,
+                                               buf, blen);
 #endif
         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
-            return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh,
-                                                       buf, blen ) );
+            return ecdh_read_public_internal(&ctx->ctx.mbed_ecdh,
+                                             buf, blen);
         default:
             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
     }
 #endif
 }
 
-static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx,
-                                      size_t *olen, unsigned char *buf,
-                                      size_t blen,
-                                      int (*f_rng)(void *,
-                                                   unsigned char *,
-                                                   size_t),
-                                      void *p_rng,
-                                      int restart_enabled )
+static int ecdh_calc_secret_internal(mbedtls_ecdh_context_mbed *ctx,
+                                     size_t *olen, unsigned char *buf,
+                                     size_t blen,
+                                     int (*f_rng)(void *,
+                                                  unsigned char *,
+                                                  size_t),
+                                     void *p_rng,
+                                     int restart_enabled)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 #if defined(MBEDTLS_ECP_RESTARTABLE)
     mbedtls_ecp_restart_ctx *rs_ctx = NULL;
 #endif
 
-    if( ctx == NULL || ctx->grp.pbits == 0 )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (ctx == NULL || ctx->grp.pbits == 0) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( restart_enabled )
+    if (restart_enabled) {
         rs_ctx = &ctx->rs;
+    }
 #else
     (void) restart_enabled;
 #endif
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp,
-                                                 &ctx->d, f_rng, p_rng,
-                                                 rs_ctx ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp,
+                                               &ctx->d, f_rng, p_rng,
+                                               rs_ctx)) != 0) {
+        return ret;
     }
 #else
-    if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp,
-                                             &ctx->d, f_rng, p_rng ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp,
+                                           &ctx->d, f_rng, p_rng)) != 0) {
+        return ret;
     }
 #endif /* MBEDTLS_ECP_RESTARTABLE */
 
-    if( mbedtls_mpi_size( &ctx->z ) > blen )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (mbedtls_mpi_size(&ctx->z) > blen) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
-    *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 );
+    *olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0);
 
-    if( mbedtls_ecp_get_type( &ctx->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
-        return mbedtls_mpi_write_binary_le( &ctx->z, buf, *olen );
+    if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
+        return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen);
+    }
 
-    return mbedtls_mpi_write_binary( &ctx->z, buf, *olen );
+    return mbedtls_mpi_write_binary(&ctx->z, buf, *olen);
 }
 
 /*
  * Derive and export the shared secret
  */
-int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
-                              unsigned char *buf, size_t blen,
-                              int (*f_rng)(void *, unsigned char *, size_t),
-                              void *p_rng )
+int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen,
+                             unsigned char *buf, size_t blen,
+                             int (*f_rng)(void *, unsigned char *, size_t),
+                             void *p_rng)
 {
     int restart_enabled = 0;
-    ECDH_VALIDATE_RET( ctx != NULL );
-    ECDH_VALIDATE_RET( olen != NULL );
-    ECDH_VALIDATE_RET( buf != NULL );
-
 #if defined(MBEDTLS_ECP_RESTARTABLE)
     restart_enabled = ctx->restart_enabled;
 #endif
 
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
-    return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng,
-                                       restart_enabled ) );
+    return ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng,
+                                     restart_enabled);
 #else
-    switch( ctx->var )
-    {
+    switch (ctx->var) {
 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
         case MBEDTLS_ECDH_VARIANT_EVEREST:
-            return( mbedtls_everest_calc_secret( &ctx->ctx.everest_ecdh, olen,
-                                                 buf, blen, f_rng, p_rng ) );
+            return mbedtls_everest_calc_secret(&ctx->ctx.everest_ecdh, olen,
+                                               buf, blen, f_rng, p_rng);
 #endif
         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
-            return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf,
-                                               blen, f_rng, p_rng,
-                                               restart_enabled ) );
+            return ecdh_calc_secret_internal(&ctx->ctx.mbed_ecdh, olen, buf,
+                                             blen, f_rng, p_rng,
+                                             restart_enabled);
         default:
-            return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
     }
 #endif
 }
-
 #endif /* MBEDTLS_ECDH_C */
diff --git a/lib/libmbedtls/mbedtls/library/ecdsa.c b/lib/libmbedtls/mbedtls/library/ecdsa.c
index 640eb24..eb3c303 100644
--- a/lib/libmbedtls/mbedtls/library/ecdsa.c
+++ b/lib/libmbedtls/mbedtls/library/ecdsa.c
@@ -36,30 +36,17 @@
 #include "mbedtls/hmac_drbg.h"
 #endif
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free       free
-#endif
 
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 
-/* Parameter validation macros based on platform_util.h */
-#define ECDSA_VALIDATE_RET( cond )    \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
-#define ECDSA_VALIDATE( cond )        \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
-
 #if defined(MBEDTLS_ECP_RESTARTABLE)
 
 /*
  * Sub-context for ecdsa_verify()
  */
-struct mbedtls_ecdsa_restart_ver
-{
+struct mbedtls_ecdsa_restart_ver {
     mbedtls_mpi u1, u2;     /* intermediate values  */
     enum {                  /* what to do next?     */
         ecdsa_ver_init = 0, /* getting started      */
@@ -70,32 +57,32 @@
 /*
  * Init verify restart sub-context
  */
-static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx )
+static void ecdsa_restart_ver_init(mbedtls_ecdsa_restart_ver_ctx *ctx)
 {
-    mbedtls_mpi_init( &ctx->u1 );
-    mbedtls_mpi_init( &ctx->u2 );
+    mbedtls_mpi_init(&ctx->u1);
+    mbedtls_mpi_init(&ctx->u2);
     ctx->state = ecdsa_ver_init;
 }
 
 /*
  * Free the components of a verify restart sub-context
  */
-static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx )
+static void ecdsa_restart_ver_free(mbedtls_ecdsa_restart_ver_ctx *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_mpi_free( &ctx->u1 );
-    mbedtls_mpi_free( &ctx->u2 );
+    mbedtls_mpi_free(&ctx->u1);
+    mbedtls_mpi_free(&ctx->u2);
 
-    ecdsa_restart_ver_init( ctx );
+    ecdsa_restart_ver_init(ctx);
 }
 
 /*
  * Sub-context for ecdsa_sign()
  */
-struct mbedtls_ecdsa_restart_sig
-{
+struct mbedtls_ecdsa_restart_sig {
     int sign_tries;
     int key_tries;
     mbedtls_mpi k;          /* per-signature random */
@@ -110,33 +97,33 @@
 /*
  * Init verify sign sub-context
  */
-static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx )
+static void ecdsa_restart_sig_init(mbedtls_ecdsa_restart_sig_ctx *ctx)
 {
     ctx->sign_tries = 0;
     ctx->key_tries = 0;
-    mbedtls_mpi_init( &ctx->k );
-    mbedtls_mpi_init( &ctx->r );
+    mbedtls_mpi_init(&ctx->k);
+    mbedtls_mpi_init(&ctx->r);
     ctx->state = ecdsa_sig_init;
 }
 
 /*
  * Free the components of a sign restart sub-context
  */
-static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx )
+static void ecdsa_restart_sig_free(mbedtls_ecdsa_restart_sig_ctx *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_mpi_free( &ctx->k );
-    mbedtls_mpi_free( &ctx->r );
+    mbedtls_mpi_free(&ctx->k);
+    mbedtls_mpi_free(&ctx->r);
 }
 
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
 /*
  * Sub-context for ecdsa_sign_det()
  */
-struct mbedtls_ecdsa_restart_det
-{
+struct mbedtls_ecdsa_restart_det {
     mbedtls_hmac_drbg_context rng_ctx;  /* DRBG state   */
     enum {                      /* what to do next?     */
         ecdsa_det_init = 0,     /* getting started      */
@@ -147,73 +134,74 @@
 /*
  * Init verify sign_det sub-context
  */
-static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx )
+static void ecdsa_restart_det_init(mbedtls_ecdsa_restart_det_ctx *ctx)
 {
-    mbedtls_hmac_drbg_init( &ctx->rng_ctx );
+    mbedtls_hmac_drbg_init(&ctx->rng_ctx);
     ctx->state = ecdsa_det_init;
 }
 
 /*
  * Free the components of a sign_det restart sub-context
  */
-static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx )
+static void ecdsa_restart_det_free(mbedtls_ecdsa_restart_det_ctx *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_hmac_drbg_free( &ctx->rng_ctx );
+    mbedtls_hmac_drbg_free(&ctx->rng_ctx);
 
-    ecdsa_restart_det_init( ctx );
+    ecdsa_restart_det_init(ctx);
 }
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
 
-#define ECDSA_RS_ECP    ( rs_ctx == NULL ? NULL : &rs_ctx->ecp )
+#define ECDSA_RS_ECP    (rs_ctx == NULL ? NULL : &rs_ctx->ecp)
 
 /* Utility macro for checking and updating ops budget */
-#define ECDSA_BUDGET( ops )   \
-    MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, ECDSA_RS_ECP, ops ) );
+#define ECDSA_BUDGET(ops)   \
+    MBEDTLS_MPI_CHK(mbedtls_ecp_check_budget(grp, ECDSA_RS_ECP, ops));
 
 /* Call this when entering a function that needs its own sub-context */
-#define ECDSA_RS_ENTER( SUB )   do {                                 \
-    /* reset ops count for this call if top-level */                 \
-    if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 )                 \
+#define ECDSA_RS_ENTER(SUB)   do {                                 \
+        /* reset ops count for this call if top-level */                 \
+        if (rs_ctx != NULL && rs_ctx->ecp.depth++ == 0)                 \
         rs_ctx->ecp.ops_done = 0;                                    \
                                                                      \
-    /* set up our own sub-context if needed */                       \
-    if( mbedtls_ecp_restart_is_enabled() &&                          \
-        rs_ctx != NULL && rs_ctx->SUB == NULL )                      \
-    {                                                                \
-        rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) );   \
-        if( rs_ctx->SUB == NULL )                                    \
-            return( MBEDTLS_ERR_ECP_ALLOC_FAILED );                  \
-                                                                     \
-        ecdsa_restart_## SUB ##_init( rs_ctx->SUB );                 \
-    }                                                                \
-} while( 0 )
+        /* set up our own sub-context if needed */                       \
+        if (mbedtls_ecp_restart_is_enabled() &&                          \
+            rs_ctx != NULL && rs_ctx->SUB == NULL)                      \
+        {                                                                \
+            rs_ctx->SUB = mbedtls_calloc(1, sizeof(*rs_ctx->SUB));   \
+            if (rs_ctx->SUB == NULL)                                    \
+            return MBEDTLS_ERR_ECP_ALLOC_FAILED;                  \
+                                                                   \
+            ecdsa_restart_## SUB ##_init(rs_ctx->SUB);                 \
+        }                                                                \
+} while (0)
 
 /* Call this when leaving a function that needs its own sub-context */
-#define ECDSA_RS_LEAVE( SUB )   do {                                 \
-    /* clear our sub-context when not in progress (done or error) */ \
-    if( rs_ctx != NULL && rs_ctx->SUB != NULL &&                     \
-        ret != MBEDTLS_ERR_ECP_IN_PROGRESS )                         \
-    {                                                                \
-        ecdsa_restart_## SUB ##_free( rs_ctx->SUB );                 \
-        mbedtls_free( rs_ctx->SUB );                                 \
-        rs_ctx->SUB = NULL;                                          \
-    }                                                                \
+#define ECDSA_RS_LEAVE(SUB)   do {                                 \
+        /* clear our sub-context when not in progress (done or error) */ \
+        if (rs_ctx != NULL && rs_ctx->SUB != NULL &&                     \
+            ret != MBEDTLS_ERR_ECP_IN_PROGRESS)                         \
+        {                                                                \
+            ecdsa_restart_## SUB ##_free(rs_ctx->SUB);                 \
+            mbedtls_free(rs_ctx->SUB);                                 \
+            rs_ctx->SUB = NULL;                                          \
+        }                                                                \
                                                                      \
-    if( rs_ctx != NULL )                                             \
+        if (rs_ctx != NULL)                                             \
         rs_ctx->ecp.depth--;                                         \
-} while( 0 )
+} while (0)
 
 #else /* MBEDTLS_ECP_RESTARTABLE */
 
 #define ECDSA_RS_ECP    NULL
 
-#define ECDSA_BUDGET( ops )   /* no-op; for compatibility */
+#define ECDSA_BUDGET(ops)     /* no-op; for compatibility */
 
-#define ECDSA_RS_ENTER( SUB )   (void) rs_ctx
-#define ECDSA_RS_LEAVE( SUB )   (void) rs_ctx
+#define ECDSA_RS_ENTER(SUB)   (void) rs_ctx
+#define ECDSA_RS_LEAVE(SUB)   (void) rs_ctx
 
 #endif /* MBEDTLS_ECP_RESTARTABLE */
 
@@ -224,23 +212,25 @@
  * Derive a suitable integer for group grp from a buffer of length len
  * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
  */
-static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x,
-                       const unsigned char *buf, size_t blen )
+static int derive_mpi(const mbedtls_ecp_group *grp, mbedtls_mpi *x,
+                      const unsigned char *buf, size_t blen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t n_size = ( grp->nbits + 7 ) / 8;
+    size_t n_size = (grp->nbits + 7) / 8;
     size_t use_size = blen > n_size ? n_size : blen;
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) );
-    if( use_size * 8 > grp->nbits )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(x, buf, use_size));
+    if (use_size * 8 > grp->nbits) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(x, use_size * 8 - grp->nbits));
+    }
 
     /* While at it, reduce modulo N */
-    if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) );
+    if (mbedtls_mpi_cmp_mpi(x, &grp->N) >= 0) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(x, x, &grp->N));
+    }
 
 cleanup:
-    return( ret );
+    return ret;
 }
 #endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */
 
@@ -249,13 +239,13 @@
  * Compute ECDSA signature of a hashed message (SEC1 4.1.3)
  * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
  */
-static int ecdsa_sign_restartable( mbedtls_ecp_group *grp,
-                mbedtls_mpi *r, mbedtls_mpi *s,
-                const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
-                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
-                int (*f_rng_blind)(void *, unsigned char *, size_t),
-                void *p_rng_blind,
-                mbedtls_ecdsa_restart_ctx *rs_ctx )
+int mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp,
+                                   mbedtls_mpi *r, mbedtls_mpi *s,
+                                   const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
+                                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                                   int (*f_rng_blind)(void *, unsigned char *, size_t),
+                                   void *p_rng_blind,
+                                   mbedtls_ecdsa_restart_ctx *rs_ctx)
 {
     int ret, key_tries, sign_tries;
     int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries;
@@ -264,21 +254,22 @@
     mbedtls_mpi *pk = &k, *pr = r;
 
     /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
-    if( ! mbedtls_ecdsa_can_do( grp->id ) || grp->N.p == NULL )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
     /* Make sure d is in range 1..n-1 */
-    if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
-        return( MBEDTLS_ERR_ECP_INVALID_KEY );
+    if (mbedtls_mpi_cmp_int(d, 1) < 0 || mbedtls_mpi_cmp_mpi(d, &grp->N) >= 0) {
+        return MBEDTLS_ERR_ECP_INVALID_KEY;
+    }
 
-    mbedtls_ecp_point_init( &R );
-    mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t );
+    mbedtls_ecp_point_init(&R);
+    mbedtls_mpi_init(&k); mbedtls_mpi_init(&e); mbedtls_mpi_init(&t);
 
-    ECDSA_RS_ENTER( sig );
+    ECDSA_RS_ENTER(sig);
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->sig != NULL )
-    {
+    if (rs_ctx != NULL && rs_ctx->sig != NULL) {
         /* redirect to our context */
         p_sign_tries = &rs_ctx->sig->sign_tries;
         p_key_tries = &rs_ctx->sig->key_tries;
@@ -286,18 +277,18 @@
         pr = &rs_ctx->sig->r;
 
         /* jump to current step */
-        if( rs_ctx->sig->state == ecdsa_sig_mul )
+        if (rs_ctx->sig->state == ecdsa_sig_mul) {
             goto mul;
-        if( rs_ctx->sig->state == ecdsa_sig_modn )
+        }
+        if (rs_ctx->sig->state == ecdsa_sig_modn) {
             goto modn;
+        }
     }
 #endif /* MBEDTLS_ECP_RESTARTABLE */
 
     *p_sign_tries = 0;
-    do
-    {
-        if( (*p_sign_tries)++ > 10 )
-        {
+    do {
+        if ((*p_sign_tries)++ > 10) {
             ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
             goto cleanup;
         }
@@ -307,33 +298,32 @@
          * and set r = xR mod n
          */
         *p_key_tries = 0;
-        do
-        {
-            if( (*p_key_tries)++ > 10 )
-            {
+        do {
+            if ((*p_key_tries)++ > 10) {
                 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
                 goto cleanup;
             }
 
-            MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, pk, f_rng, p_rng ) );
+            MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, pk, f_rng, p_rng));
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-            if( rs_ctx != NULL && rs_ctx->sig != NULL )
+            if (rs_ctx != NULL && rs_ctx->sig != NULL) {
                 rs_ctx->sig->state = ecdsa_sig_mul;
+            }
 
 mul:
 #endif
-            MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G,
-                                                          f_rng_blind,
-                                                          p_rng_blind,
-                                                          ECDSA_RS_ECP ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) );
-        }
-        while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 );
+            MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &R, pk, &grp->G,
+                                                        f_rng_blind,
+                                                        p_rng_blind,
+                                                        ECDSA_RS_ECP));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pr, &R.X, &grp->N));
+        } while (mbedtls_mpi_cmp_int(pr, 0) == 0);
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-        if( rs_ctx != NULL && rs_ctx->sig != NULL )
+        if (rs_ctx != NULL && rs_ctx->sig != NULL) {
             rs_ctx->sig->state = ecdsa_sig_modn;
+        }
 
 modn:
 #endif
@@ -341,252 +331,164 @@
          * Accounting for everything up to the end of the loop
          * (step 6, but checking now avoids saving e and t)
          */
-        ECDSA_BUDGET( MBEDTLS_ECP_OPS_INV + 4 );
+        ECDSA_BUDGET(MBEDTLS_ECP_OPS_INV + 4);
 
         /*
          * Step 5: derive MPI from hashed message
          */
-        MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
+        MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen));
 
         /*
          * Generate a random value to blind inv_mod in next step,
          * avoiding a potential timing leak.
          */
-        MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng_blind,
-                                                  p_rng_blind ) );
+        MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, &t, f_rng_blind,
+                                                p_rng_blind));
 
         /*
          * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
          */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, pr, d ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pk, pk, &grp->N ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) );
-    }
-    while( mbedtls_mpi_cmp_int( s, 0 ) == 0 );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, pr, d));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&e, &e, s));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&e, &e, &t));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pk, pk, &t));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pk, pk, &grp->N));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(s, pk, &grp->N));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, s, &e));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(s, s, &grp->N));
+    } while (mbedtls_mpi_cmp_int(s, 0) == 0);
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->sig != NULL )
-        mbedtls_mpi_copy( r, pr );
+    if (rs_ctx != NULL && rs_ctx->sig != NULL) {
+        mbedtls_mpi_copy(r, pr);
+    }
 #endif
 
 cleanup:
-    mbedtls_ecp_point_free( &R );
-    mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t );
+    mbedtls_ecp_point_free(&R);
+    mbedtls_mpi_free(&k); mbedtls_mpi_free(&e); mbedtls_mpi_free(&t);
 
-    ECDSA_RS_LEAVE( sig );
+    ECDSA_RS_LEAVE(sig);
 
-    return( ret );
+    return ret;
 }
 
-int mbedtls_ecdsa_can_do( mbedtls_ecp_group_id gid )
+int mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid)
 {
-    switch( gid )
-    {
+    switch (gid) {
 #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED
         case MBEDTLS_ECP_DP_CURVE25519: return 0;
 #endif
 #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED
         case MBEDTLS_ECP_DP_CURVE448: return 0;
 #endif
-    default: return 1;
+        default: return 1;
     }
 }
 
 /*
  * Compute ECDSA signature of a hashed message
  */
-int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
-                const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
-                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+int mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
+                       const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
+                       int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
-    ECDSA_VALIDATE_RET( grp   != NULL );
-    ECDSA_VALIDATE_RET( r     != NULL );
-    ECDSA_VALIDATE_RET( s     != NULL );
-    ECDSA_VALIDATE_RET( d     != NULL );
-    ECDSA_VALIDATE_RET( f_rng != NULL );
-    ECDSA_VALIDATE_RET( buf   != NULL || blen == 0 );
-
     /* Use the same RNG for both blinding and ephemeral key generation */
-    return( ecdsa_sign_restartable( grp, r, s, d, buf, blen,
-                                    f_rng, p_rng, f_rng, p_rng, NULL ) );
+    return mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen,
+                                          f_rng, p_rng, f_rng, p_rng, NULL);
 }
 #endif /* !MBEDTLS_ECDSA_SIGN_ALT */
 
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
 /*
  * Deterministic signature wrapper
+ *
+ * note:    The f_rng_blind parameter must not be NULL.
+ *
  */
-static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp,
-                    mbedtls_mpi *r, mbedtls_mpi *s,
-                    const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
-                    mbedtls_md_type_t md_alg,
-                    int (*f_rng_blind)(void *, unsigned char *, size_t),
-                    void *p_rng_blind,
-                    mbedtls_ecdsa_restart_ctx *rs_ctx )
+int mbedtls_ecdsa_sign_det_restartable(mbedtls_ecp_group *grp,
+                                       mbedtls_mpi *r, mbedtls_mpi *s,
+                                       const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
+                                       mbedtls_md_type_t md_alg,
+                                       int (*f_rng_blind)(void *, unsigned char *, size_t),
+                                       void *p_rng_blind,
+                                       mbedtls_ecdsa_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_hmac_drbg_context rng_ctx;
     mbedtls_hmac_drbg_context *p_rng = &rng_ctx;
     unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
-    size_t grp_len = ( grp->nbits + 7 ) / 8;
+    size_t grp_len = (grp->nbits + 7) / 8;
     const mbedtls_md_info_t *md_info;
     mbedtls_mpi h;
 
-    if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if ((md_info = mbedtls_md_info_from_type(md_alg)) == NULL) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
-    mbedtls_mpi_init( &h );
-    mbedtls_hmac_drbg_init( &rng_ctx );
+    mbedtls_mpi_init(&h);
+    mbedtls_hmac_drbg_init(&rng_ctx);
 
-    ECDSA_RS_ENTER( det );
+    ECDSA_RS_ENTER(det);
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->det != NULL )
-    {
+    if (rs_ctx != NULL && rs_ctx->det != NULL) {
         /* redirect to our context */
         p_rng = &rs_ctx->det->rng_ctx;
 
         /* jump to current step */
-        if( rs_ctx->det->state == ecdsa_det_sign )
+        if (rs_ctx->det->state == ecdsa_det_sign) {
             goto sign;
+        }
     }
 #endif /* MBEDTLS_ECP_RESTARTABLE */
 
     /* Use private key and message hash (reduced) to initialize HMAC_DRBG */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) );
-    MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) );
-    mbedtls_hmac_drbg_seed_buf( p_rng, md_info, data, 2 * grp_len );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(d, data, grp_len));
+    MBEDTLS_MPI_CHK(derive_mpi(grp, &h, buf, blen));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, data + grp_len, grp_len));
+    mbedtls_hmac_drbg_seed_buf(p_rng, md_info, data, 2 * grp_len);
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->det != NULL )
+    if (rs_ctx != NULL && rs_ctx->det != NULL) {
         rs_ctx->det->state = ecdsa_det_sign;
+    }
 
 sign:
 #endif
 #if defined(MBEDTLS_ECDSA_SIGN_ALT)
     (void) f_rng_blind;
     (void) p_rng_blind;
-    ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen,
-                              mbedtls_hmac_drbg_random, p_rng );
+    ret = mbedtls_ecdsa_sign(grp, r, s, d, buf, blen,
+                             mbedtls_hmac_drbg_random, p_rng);
 #else
-    if( f_rng_blind != NULL )
-        ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen,
-                                      mbedtls_hmac_drbg_random, p_rng,
-                                      f_rng_blind, p_rng_blind, rs_ctx );
-    else
-    {
-        mbedtls_hmac_drbg_context *p_rng_blind_det;
-
-#if !defined(MBEDTLS_ECP_RESTARTABLE)
-        /*
-         * To avoid reusing rng_ctx and risking incorrect behavior we seed a
-         * second HMAC-DRBG with the same seed. We also apply a label to avoid
-         * reusing the bits of the ephemeral key for blinding and eliminate the
-         * risk that they leak this way.
-         */
-        const char* blind_label = "BLINDING CONTEXT";
-        mbedtls_hmac_drbg_context rng_ctx_blind;
-
-        mbedtls_hmac_drbg_init( &rng_ctx_blind );
-        p_rng_blind_det = &rng_ctx_blind;
-        mbedtls_hmac_drbg_seed_buf( p_rng_blind_det, md_info,
-                                    data, 2 * grp_len );
-        ret = mbedtls_hmac_drbg_update_ret( p_rng_blind_det,
-                                            (const unsigned char*) blind_label,
-                                            strlen( blind_label ) );
-        if( ret != 0 )
-        {
-            mbedtls_hmac_drbg_free( &rng_ctx_blind );
-            goto cleanup;
-        }
-#else
-        /*
-         * In the case of restartable computations we would either need to store
-         * the second RNG in the restart context too or set it up at every
-         * restart. The first option would penalize the correct application of
-         * the function and the second would defeat the purpose of the
-         * restartable feature.
-         *
-         * Therefore in this case we reuse the original RNG. This comes with the
-         * price that the resulting signature might not be a valid deterministic
-         * ECDSA signature with a very low probability (same magnitude as
-         * successfully guessing the private key). However even then it is still
-         * a valid ECDSA signature.
-         */
-        p_rng_blind_det = p_rng;
-#endif /* MBEDTLS_ECP_RESTARTABLE */
-
-        /*
-         * Since the output of the RNGs is always the same for the same key and
-         * message, this limits the efficiency of blinding and leaks information
-         * through side channels. After mbedtls_ecdsa_sign_det() is removed NULL
-         * won't be a valid value for f_rng_blind anymore. Therefore it should
-         * be checked by the caller and this branch and check can be removed.
-         */
-        ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen,
-                                      mbedtls_hmac_drbg_random, p_rng,
-                                      mbedtls_hmac_drbg_random, p_rng_blind_det,
-                                      rs_ctx );
-
-#if !defined(MBEDTLS_ECP_RESTARTABLE)
-        mbedtls_hmac_drbg_free( &rng_ctx_blind );
-#endif
-    }
+    ret = mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen,
+                                         mbedtls_hmac_drbg_random, p_rng,
+                                         f_rng_blind, p_rng_blind, rs_ctx);
 #endif /* MBEDTLS_ECDSA_SIGN_ALT */
 
 cleanup:
-    mbedtls_hmac_drbg_free( &rng_ctx );
-    mbedtls_mpi_free( &h );
+    mbedtls_hmac_drbg_free(&rng_ctx);
+    mbedtls_mpi_free(&h);
 
-    ECDSA_RS_LEAVE( det );
+    ECDSA_RS_LEAVE(det);
 
-    return( ret );
+    return ret;
 }
 
 /*
- * Deterministic signature wrappers
+ * Deterministic signature wrapper
  */
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r,
-                            mbedtls_mpi *s, const mbedtls_mpi *d,
-                            const unsigned char *buf, size_t blen,
-                            mbedtls_md_type_t md_alg )
+int mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r,
+                               mbedtls_mpi *s, const mbedtls_mpi *d,
+                               const unsigned char *buf, size_t blen,
+                               mbedtls_md_type_t md_alg,
+                               int (*f_rng_blind)(void *, unsigned char *,
+                                                  size_t),
+                               void *p_rng_blind)
 {
-    ECDSA_VALIDATE_RET( grp   != NULL );
-    ECDSA_VALIDATE_RET( r     != NULL );
-    ECDSA_VALIDATE_RET( s     != NULL );
-    ECDSA_VALIDATE_RET( d     != NULL );
-    ECDSA_VALIDATE_RET( buf   != NULL || blen == 0 );
-
-    return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg,
-                                        NULL, NULL, NULL ) );
-}
-#endif /* MBEDTLS_DEPRECATED_REMOVED */
-
-int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r,
-                                mbedtls_mpi *s, const mbedtls_mpi *d,
-                                const unsigned char *buf, size_t blen,
-                                mbedtls_md_type_t md_alg,
-                                int (*f_rng_blind)(void *, unsigned char *,
-                                                   size_t),
-                                void *p_rng_blind )
-{
-    ECDSA_VALIDATE_RET( grp   != NULL );
-    ECDSA_VALIDATE_RET( r     != NULL );
-    ECDSA_VALIDATE_RET( s     != NULL );
-    ECDSA_VALIDATE_RET( d     != NULL );
-    ECDSA_VALIDATE_RET( buf   != NULL || blen == 0 );
-    ECDSA_VALIDATE_RET( f_rng_blind != NULL );
-
-    return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg,
-                                        f_rng_blind, p_rng_blind, NULL ) );
+    return mbedtls_ecdsa_sign_det_restartable(grp, r, s, d, buf, blen, md_alg,
+                                              f_rng_blind, p_rng_blind, NULL);
 }
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
 
@@ -595,46 +497,47 @@
  * Verify ECDSA signature of hashed message (SEC1 4.1.4)
  * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
  */
-static int ecdsa_verify_restartable( mbedtls_ecp_group *grp,
+int mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp,
                                      const unsigned char *buf, size_t blen,
                                      const mbedtls_ecp_point *Q,
-                                     const mbedtls_mpi *r, const mbedtls_mpi *s,
-                                     mbedtls_ecdsa_restart_ctx *rs_ctx )
+                                     const mbedtls_mpi *r,
+                                     const mbedtls_mpi *s,
+                                     mbedtls_ecdsa_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_mpi e, s_inv, u1, u2;
     mbedtls_ecp_point R;
     mbedtls_mpi *pu1 = &u1, *pu2 = &u2;
 
-    mbedtls_ecp_point_init( &R );
-    mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv );
-    mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 );
+    mbedtls_ecp_point_init(&R);
+    mbedtls_mpi_init(&e); mbedtls_mpi_init(&s_inv);
+    mbedtls_mpi_init(&u1); mbedtls_mpi_init(&u2);
 
     /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
-    if( ! mbedtls_ecdsa_can_do( grp->id ) || grp->N.p == NULL )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
-    ECDSA_RS_ENTER( ver );
+    ECDSA_RS_ENTER(ver);
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->ver != NULL )
-    {
+    if (rs_ctx != NULL && rs_ctx->ver != NULL) {
         /* redirect to our context */
         pu1 = &rs_ctx->ver->u1;
         pu2 = &rs_ctx->ver->u2;
 
         /* jump to current step */
-        if( rs_ctx->ver->state == ecdsa_ver_muladd )
+        if (rs_ctx->ver->state == ecdsa_ver_muladd) {
             goto muladd;
+        }
     }
 #endif /* MBEDTLS_ECP_RESTARTABLE */
 
     /*
      * Step 1: make sure r and s are in range 1..n-1
      */
-    if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 ||
-        mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 )
-    {
+    if (mbedtls_mpi_cmp_int(r, 1) < 0 || mbedtls_mpi_cmp_mpi(r, &grp->N) >= 0 ||
+        mbedtls_mpi_cmp_int(s, 1) < 0 || mbedtls_mpi_cmp_mpi(s, &grp->N) >= 0) {
         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
         goto cleanup;
     }
@@ -642,35 +545,35 @@
     /*
      * Step 3: derive MPI from hashed message
      */
-    MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
+    MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen));
 
     /*
      * Step 4: u1 = e / s mod n, u2 = r / s mod n
      */
-    ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 );
+    ECDSA_BUDGET(MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2);
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&s_inv, s, &grp->N));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu1, pu1, &grp->N ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu1, &e, &s_inv));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu1, pu1, &grp->N));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu2, r, &s_inv ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu2, pu2, &grp->N ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu2, r, &s_inv));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu2, pu2, &grp->N));
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->ver != NULL )
+    if (rs_ctx != NULL && rs_ctx->ver != NULL) {
         rs_ctx->ver->state = ecdsa_ver_muladd;
+    }
 
 muladd:
 #endif
     /*
      * Step 5: R = u1 G + u2 Q
      */
-    MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp,
-                     &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecp_muladd_restartable(grp,
+                                                   &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP));
 
-    if( mbedtls_ecp_is_zero( &R ) )
-    {
+    if (mbedtls_ecp_is_zero(&R)) {
         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
         goto cleanup;
     }
@@ -679,302 +582,265 @@
      * Step 6: convert xR to an integer (no-op)
      * Step 7: reduce xR mod n (gives v)
      */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&R.X, &R.X, &grp->N));
 
     /*
      * Step 8: check if v (that is, R.X) is equal to r
      */
-    if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 )
-    {
+    if (mbedtls_mpi_cmp_mpi(&R.X, r) != 0) {
         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
         goto cleanup;
     }
 
 cleanup:
-    mbedtls_ecp_point_free( &R );
-    mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv );
-    mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 );
+    mbedtls_ecp_point_free(&R);
+    mbedtls_mpi_free(&e); mbedtls_mpi_free(&s_inv);
+    mbedtls_mpi_free(&u1); mbedtls_mpi_free(&u2);
 
-    ECDSA_RS_LEAVE( ver );
+    ECDSA_RS_LEAVE(ver);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Verify ECDSA signature of hashed message
  */
-int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
-                          const unsigned char *buf, size_t blen,
-                          const mbedtls_ecp_point *Q,
-                          const mbedtls_mpi *r,
-                          const mbedtls_mpi *s)
+int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp,
+                         const unsigned char *buf, size_t blen,
+                         const mbedtls_ecp_point *Q,
+                         const mbedtls_mpi *r,
+                         const mbedtls_mpi *s)
 {
-    ECDSA_VALIDATE_RET( grp != NULL );
-    ECDSA_VALIDATE_RET( Q   != NULL );
-    ECDSA_VALIDATE_RET( r   != NULL );
-    ECDSA_VALIDATE_RET( s   != NULL );
-    ECDSA_VALIDATE_RET( buf != NULL || blen == 0 );
-
-    return( ecdsa_verify_restartable( grp, buf, blen, Q, r, s, NULL ) );
+    return mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, NULL);
 }
 #endif /* !MBEDTLS_ECDSA_VERIFY_ALT */
 
 /*
  * Convert a signature (given by context) to ASN.1
  */
-static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s,
-                                    unsigned char *sig, size_t *slen )
+static int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s,
+                                   unsigned char *sig, size_t sig_size,
+                                   size_t *slen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = {0};
-    unsigned char *p = buf + sizeof( buf );
+    unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = { 0 };
+    unsigned char *p = buf + sizeof(buf);
     size_t len = 0;
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, s));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, r));
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf,
-                                       MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, buf, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, buf,
+                                                     MBEDTLS_ASN1_CONSTRUCTED |
+                                                     MBEDTLS_ASN1_SEQUENCE));
 
-    memcpy( sig, p, len );
+    if (len > sig_size) {
+        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+    }
+
+    memcpy(sig, p, len);
     *slen = len;
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Compute and write signature
  */
-int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx,
-                           mbedtls_md_type_t md_alg,
-                           const unsigned char *hash, size_t hlen,
-                           unsigned char *sig, size_t *slen,
-                           int (*f_rng)(void *, unsigned char *, size_t),
-                           void *p_rng,
-                           mbedtls_ecdsa_restart_ctx *rs_ctx )
+int mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx,
+                                              mbedtls_md_type_t md_alg,
+                                              const unsigned char *hash, size_t hlen,
+                                              unsigned char *sig, size_t sig_size, size_t *slen,
+                                              int (*f_rng)(void *, unsigned char *, size_t),
+                                              void *p_rng,
+                                              mbedtls_ecdsa_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_mpi r, s;
-    ECDSA_VALIDATE_RET( ctx  != NULL );
-    ECDSA_VALIDATE_RET( hash != NULL );
-    ECDSA_VALIDATE_RET( sig  != NULL );
-    ECDSA_VALIDATE_RET( slen != NULL );
+    if (f_rng == NULL) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
-    mbedtls_mpi_init( &r );
-    mbedtls_mpi_init( &s );
+    mbedtls_mpi_init(&r);
+    mbedtls_mpi_init(&s);
 
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
-    MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d,
-                                                 hash, hlen, md_alg, f_rng,
-                                                 p_rng, rs_ctx ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_restartable(&ctx->grp, &r, &s, &ctx->d,
+                                                       hash, hlen, md_alg, f_rng,
+                                                       p_rng, rs_ctx));
 #else
     (void) md_alg;
 
 #if defined(MBEDTLS_ECDSA_SIGN_ALT)
     (void) rs_ctx;
 
-    MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
-                         hash, hlen, f_rng, p_rng ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ctx->grp, &r, &s, &ctx->d,
+                                       hash, hlen, f_rng, p_rng));
 #else
     /* Use the same RNG for both blinding and ephemeral key generation */
-    MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d,
-                                             hash, hlen, f_rng, p_rng, f_rng,
-                                             p_rng, rs_ctx ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_restartable(&ctx->grp, &r, &s, &ctx->d,
+                                                   hash, hlen, f_rng, p_rng, f_rng,
+                                                   p_rng, rs_ctx));
 #endif /* MBEDTLS_ECDSA_SIGN_ALT */
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
 
-    MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) );
+    MBEDTLS_MPI_CHK(ecdsa_signature_to_asn1(&r, &s, sig, sig_size, slen));
 
 cleanup:
-    mbedtls_mpi_free( &r );
-    mbedtls_mpi_free( &s );
+    mbedtls_mpi_free(&r);
+    mbedtls_mpi_free(&s);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Compute and write signature
  */
-int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx,
-                                 mbedtls_md_type_t md_alg,
-                                 const unsigned char *hash, size_t hlen,
-                                 unsigned char *sig, size_t *slen,
-                                 int (*f_rng)(void *, unsigned char *, size_t),
-                                 void *p_rng )
+int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx,
+                                  mbedtls_md_type_t md_alg,
+                                  const unsigned char *hash, size_t hlen,
+                                  unsigned char *sig, size_t sig_size, size_t *slen,
+                                  int (*f_rng)(void *, unsigned char *, size_t),
+                                  void *p_rng)
 {
-    ECDSA_VALIDATE_RET( ctx  != NULL );
-    ECDSA_VALIDATE_RET( hash != NULL );
-    ECDSA_VALIDATE_RET( sig  != NULL );
-    ECDSA_VALIDATE_RET( slen != NULL );
-    return( mbedtls_ecdsa_write_signature_restartable(
-                ctx, md_alg, hash, hlen, sig, slen, f_rng, p_rng, NULL ) );
+    return mbedtls_ecdsa_write_signature_restartable(
+        ctx, md_alg, hash, hlen, sig, sig_size, slen,
+        f_rng, p_rng, NULL);
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED) && \
-    defined(MBEDTLS_ECDSA_DETERMINISTIC)
-int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx,
-                               const unsigned char *hash, size_t hlen,
-                               unsigned char *sig, size_t *slen,
-                               mbedtls_md_type_t md_alg )
-{
-    ECDSA_VALIDATE_RET( ctx  != NULL );
-    ECDSA_VALIDATE_RET( hash != NULL );
-    ECDSA_VALIDATE_RET( sig  != NULL );
-    ECDSA_VALIDATE_RET( slen != NULL );
-    return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen,
-                                   NULL, NULL ) );
-}
-#endif
-
 /*
  * Read and check signature
  */
-int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
-                          const unsigned char *hash, size_t hlen,
-                          const unsigned char *sig, size_t slen )
+int mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx,
+                                 const unsigned char *hash, size_t hlen,
+                                 const unsigned char *sig, size_t slen)
 {
-    ECDSA_VALIDATE_RET( ctx  != NULL );
-    ECDSA_VALIDATE_RET( hash != NULL );
-    ECDSA_VALIDATE_RET( sig  != NULL );
-    return( mbedtls_ecdsa_read_signature_restartable(
-                ctx, hash, hlen, sig, slen, NULL ) );
+    return mbedtls_ecdsa_read_signature_restartable(
+        ctx, hash, hlen, sig, slen, NULL);
 }
 
 /*
  * Restartable read and check signature
  */
-int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx,
-                          const unsigned char *hash, size_t hlen,
-                          const unsigned char *sig, size_t slen,
-                          mbedtls_ecdsa_restart_ctx *rs_ctx )
+int mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx,
+                                             const unsigned char *hash, size_t hlen,
+                                             const unsigned char *sig, size_t slen,
+                                             mbedtls_ecdsa_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *p = (unsigned char *) sig;
     const unsigned char *end = sig + slen;
     size_t len;
     mbedtls_mpi r, s;
-    ECDSA_VALIDATE_RET( ctx  != NULL );
-    ECDSA_VALIDATE_RET( hash != NULL );
-    ECDSA_VALIDATE_RET( sig  != NULL );
+    mbedtls_mpi_init(&r);
+    mbedtls_mpi_init(&s);
 
-    mbedtls_mpi_init( &r );
-    mbedtls_mpi_init( &s );
-
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
         ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
         goto cleanup;
     }
 
-    if( p + len != end )
-    {
-        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
-              MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+    if (p + len != end) {
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
+                                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
         goto cleanup;
     }
 
-    if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 ||
-        ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 )
-    {
+    if ((ret = mbedtls_asn1_get_mpi(&p, end, &r)) != 0 ||
+        (ret = mbedtls_asn1_get_mpi(&p, end, &s)) != 0) {
         ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
         goto cleanup;
     }
 #if defined(MBEDTLS_ECDSA_VERIFY_ALT)
     (void) rs_ctx;
 
-    if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen,
-                                      &ctx->Q, &r, &s ) ) != 0 )
+    if ((ret = mbedtls_ecdsa_verify(&ctx->grp, hash, hlen,
+                                    &ctx->Q, &r, &s)) != 0) {
         goto cleanup;
+    }
 #else
-    if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen,
-                              &ctx->Q, &r, &s, rs_ctx ) ) != 0 )
+    if ((ret = mbedtls_ecdsa_verify_restartable(&ctx->grp, hash, hlen,
+                                                &ctx->Q, &r, &s, rs_ctx)) != 0) {
         goto cleanup;
+    }
 #endif /* MBEDTLS_ECDSA_VERIFY_ALT */
 
     /* At this point we know that the buffer starts with a valid signature.
      * Return 0 if the buffer just contains the signature, and a specific
      * error code if the valid signature is followed by more data. */
-    if( p != end )
+    if (p != end) {
         ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH;
+    }
 
 cleanup:
-    mbedtls_mpi_free( &r );
-    mbedtls_mpi_free( &s );
+    mbedtls_mpi_free(&r);
+    mbedtls_mpi_free(&s);
 
-    return( ret );
+    return ret;
 }
 
 #if !defined(MBEDTLS_ECDSA_GENKEY_ALT)
 /*
  * Generate key pair
  */
-int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
-                  int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+int mbedtls_ecdsa_genkey(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
+                         int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
     int ret = 0;
-    ECDSA_VALIDATE_RET( ctx   != NULL );
-    ECDSA_VALIDATE_RET( f_rng != NULL );
+    ret = mbedtls_ecp_group_load(&ctx->grp, gid);
+    if (ret != 0) {
+        return ret;
+    }
 
-    ret = mbedtls_ecp_group_load( &ctx->grp, gid );
-    if( ret != 0 )
-        return( ret );
-
-   return( mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d,
-                                    &ctx->Q, f_rng, p_rng ) );
+    return mbedtls_ecp_gen_keypair(&ctx->grp, &ctx->d,
+                                   &ctx->Q, f_rng, p_rng);
 }
 #endif /* !MBEDTLS_ECDSA_GENKEY_ALT */
 
 /*
  * Set context from an mbedtls_ecp_keypair
  */
-int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key )
+int mbedtls_ecdsa_from_keypair(mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    ECDSA_VALIDATE_RET( ctx != NULL );
-    ECDSA_VALIDATE_RET( key != NULL );
-
-    if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ||
-        ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ||
-        ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 )
-    {
-        mbedtls_ecdsa_free( ctx );
+    if ((ret = mbedtls_ecp_group_copy(&ctx->grp, &key->grp)) != 0 ||
+        (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0 ||
+        (ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0) {
+        mbedtls_ecdsa_free(ctx);
     }
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Initialize context
  */
-void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx )
+void mbedtls_ecdsa_init(mbedtls_ecdsa_context *ctx)
 {
-    ECDSA_VALIDATE( ctx != NULL );
-
-    mbedtls_ecp_keypair_init( ctx );
+    mbedtls_ecp_keypair_init(ctx);
 }
 
 /*
  * Free context
  */
-void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx )
+void mbedtls_ecdsa_free(mbedtls_ecdsa_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_ecp_keypair_free( ctx );
+    mbedtls_ecp_keypair_free(ctx);
 }
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
 /*
  * Initialize a restart context
  */
-void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx )
+void mbedtls_ecdsa_restart_init(mbedtls_ecdsa_restart_ctx *ctx)
 {
-    ECDSA_VALIDATE( ctx != NULL );
-
-    mbedtls_ecp_restart_init( &ctx->ecp );
+    mbedtls_ecp_restart_init(&ctx->ecp);
 
     ctx->ver = NULL;
     ctx->sig = NULL;
@@ -986,24 +852,25 @@
 /*
  * Free the components of a restart context
  */
-void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx )
+void mbedtls_ecdsa_restart_free(mbedtls_ecdsa_restart_ctx *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_ecp_restart_free( &ctx->ecp );
+    mbedtls_ecp_restart_free(&ctx->ecp);
 
-    ecdsa_restart_ver_free( ctx->ver );
-    mbedtls_free( ctx->ver );
+    ecdsa_restart_ver_free(ctx->ver);
+    mbedtls_free(ctx->ver);
     ctx->ver = NULL;
 
-    ecdsa_restart_sig_free( ctx->sig );
-    mbedtls_free( ctx->sig );
+    ecdsa_restart_sig_free(ctx->sig);
+    mbedtls_free(ctx->sig);
     ctx->sig = NULL;
 
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
-    ecdsa_restart_det_free( ctx->det );
-    mbedtls_free( ctx->det );
+    ecdsa_restart_det_free(ctx->det);
+    mbedtls_free(ctx->det);
     ctx->det = NULL;
 #endif
 }
diff --git a/lib/libmbedtls/mbedtls/library/ecjpake.c b/lib/libmbedtls/mbedtls/library/ecjpake.c
index 0b9bffb..36c1327 100644
--- a/lib/libmbedtls/mbedtls/library/ecjpake.c
+++ b/lib/libmbedtls/mbedtls/library/ecjpake.c
@@ -30,16 +30,24 @@
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 
+/* We use MD first if it's available (for compatibility reasons)
+ * and "fall back" to PSA otherwise (which needs psa_crypto_init()). */
+#if !defined(MBEDTLS_MD_C)
+#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
+#if !defined(MBEDTLS_ECJPAKE_ALT)
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_md_errors,              \
+                                                           psa_generic_status_to_mbedtls)
+#endif /* !MBEDTLS_ECJPAKE_ALT */
+#endif /* !MBEDTLS_MD_C */
+
+#include "hash_info.h"
+
 #include <string.h>
 
 #if !defined(MBEDTLS_ECJPAKE_ALT)
 
-/* Parameter validation macros based on platform_util.h */
-#define ECJPAKE_VALIDATE_RET( cond )    \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
-#define ECJPAKE_VALIDATE( cond )        \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
-
 /*
  * Convert a mbedtls_ecjpake_role to identifier string
  */
@@ -48,206 +56,251 @@
     "server"
 };
 
-#define ID_MINE     ( ecjpake_id[ ctx->role ] )
-#define ID_PEER     ( ecjpake_id[ 1 - ctx->role ] )
+#define ID_MINE     (ecjpake_id[ctx->role])
+#define ID_PEER     (ecjpake_id[1 - ctx->role])
+
+/**
+ * Helper to Compute a hash from md_type
+ */
+static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,
+                                        const unsigned char *input, size_t ilen,
+                                        unsigned char *output)
+{
+#if defined(MBEDTLS_MD_C)
+    return mbedtls_md(mbedtls_md_info_from_type(md_type),
+                      input, ilen, output);
+#else
+    psa_algorithm_t alg = mbedtls_psa_translate_md(md_type);
+    psa_status_t status;
+    size_t out_size = PSA_HASH_LENGTH(alg);
+    size_t out_len;
+
+    status = psa_hash_compute(alg, input, ilen, output, out_size, &out_len);
+
+    return PSA_TO_MBEDTLS_ERR(status);
+#endif /* !MBEDTLS_MD_C */
+}
 
 /*
  * Initialize context
  */
-void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx )
+void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)
 {
-    ECJPAKE_VALIDATE( ctx != NULL );
-
-    ctx->md_info = NULL;
-    mbedtls_ecp_group_init( &ctx->grp );
+    ctx->md_type = MBEDTLS_MD_NONE;
+    mbedtls_ecp_group_init(&ctx->grp);
     ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
 
-    mbedtls_ecp_point_init( &ctx->Xm1 );
-    mbedtls_ecp_point_init( &ctx->Xm2 );
-    mbedtls_ecp_point_init( &ctx->Xp1 );
-    mbedtls_ecp_point_init( &ctx->Xp2 );
-    mbedtls_ecp_point_init( &ctx->Xp  );
+    mbedtls_ecp_point_init(&ctx->Xm1);
+    mbedtls_ecp_point_init(&ctx->Xm2);
+    mbedtls_ecp_point_init(&ctx->Xp1);
+    mbedtls_ecp_point_init(&ctx->Xp2);
+    mbedtls_ecp_point_init(&ctx->Xp);
 
-    mbedtls_mpi_init( &ctx->xm1 );
-    mbedtls_mpi_init( &ctx->xm2 );
-    mbedtls_mpi_init( &ctx->s   );
+    mbedtls_mpi_init(&ctx->xm1);
+    mbedtls_mpi_init(&ctx->xm2);
+    mbedtls_mpi_init(&ctx->s);
 }
 
 /*
  * Free context
  */
-void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx )
+void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    ctx->md_info = NULL;
-    mbedtls_ecp_group_free( &ctx->grp );
+    ctx->md_type = MBEDTLS_MD_NONE;
+    mbedtls_ecp_group_free(&ctx->grp);
 
-    mbedtls_ecp_point_free( &ctx->Xm1 );
-    mbedtls_ecp_point_free( &ctx->Xm2 );
-    mbedtls_ecp_point_free( &ctx->Xp1 );
-    mbedtls_ecp_point_free( &ctx->Xp2 );
-    mbedtls_ecp_point_free( &ctx->Xp  );
+    mbedtls_ecp_point_free(&ctx->Xm1);
+    mbedtls_ecp_point_free(&ctx->Xm2);
+    mbedtls_ecp_point_free(&ctx->Xp1);
+    mbedtls_ecp_point_free(&ctx->Xp2);
+    mbedtls_ecp_point_free(&ctx->Xp);
 
-    mbedtls_mpi_free( &ctx->xm1 );
-    mbedtls_mpi_free( &ctx->xm2 );
-    mbedtls_mpi_free( &ctx->s   );
+    mbedtls_mpi_free(&ctx->xm1);
+    mbedtls_mpi_free(&ctx->xm2);
+    mbedtls_mpi_free(&ctx->s);
 }
 
 /*
  * Setup context
  */
-int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
-                           mbedtls_ecjpake_role role,
-                           mbedtls_md_type_t hash,
-                           mbedtls_ecp_group_id curve,
-                           const unsigned char *secret,
-                           size_t len )
+int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,
+                          mbedtls_ecjpake_role role,
+                          mbedtls_md_type_t hash,
+                          mbedtls_ecp_group_id curve,
+                          const unsigned char *secret,
+                          size_t len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    ECJPAKE_VALIDATE_RET( ctx != NULL );
-    ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT ||
-                          role == MBEDTLS_ECJPAKE_SERVER );
-    ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 );
+    if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
     ctx->role = role;
 
-    if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL )
-        return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
+#if defined(MBEDTLS_MD_C)
+    if ((mbedtls_md_info_from_type(hash)) == NULL) {
+        return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
+    }
+#else
+    if (mbedtls_psa_translate_md(hash) == MBEDTLS_MD_NONE) {
+        return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
+    }
+#endif
 
-    MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) );
+    ctx->md_type = hash;
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));
+
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));
 
 cleanup:
-    if( ret != 0 )
-        mbedtls_ecjpake_free( ctx );
+    if (ret != 0) {
+        mbedtls_ecjpake_free(ctx);
+    }
 
-    return( ret );
+    return ret;
+}
+
+int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx,
+                                     int point_format)
+{
+    switch (point_format) {
+        case MBEDTLS_ECP_PF_UNCOMPRESSED:
+        case MBEDTLS_ECP_PF_COMPRESSED:
+            ctx->point_format = point_format;
+            return 0;
+        default:
+            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 }
 
 /*
  * Check if context is ready for use
  */
-int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx )
+int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)
 {
-    ECJPAKE_VALIDATE_RET( ctx != NULL );
-
-    if( ctx->md_info == NULL ||
+    if (ctx->md_type == MBEDTLS_MD_NONE ||
         ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
-        ctx->s.p == NULL )
-    {
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+        ctx->s.p == NULL) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Write a point plus its length to a buffer
  */
-static int ecjpake_write_len_point( unsigned char **p,
-                                    const unsigned char *end,
-                                    const mbedtls_ecp_group *grp,
-                                    const int pf,
-                                    const mbedtls_ecp_point *P )
+static int ecjpake_write_len_point(unsigned char **p,
+                                   const unsigned char *end,
+                                   const mbedtls_ecp_group *grp,
+                                   const int pf,
+                                   const mbedtls_ecp_point *P)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
     /* Need at least 4 for length plus 1 for point */
-    if( end < *p || end - *p < 5 )
-        return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
+    if (end < *p || end - *p < 5) {
+        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+    }
 
-    ret = mbedtls_ecp_point_write_binary( grp, P, pf,
-                                          &len, *p + 4, end - ( *p + 4 ) );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_ecp_point_write_binary(grp, P, pf,
+                                         &len, *p + 4, end - (*p + 4));
+    if (ret != 0) {
+        return ret;
+    }
 
-    MBEDTLS_PUT_UINT32_BE( len, *p, 0 );
+    MBEDTLS_PUT_UINT32_BE(len, *p, 0);
 
     *p += 4 + len;
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Size of the temporary buffer for ecjpake_hash:
  * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
  */
-#define ECJPAKE_HASH_BUF_LEN    ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 )
+#define ECJPAKE_HASH_BUF_LEN    (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6)
 
 /*
  * Compute hash for ZKP (7.4.2.2.2.1)
  */
-static int ecjpake_hash( const mbedtls_md_info_t *md_info,
-                         const mbedtls_ecp_group *grp,
-                         const int pf,
-                         const mbedtls_ecp_point *G,
-                         const mbedtls_ecp_point *V,
-                         const mbedtls_ecp_point *X,
-                         const char *id,
-                         mbedtls_mpi *h )
+static int ecjpake_hash(const mbedtls_md_type_t md_type,
+                        const mbedtls_ecp_group *grp,
+                        const int pf,
+                        const mbedtls_ecp_point *G,
+                        const mbedtls_ecp_point *V,
+                        const mbedtls_ecp_point *X,
+                        const char *id,
+                        mbedtls_mpi *h)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char buf[ECJPAKE_HASH_BUF_LEN];
     unsigned char *p = buf;
-    const unsigned char *end = buf + sizeof( buf );
-    const size_t id_len = strlen( id );
-    unsigned char hash[MBEDTLS_MD_MAX_SIZE];
+    const unsigned char *end = buf + sizeof(buf);
+    const size_t id_len = strlen(id);
+    unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
 
     /* Write things to temporary buffer */
-    MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
-    MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) );
-    MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) );
+    MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G));
+    MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V));
+    MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X));
 
-    if( end - p < 4 )
-        return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
+    if (end - p < 4) {
+        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+    }
 
-    MBEDTLS_PUT_UINT32_BE( id_len, p, 0 );
+    MBEDTLS_PUT_UINT32_BE(id_len, p, 0);
     p += 4;
 
-    if( end < p || (size_t)( end - p ) < id_len )
-        return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
+    if (end < p || (size_t) (end - p) < id_len) {
+        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+    }
 
-    memcpy( p, id, id_len );
+    memcpy(p, id, id_len);
     p += id_len;
 
     /* Compute hash */
-    MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,
+                                                 buf, p - buf, hash));
 
     /* Turn it into an integer mod n */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash,
-                                        mbedtls_md_get_size( md_info ) ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,
+                                            mbedtls_hash_info_get_size(md_type)));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
  * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
  */
-static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
-                             const mbedtls_ecp_group *grp,
-                             const int pf,
-                             const mbedtls_ecp_point *G,
-                             const mbedtls_ecp_point *X,
-                             const char *id,
-                             const unsigned char **p,
-                             const unsigned char *end )
+static int ecjpake_zkp_read(const mbedtls_md_type_t md_type,
+                            const mbedtls_ecp_group *grp,
+                            const int pf,
+                            const mbedtls_ecp_point *G,
+                            const mbedtls_ecp_point *X,
+                            const char *id,
+                            const unsigned char **p,
+                            const unsigned char *end)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecp_point V, VV;
     mbedtls_mpi r, h;
     size_t r_len;
 
-    mbedtls_ecp_point_init( &V );
-    mbedtls_ecp_point_init( &VV );
-    mbedtls_mpi_init( &r );
-    mbedtls_mpi_init( &h );
+    mbedtls_ecp_point_init(&V);
+    mbedtls_ecp_point_init(&VV);
+    mbedtls_mpi_init(&r);
+    mbedtls_mpi_init(&h);
 
     /*
      * struct {
@@ -255,64 +308,62 @@
      *     opaque r<1..2^8-1>;
      * } ECSchnorrZKP;
      */
-    if( end < *p )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (end < *p) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
-    MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, end - *p));
 
-    if( end < *p || (size_t)( end - *p ) < 1 )
-    {
+    if (end < *p || (size_t) (end - *p) < 1) {
         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
         goto cleanup;
     }
 
     r_len = *(*p)++;
 
-    if( end < *p || (size_t)( end - *p ) < r_len || r_len == 0 )
-    {
+    if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {
         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
         goto cleanup;
     }
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));
     *p += r_len;
 
     /*
      * Verification
      */
-    MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
-    MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
-                     &VV, &h, X, &r, G ) );
+    MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
+    MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp,
+                                       &VV, &h, X, &r, G));
 
-    if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
-    {
+    if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {
         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
         goto cleanup;
     }
 
 cleanup:
-    mbedtls_ecp_point_free( &V );
-    mbedtls_ecp_point_free( &VV );
-    mbedtls_mpi_free( &r );
-    mbedtls_mpi_free( &h );
+    mbedtls_ecp_point_free(&V);
+    mbedtls_ecp_point_free(&VV);
+    mbedtls_mpi_free(&r);
+    mbedtls_mpi_free(&h);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
  */
-static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
-                              const mbedtls_ecp_group *grp,
-                              const int pf,
-                              const mbedtls_ecp_point *G,
-                              const mbedtls_mpi *x,
-                              const mbedtls_ecp_point *X,
-                              const char *id,
-                              unsigned char **p,
-                              const unsigned char *end,
-                              int (*f_rng)(void *, unsigned char *, size_t),
-                              void *p_rng )
+static int ecjpake_zkp_write(const mbedtls_md_type_t md_type,
+                             const mbedtls_ecp_group *grp,
+                             const int pf,
+                             const mbedtls_ecp_point *G,
+                             const mbedtls_mpi *x,
+                             const mbedtls_ecp_point *X,
+                             const char *id,
+                             unsigned char **p,
+                             const unsigned char *end,
+                             int (*f_rng)(void *, unsigned char *, size_t),
+                             void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecp_point V;
@@ -320,62 +371,63 @@
     mbedtls_mpi h; /* later recycled to hold r */
     size_t len;
 
-    if( end < *p )
-        return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
+    if (end < *p) {
+        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+    }
 
-    mbedtls_ecp_point_init( &V );
-    mbedtls_mpi_init( &v );
-    mbedtls_mpi_init( &h );
+    mbedtls_ecp_point_init(&V);
+    mbedtls_mpi_init(&v);
+    mbedtls_mpi_init(&h);
 
     /* Compute signature */
-    MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp,
-                                                   G, &v, &V, f_rng, p_rng ) );
-    MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */
+    MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp,
+                                                 G, &v, &V, f_rng, p_rng));
+    MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x));     /* x*h */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h));     /* v - x*h */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N));     /* r */
 
     /* Write it out */
-    MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V,
-                pf, &len, *p, end - *p ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,
+                                                pf, &len, *p, end - *p));
     *p += len;
 
-    len = mbedtls_mpi_size( &h ); /* actually r */
-    if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 )
-    {
+    len = mbedtls_mpi_size(&h);   /* actually r */
+    if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {
         ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
         goto cleanup;
     }
 
-    *(*p)++ = MBEDTLS_BYTE_0( len );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */
+    *(*p)++ = MBEDTLS_BYTE_0(len);
+    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len));     /* r */
     *p += len;
 
 cleanup:
-    mbedtls_ecp_point_free( &V );
-    mbedtls_mpi_free( &v );
-    mbedtls_mpi_free( &h );
+    mbedtls_ecp_point_free(&V);
+    mbedtls_mpi_free(&v);
+    mbedtls_mpi_free(&h);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
  * Output: verified public key X
  */
-static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
-                             const mbedtls_ecp_group *grp,
-                             const int pf,
-                             const mbedtls_ecp_point *G,
-                             mbedtls_ecp_point *X,
-                             const char *id,
-                             const unsigned char **p,
-                             const unsigned char *end )
+static int ecjpake_kkp_read(const mbedtls_md_type_t md_type,
+                            const mbedtls_ecp_group *grp,
+                            const int pf,
+                            const mbedtls_ecp_point *G,
+                            mbedtls_ecp_point *X,
+                            const char *id,
+                            const unsigned char **p,
+                            const unsigned char *end)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( end < *p )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (end < *p) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
     /*
      * struct {
@@ -383,69 +435,69 @@
      *     ECSchnorrZKP zkp;
      * } ECJPAKEKeyKP;
      */
-    MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) );
-    if( mbedtls_ecp_is_zero( X ) )
-    {
+    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, end - *p));
+    if (mbedtls_ecp_is_zero(X)) {
         ret = MBEDTLS_ERR_ECP_INVALID_KEY;
         goto cleanup;
     }
 
-    MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) );
+    MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end));
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
  * Generate an ECJPAKEKeyKP
  * Output: the serialized structure, plus private/public key pair
  */
-static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
-                              const mbedtls_ecp_group *grp,
-                              const int pf,
-                              const mbedtls_ecp_point *G,
-                              mbedtls_mpi *x,
-                              mbedtls_ecp_point *X,
-                              const char *id,
-                              unsigned char **p,
-                              const unsigned char *end,
-                              int (*f_rng)(void *, unsigned char *, size_t),
-                              void *p_rng )
+static int ecjpake_kkp_write(const mbedtls_md_type_t md_type,
+                             const mbedtls_ecp_group *grp,
+                             const int pf,
+                             const mbedtls_ecp_point *G,
+                             mbedtls_mpi *x,
+                             mbedtls_ecp_point *X,
+                             const char *id,
+                             unsigned char **p,
+                             const unsigned char *end,
+                             int (*f_rng)(void *, unsigned char *, size_t),
+                             void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
-    if( end < *p )
-        return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
+    if (end < *p) {
+        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+    }
 
     /* Generate key (7.4.2.3.1) and write it out */
-    MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X,
-                                                   f_rng, p_rng ) );
-    MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X,
-                pf, &len, *p, end - *p ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X,
+                                                 f_rng, p_rng));
+    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X,
+                                                pf, &len, *p, end - *p));
     *p += len;
 
     /* Generate and write proof */
-    MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id,
-                                        p, end, f_rng, p_rng ) );
+    MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id,
+                                      p, end, f_rng, p_rng));
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
  * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
  * Outputs: verified peer public keys Xa, Xb
  */
-static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
-                              const mbedtls_ecp_group *grp,
-                              const int pf,
-                              const mbedtls_ecp_point *G,
-                              mbedtls_ecp_point *Xa,
-                              mbedtls_ecp_point *Xb,
-                              const char *id,
-                              const unsigned char *buf,
-                              size_t len )
+static int ecjpake_kkpp_read(const mbedtls_md_type_t md_type,
+                             const mbedtls_ecp_group *grp,
+                             const int pf,
+                             const mbedtls_ecp_point *G,
+                             mbedtls_ecp_point *Xa,
+                             mbedtls_ecp_point *Xb,
+                             const char *id,
+                             const unsigned char *buf,
+                             size_t len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const unsigned char *p = buf;
@@ -456,114 +508,107 @@
      *     ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
      * } ECJPAKEKeyKPPairList;
      */
-    MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) );
-    MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) );
+    MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end));
+    MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end));
 
-    if( p != end )
+    if (p != end) {
         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
  * Generate a ECJPAKEKeyKPPairList
  * Outputs: the serialized structure, plus two private/public key pairs
  */
-static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
-                               const mbedtls_ecp_group *grp,
-                               const int pf,
-                               const mbedtls_ecp_point *G,
-                               mbedtls_mpi *xm1,
-                               mbedtls_ecp_point *Xa,
-                               mbedtls_mpi *xm2,
-                               mbedtls_ecp_point *Xb,
-                               const char *id,
-                               unsigned char *buf,
-                               size_t len,
-                               size_t *olen,
-                               int (*f_rng)(void *, unsigned char *, size_t),
-                               void *p_rng )
+static int ecjpake_kkpp_write(const mbedtls_md_type_t md_type,
+                              const mbedtls_ecp_group *grp,
+                              const int pf,
+                              const mbedtls_ecp_point *G,
+                              mbedtls_mpi *xm1,
+                              mbedtls_ecp_point *Xa,
+                              mbedtls_mpi *xm2,
+                              mbedtls_ecp_point *Xb,
+                              const char *id,
+                              unsigned char *buf,
+                              size_t len,
+                              size_t *olen,
+                              int (*f_rng)(void *, unsigned char *, size_t),
+                              void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *p = buf;
     const unsigned char *end = buf + len;
 
-    MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id,
-                &p, end, f_rng, p_rng ) );
-    MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id,
-                &p, end, f_rng, p_rng ) );
+    MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id,
+                                      &p, end, f_rng, p_rng));
+    MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id,
+                                      &p, end, f_rng, p_rng));
 
     *olen = p - buf;
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
  * Read and process the first round message
  */
-int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
-                                    const unsigned char *buf,
-                                    size_t len )
+int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,
+                                   const unsigned char *buf,
+                                   size_t len)
 {
-    ECJPAKE_VALIDATE_RET( ctx != NULL );
-    ECJPAKE_VALIDATE_RET( buf != NULL );
-
-    return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format,
-                               &ctx->grp.G,
-                               &ctx->Xp1, &ctx->Xp2, ID_PEER,
-                               buf, len ) );
+    return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format,
+                             &ctx->grp.G,
+                             &ctx->Xp1, &ctx->Xp2, ID_PEER,
+                             buf, len);
 }
 
 /*
  * Generate and write the first round message
  */
-int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
-                            unsigned char *buf, size_t len, size_t *olen,
-                            int (*f_rng)(void *, unsigned char *, size_t),
-                            void *p_rng )
+int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx,
+                                    unsigned char *buf, size_t len, size_t *olen,
+                                    int (*f_rng)(void *, unsigned char *, size_t),
+                                    void *p_rng)
 {
-    ECJPAKE_VALIDATE_RET( ctx   != NULL );
-    ECJPAKE_VALIDATE_RET( buf   != NULL );
-    ECJPAKE_VALIDATE_RET( olen  != NULL );
-    ECJPAKE_VALIDATE_RET( f_rng != NULL );
-
-    return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format,
-                                &ctx->grp.G,
-                                &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
-                                ID_MINE, buf, len, olen, f_rng, p_rng ) );
+    return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format,
+                              &ctx->grp.G,
+                              &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
+                              ID_MINE, buf, len, olen, f_rng, p_rng);
 }
 
 /*
  * Compute the sum of three points R = A + B + C
  */
-static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
-                             const mbedtls_ecp_point *A,
-                             const mbedtls_ecp_point *B,
-                             const mbedtls_ecp_point *C )
+static int ecjpake_ecp_add3(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+                            const mbedtls_ecp_point *A,
+                            const mbedtls_ecp_point *B,
+                            const mbedtls_ecp_point *C)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_mpi one;
 
-    mbedtls_mpi_init( &one );
+    mbedtls_mpi_init(&one);
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
-    MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) );
-    MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
+    MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B));
+    MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C));
 
 cleanup:
-    mbedtls_mpi_free( &one );
+    mbedtls_mpi_free(&one);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)
  */
-int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
-                                            const unsigned char *buf,
-                                            size_t len )
+int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,
+                                   const unsigned char *buf,
+                                   size_t len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const unsigned char *p = buf;
@@ -571,11 +616,8 @@
     mbedtls_ecp_group grp;
     mbedtls_ecp_point G;    /* C: GB, S: GA */
 
-    ECJPAKE_VALIDATE_RET( ctx != NULL );
-    ECJPAKE_VALIDATE_RET( buf != NULL );
-
-    mbedtls_ecp_group_init( &grp );
-    mbedtls_ecp_point_init( &G );
+    mbedtls_ecp_group_init(&grp);
+    mbedtls_ecp_point_init(&G);
 
     /*
      * Server: GA = X3  + X4  + X1      (7.4.2.6.1)
@@ -583,8 +625,8 @@
      * Unified: G = Xm1 + Xm2 + Xp1
      * We need that before parsing in order to check Xp as we read it
      */
-    MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
-                                       &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) );
+    MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
+                                     &ctx->Xm1, &ctx->Xm2, &ctx->Xp1));
 
     /*
      * struct {
@@ -592,71 +634,68 @@
      *     ECJPAKEKeyKP ecjpake_key_kp;
      * } Client/ServerECJPAKEParams;
      */
-    if( ctx->role == MBEDTLS_ECJPAKE_CLIENT )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) );
-        if( grp.id != ctx->grp.id )
-        {
+    if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) {
+        MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len));
+        if (grp.id != ctx->grp.id) {
             ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
             goto cleanup;
         }
     }
 
-    MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp,
-                            ctx->point_format,
-                            &G, &ctx->Xp, ID_PEER, &p, end ) );
+    MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp,
+                                     ctx->point_format,
+                                     &G, &ctx->Xp, ID_PEER, &p, end));
 
-    if( p != end )
-    {
+    if (p != end) {
         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
         goto cleanup;
     }
 
 cleanup:
-    mbedtls_ecp_group_free( &grp );
-    mbedtls_ecp_point_free( &G );
+    mbedtls_ecp_group_free(&grp);
+    mbedtls_ecp_point_free(&G);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Compute R = +/- X * S mod N, taking care not to leak S
  */
-static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
-                               const mbedtls_mpi *X,
-                               const mbedtls_mpi *S,
-                               const mbedtls_mpi *N,
-                               int (*f_rng)(void *, unsigned char *, size_t),
-                               void *p_rng )
+static int ecjpake_mul_secret(mbedtls_mpi *R, int sign,
+                              const mbedtls_mpi *X,
+                              const mbedtls_mpi *S,
+                              const mbedtls_mpi *N,
+                              int (*f_rng)(void *, unsigned char *, size_t),
+                              void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_mpi b; /* Blinding value, then s + N * blinding */
 
-    mbedtls_mpi_init( &b );
+    mbedtls_mpi_init(&b);
 
     /* b = s + rnd-128-bit * N */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S));
 
     /* R = sign * X * b mod N */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));
     R->s *= sign;
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));
 
 cleanup:
-    mbedtls_mpi_free( &b );
+    mbedtls_mpi_free(&b);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)
  */
-int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
-                            unsigned char *buf, size_t len, size_t *olen,
-                            int (*f_rng)(void *, unsigned char *, size_t),
-                            void *p_rng )
+int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,
+                                    unsigned char *buf, size_t len, size_t *olen,
+                                    int (*f_rng)(void *, unsigned char *, size_t),
+                                    void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecp_point G;    /* C: GA, S: GB */
@@ -666,14 +705,9 @@
     const unsigned char *end = buf + len;
     size_t ec_len;
 
-    ECJPAKE_VALIDATE_RET( ctx   != NULL );
-    ECJPAKE_VALIDATE_RET( buf   != NULL );
-    ECJPAKE_VALIDATE_RET( olen  != NULL );
-    ECJPAKE_VALIDATE_RET( f_rng != NULL );
-
-    mbedtls_ecp_point_init( &G );
-    mbedtls_ecp_point_init( &Xm );
-    mbedtls_mpi_init( &xm );
+    mbedtls_ecp_point_init(&G);
+    mbedtls_ecp_point_init(&Xm);
+    mbedtls_mpi_init(&xm);
 
     /*
      * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1)
@@ -682,11 +716,11 @@
      * Server:  GB = X3  + X1  + X2  | xs = x4  * s | Xs = xs * GB
      * Unified: G  = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
      */
-    MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G,
-                                       &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) );
-    MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s,
-                                         &ctx->grp.N, f_rng, p_rng ) );
-    MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) );
+    MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
+                                     &ctx->Xp1, &ctx->Xp2, &ctx->Xm1));
+    MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm, 1, &ctx->xm2, &ctx->s,
+                                       &ctx->grp.N, f_rng, p_rng));
+    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &Xm, &xm, &G, f_rng, p_rng));
 
     /*
      * Now write things out
@@ -696,95 +730,134 @@
      *     ECJPAKEKeyKP ecjpake_key_kp;
      * } Client/ServerECJPAKEParams;
      */
-    if( ctx->role == MBEDTLS_ECJPAKE_SERVER )
-    {
-        if( end < p )
-        {
+    if (ctx->role == MBEDTLS_ECJPAKE_SERVER) {
+        if (end < p) {
             ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
             goto cleanup;
         }
-        MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len,
-                                                      p, end - p ) );
+        MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,
+                                                    p, end - p));
         p += ec_len;
     }
 
-    if( end < p )
-    {
+    if (end < p) {
         ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
         goto cleanup;
     }
-    MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm,
-                     ctx->point_format, &ec_len, p, end - p ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,
+                                                ctx->point_format, &ec_len, p, end - p));
     p += ec_len;
 
-    MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp,
-                                        ctx->point_format,
-                                        &G, &xm, &Xm, ID_MINE,
-                                        &p, end, f_rng, p_rng ) );
+    MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp,
+                                      ctx->point_format,
+                                      &G, &xm, &Xm, ID_MINE,
+                                      &p, end, f_rng, p_rng));
 
     *olen = p - buf;
 
 cleanup:
-    mbedtls_ecp_point_free( &G );
-    mbedtls_ecp_point_free( &Xm );
-    mbedtls_mpi_free( &xm );
+    mbedtls_ecp_point_free(&G);
+    mbedtls_ecp_point_free(&Xm);
+    mbedtls_mpi_free(&xm);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Derive PMS (7.4.2.7 / 7.4.2.8)
  */
-int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
-                            unsigned char *buf, size_t len, size_t *olen,
-                            int (*f_rng)(void *, unsigned char *, size_t),
-                            void *p_rng )
+static int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx,
+                                    mbedtls_ecp_point *K,
+                                    int (*f_rng)(void *, unsigned char *, size_t),
+                                    void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_ecp_point K;
     mbedtls_mpi m_xm2_s, one;
-    unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
-    size_t x_bytes;
 
-    ECJPAKE_VALIDATE_RET( ctx   != NULL );
-    ECJPAKE_VALIDATE_RET( buf   != NULL );
-    ECJPAKE_VALIDATE_RET( olen  != NULL );
-    ECJPAKE_VALIDATE_RET( f_rng != NULL );
+    mbedtls_mpi_init(&m_xm2_s);
+    mbedtls_mpi_init(&one);
 
-    *olen = mbedtls_md_get_size( ctx->md_info );
-    if( len < *olen )
-        return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
-
-    mbedtls_ecp_point_init( &K );
-    mbedtls_mpi_init( &m_xm2_s );
-    mbedtls_mpi_init( &one );
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
 
     /*
      * Client:  K = ( Xs - X4  * x2  * s ) * x2
      * Server:  K = ( Xc - X2  * x4  * s ) * x4
      * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
      */
-    MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
-                                         &ctx->grp.N, f_rng, p_rng ) );
-    MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
-                                         &one, &ctx->Xp,
-                                         &m_xm2_s, &ctx->Xp2 ) );
-    MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
-                                      f_rng, p_rng ) );
-
-    /* PMS = SHA-256( K.X ) */
-    x_bytes = ( ctx->grp.pbits + 7 ) / 8;
-    MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
-    MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) );
+    MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s,
+                                       &ctx->grp.N, f_rng, p_rng));
+    MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K,
+                                       &one, &ctx->Xp,
+                                       &m_xm2_s, &ctx->Xp2));
+    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K,
+                                    f_rng, p_rng));
 
 cleanup:
-    mbedtls_ecp_point_free( &K );
-    mbedtls_mpi_free( &m_xm2_s );
-    mbedtls_mpi_free( &one );
+    mbedtls_mpi_free(&m_xm2_s);
+    mbedtls_mpi_free(&one);
 
-    return( ret );
+    return ret;
+}
+
+int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,
+                                  unsigned char *buf, size_t len, size_t *olen,
+                                  int (*f_rng)(void *, unsigned char *, size_t),
+                                  void *p_rng)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ecp_point K;
+    unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
+    size_t x_bytes;
+
+    *olen = mbedtls_hash_info_get_size(ctx->md_type);
+    if (len < *olen) {
+        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+    }
+
+    mbedtls_ecp_point_init(&K);
+
+    ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
+    if (ret) {
+        goto cleanup;
+    }
+
+    /* PMS = SHA-256( K.X ) */
+    x_bytes = (ctx->grp.pbits + 7) / 8;
+    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes));
+    MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type,
+                                                 kx, x_bytes, buf));
+
+cleanup:
+    mbedtls_ecp_point_free(&K);
+
+    return ret;
+}
+
+int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx,
+                                     unsigned char *buf, size_t len, size_t *olen,
+                                     int (*f_rng)(void *, unsigned char *, size_t),
+                                     void *p_rng)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ecp_point K;
+
+    mbedtls_ecp_point_init(&K);
+
+    ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
+    if (ret) {
+        goto cleanup;
+    }
+
+    ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format,
+                                         olen, buf, len);
+    if (ret != 0) {
+        goto cleanup;
+    }
+
+cleanup:
+    mbedtls_ecp_point_free(&K);
+
+    return ret;
 }
 
 #undef ID_MINE
@@ -794,19 +867,14 @@
 
 #if defined(MBEDTLS_SELF_TEST)
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf     printf
-#endif
 
 #if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
     !defined(MBEDTLS_SHA256_C)
-int mbedtls_ecjpake_self_test( int verbose )
+int mbedtls_ecjpake_self_test(int verbose)
 {
     (void) verbose;
-    return( 0 );
+    return 0;
 }
 #else
 
@@ -937,66 +1005,95 @@
     0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
 };
 
+static const unsigned char ecjpake_test_shared_key[] = {
+    0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80,
+    0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79,
+    0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1,
+    0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0,
+    0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12,
+    0x17, 0xc3, 0xde, 0x27, 0xb4,
+};
+
 static const unsigned char ecjpake_test_pms[] = {
     0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
     0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
     0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
 };
 
+/*
+ * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
+ *
+ * This is the linear congruential generator from numerical recipes,
+ * except we only use the low byte as the output. See
+ * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
+ */
+static int self_test_rng(void *ctx, unsigned char *out, size_t len)
+{
+    static uint32_t state = 42;
+
+    (void) ctx;
+
+    for (size_t i = 0; i < len; i++) {
+        state = state * 1664525u + 1013904223u;
+        out[i] = (unsigned char) state;
+    }
+
+    return 0;
+}
+
 /* Load my private keys and generate the corresponding public keys */
-static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
-                              const unsigned char *xm1, size_t len1,
-                              const unsigned char *xm2, size_t len2 )
+static int ecjpake_test_load(mbedtls_ecjpake_context *ctx,
+                             const unsigned char *xm1, size_t len1,
+                             const unsigned char *xm2, size_t len2)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
-    MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1,
-                                      &ctx->grp.G, NULL, NULL ) );
-    MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2,
-                                      &ctx->grp.G, NULL, NULL ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2));
+    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1,
+                                    &ctx->grp.G, self_test_rng, NULL));
+    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2,
+                                    &ctx->grp.G, self_test_rng, NULL));
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 #endif /* ! MBEDTLS_ECJPAKE_ALT */
 
 /* For tests we don't need a secure RNG;
  * use the LGC from Numerical Recipes for simplicity */
-static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
+static int ecjpake_lgc(void *p, unsigned char *out, size_t len)
 {
     static uint32_t x = 42;
     (void) p;
 
-    while( len > 0 )
-    {
+    while (len > 0) {
         size_t use_len = len > 4 ? 4 : len;
         x = 1664525 * x + 1013904223;
-        memcpy( out, &x, use_len );
+        memcpy(out, &x, use_len);
         out += use_len;
         len -= use_len;
     }
 
-    return( 0 );
+    return 0;
 }
 
-#define TEST_ASSERT( x )    \
+#define TEST_ASSERT(x)    \
     do {                    \
-        if( x )             \
-            ret = 0;        \
+        if (x)             \
+        ret = 0;        \
         else                \
         {                   \
             ret = 1;        \
             goto cleanup;   \
         }                   \
-    } while( 0 )
+    } while (0)
 
 /*
  * Checkup routine
  */
-int mbedtls_ecjpake_self_test( int verbose )
+int mbedtls_ecjpake_self_test(int verbose)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecjpake_context cli;
@@ -1004,59 +1101,63 @@
     unsigned char buf[512], pms[32];
     size_t len, pmslen;
 
-    mbedtls_ecjpake_init( &cli );
-    mbedtls_ecjpake_init( &srv );
+    mbedtls_ecjpake_init(&cli);
+    mbedtls_ecjpake_init(&srv);
 
-    if( verbose != 0 )
-        mbedtls_printf( "  ECJPAKE test #0 (setup): " );
+    if (verbose != 0) {
+        mbedtls_printf("  ECJPAKE test #0 (setup): ");
+    }
 
-    TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT,
-                    MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
-                    ecjpake_test_password,
-            sizeof( ecjpake_test_password ) ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT,
+                                      MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
+                                      ecjpake_test_password,
+                                      sizeof(ecjpake_test_password)) == 0);
 
-    TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER,
-                    MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
-                    ecjpake_test_password,
-            sizeof( ecjpake_test_password ) ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER,
+                                      MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
+                                      ecjpake_test_password,
+                                      sizeof(ecjpake_test_password)) == 0);
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
 
-    if( verbose != 0 )
-        mbedtls_printf( "  ECJPAKE test #1 (random handshake): " );
+    if (verbose != 0) {
+        mbedtls_printf("  ECJPAKE test #1 (random handshake): ");
+    }
 
-    TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli,
-                 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,
+                                                buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
 
-    TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);
 
-    TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv,
-                 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv,
+                                                buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
 
-    TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0);
 
-    TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv,
-                 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv,
+                                                buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
 
-    TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);
 
-    TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
-                 pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
+                                              pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);
 
-    TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli,
-                 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,
+                                                buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
 
-    TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);
 
-    TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
-                 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
+                                              buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
 
-    TEST_ASSERT( len == pmslen );
-    TEST_ASSERT( memcmp( buf, pms, len ) == 0 );
+    TEST_ASSERT(len == pmslen);
+    TEST_ASSERT(memcmp(buf, pms, len) == 0);
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
 
 #if !defined(MBEDTLS_ECJPAKE_ALT)
     /* 'reference handshake' tests can only be run against implementations
@@ -1064,72 +1165,89 @@
      * are generated. This is only the case for the internal mbed TLS
      * implementation, so these tests are skipped in case the internal
      * implementation is swapped out for an alternative one. */
-    if( verbose != 0 )
-        mbedtls_printf( "  ECJPAKE test #2 (reference handshake): " );
+    if (verbose != 0) {
+        mbedtls_printf("  ECJPAKE test #2 (reference handshake): ");
+    }
 
     /* Simulate generation of round one */
-    MBEDTLS_MPI_CHK( ecjpake_test_load( &cli,
-                ecjpake_test_x1, sizeof( ecjpake_test_x1 ),
-                ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) );
+    MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,
+                                      ecjpake_test_x1, sizeof(ecjpake_test_x1),
+                                      ecjpake_test_x2, sizeof(ecjpake_test_x2)));
 
-    MBEDTLS_MPI_CHK( ecjpake_test_load( &srv,
-                ecjpake_test_x3, sizeof( ecjpake_test_x3 ),
-                ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) );
+    MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,
+                                      ecjpake_test_x3, sizeof(ecjpake_test_x3),
+                                      ecjpake_test_x4, sizeof(ecjpake_test_x4)));
 
     /* Read round one */
-    TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv,
-                                    ecjpake_test_cli_one,
-                            sizeof( ecjpake_test_cli_one ) ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,
+                                               ecjpake_test_cli_one,
+                                               sizeof(ecjpake_test_cli_one)) == 0);
 
-    TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli,
-                                    ecjpake_test_srv_one,
-                            sizeof( ecjpake_test_srv_one ) ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,
+                                               ecjpake_test_srv_one,
+                                               sizeof(ecjpake_test_srv_one)) == 0);
 
     /* Skip generation of round two, read round two */
-    TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli,
-                                    ecjpake_test_srv_two,
-                            sizeof( ecjpake_test_srv_two ) ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,
+                                               ecjpake_test_srv_two,
+                                               sizeof(ecjpake_test_srv_two)) == 0);
 
-    TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv,
-                                    ecjpake_test_cli_two,
-                            sizeof( ecjpake_test_cli_two ) ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,
+                                               ecjpake_test_cli_two,
+                                               sizeof(ecjpake_test_cli_two)) == 0);
 
     /* Server derives PMS */
-    TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv,
-                 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
+                                              buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
 
-    TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
-    TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
+    TEST_ASSERT(len == sizeof(ecjpake_test_pms));
+    TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
 
-    memset( buf, 0, len ); /* Avoid interferences with next step */
+    /* Server derives K as unsigned binary data */
+    TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv,
+                                                 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
+
+    TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
+    TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
+
+    memset(buf, 0, len);   /* Avoid interferences with next step */
 
     /* Client derives PMS */
-    TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli,
-                 buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
+    TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
+                                              buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
 
-    TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
-    TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
+    TEST_ASSERT(len == sizeof(ecjpake_test_pms));
+    TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    /* Client derives K as unsigned binary data */
+    TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli,
+                                                 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
+
+    TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
+    TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
+
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
 #endif /* ! MBEDTLS_ECJPAKE_ALT */
 
 cleanup:
-    mbedtls_ecjpake_free( &cli );
-    mbedtls_ecjpake_free( &srv );
+    mbedtls_ecjpake_free(&cli);
+    mbedtls_ecjpake_free(&srv);
 
-    if( ret != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
+    if (ret != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("failed\n");
+        }
 
         ret = 1;
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
-    return( ret );
+    return ret;
 }
 
 #undef TEST_ASSERT
diff --git a/lib/libmbedtls/mbedtls/library/ecp.c b/lib/libmbedtls/mbedtls/library/ecp.c
index 192ce6f..607d753 100644
--- a/lib/libmbedtls/mbedtls/library/ecp.c
+++ b/lib/libmbedtls/mbedtls/library/ecp.c
@@ -76,46 +76,17 @@
 #include "mbedtls/threading.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
-#include "mbedtls/bn_mul.h"
 
+#include "bn_mul.h"
 #include "ecp_invasive.h"
 
 #include <string.h>
 
 #if !defined(MBEDTLS_ECP_ALT)
 
-/* Parameter validation macros based on platform_util.h */
-#define ECP_VALIDATE_RET( cond )    \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
-#define ECP_VALIDATE( cond )        \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
-
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#include <stdio.h>
-#define mbedtls_printf     printf
-#define mbedtls_calloc    calloc
-#define mbedtls_free       free
-#endif
 
-#include "mbedtls/ecp_internal.h"
-
-#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
-#if defined(MBEDTLS_HMAC_DRBG_C)
-#include "mbedtls/hmac_drbg.h"
-#elif defined(MBEDTLS_CTR_DRBG_C)
-#include "mbedtls/ctr_drbg.h"
-#else
-#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
-#endif
-#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
-
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
-    !defined(inline) && !defined(__cplusplus)
-#define inline __inline
-#endif
+#include "ecp_internal_alt.h"
 
 #if defined(MBEDTLS_SELF_TEST)
 /*
@@ -125,144 +96,6 @@
 static unsigned long add_count, dbl_count, mul_count;
 #endif
 
-#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
-/*
- * Currently ecp_mul() takes a RNG function as an argument, used for
- * side-channel protection, but it can be NULL. The initial reasoning was
- * that people will pass non-NULL RNG when they care about side-channels, but
- * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with
- * no opportunity for the user to do anything about it.
- *
- * The obvious strategies for addressing that include:
- * - change those APIs so that they take RNG arguments;
- * - require a global RNG to be available to all crypto modules.
- *
- * Unfortunately those would break compatibility. So what we do instead is
- * have our own internal DRBG instance, seeded from the secret scalar.
- *
- * The following is a light-weight abstraction layer for doing that with
- * HMAC_DRBG (first choice) or CTR_DRBG.
- */
-
-#if defined(MBEDTLS_HMAC_DRBG_C)
-
-/* DRBG context type */
-typedef mbedtls_hmac_drbg_context ecp_drbg_context;
-
-/* DRBG context init */
-static inline void ecp_drbg_init( ecp_drbg_context *ctx )
-{
-    mbedtls_hmac_drbg_init( ctx );
-}
-
-/* DRBG context free */
-static inline void ecp_drbg_free( ecp_drbg_context *ctx )
-{
-    mbedtls_hmac_drbg_free( ctx );
-}
-
-/* DRBG function */
-static inline int ecp_drbg_random( void *p_rng,
-                                   unsigned char *output, size_t output_len )
-{
-    return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) );
-}
-
-/* DRBG context seeding */
-static int ecp_drbg_seed( ecp_drbg_context *ctx,
-                   const mbedtls_mpi *secret, size_t secret_len )
-{
-    int ret;
-    unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
-    /* The list starts with strong hashes */
-    const mbedtls_md_type_t md_type = mbedtls_md_list()[0];
-    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type );
-
-    if( secret_len > MBEDTLS_ECP_MAX_BYTES )
-    {
-        ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
-        goto cleanup;
-    }
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
-                                               secret_bytes, secret_len ) );
-
-    ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len );
-
-cleanup:
-    mbedtls_platform_zeroize( secret_bytes, secret_len );
-
-    return( ret );
-}
-
-#elif defined(MBEDTLS_CTR_DRBG_C)
-
-/* DRBG context type */
-typedef mbedtls_ctr_drbg_context ecp_drbg_context;
-
-/* DRBG context init */
-static inline void ecp_drbg_init( ecp_drbg_context *ctx )
-{
-    mbedtls_ctr_drbg_init( ctx );
-}
-
-/* DRBG context free */
-static inline void ecp_drbg_free( ecp_drbg_context *ctx )
-{
-    mbedtls_ctr_drbg_free( ctx );
-}
-
-/* DRBG function */
-static inline int ecp_drbg_random( void *p_rng,
-                                   unsigned char *output, size_t output_len )
-{
-    return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) );
-}
-
-/*
- * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does,
- * we need to pass an entropy function when seeding. So we use a dummy
- * function for that, and pass the actual entropy as customisation string.
- * (During seeding of CTR_DRBG the entropy input and customisation string are
- * concatenated before being used to update the secret state.)
- */
-static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len)
-{
-    (void) ctx;
-    memset( out, 0, len );
-    return( 0 );
-}
-
-/* DRBG context seeding */
-static int ecp_drbg_seed( ecp_drbg_context *ctx,
-                   const mbedtls_mpi *secret, size_t secret_len )
-{
-    int ret;
-    unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
-
-    if( secret_len > MBEDTLS_ECP_MAX_BYTES )
-    {
-        ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
-        goto cleanup;
-    }
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
-                                               secret_bytes, secret_len ) );
-
-    ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL,
-                                 secret_bytes, secret_len );
-
-cleanup:
-    mbedtls_platform_zeroize( secret_bytes, secret_len );
-
-    return( ret );
-}
-
-#else
-#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
-#endif /* DRBG modules */
-#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
-
 #if defined(MBEDTLS_ECP_RESTARTABLE)
 /*
  * Maximum number of "basic operations" to be done in a row.
@@ -279,7 +112,7 @@
 /*
  * Set ecp_max_ops
  */
-void mbedtls_ecp_set_max_ops( unsigned max_ops )
+void mbedtls_ecp_set_max_ops(unsigned max_ops)
 {
     ecp_max_ops = max_ops;
 }
@@ -287,16 +120,15 @@
 /*
  * Check if restart is enabled
  */
-int mbedtls_ecp_restart_is_enabled( void )
+int mbedtls_ecp_restart_is_enabled(void)
 {
-    return( ecp_max_ops != 0 );
+    return ecp_max_ops != 0;
 }
 
 /*
  * Restart sub-context for ecp_mul_comb()
  */
-struct mbedtls_ecp_restart_mul
-{
+struct mbedtls_ecp_restart_mul {
     mbedtls_ecp_point R;    /* current intermediate result                  */
     size_t i;               /* current index in various loops, 0 outside    */
     mbedtls_ecp_point *T;   /* table for precomputed points                 */
@@ -310,59 +142,47 @@
         ecp_rsm_comb_core,      /* ecp_mul_comb_core()                      */
         ecp_rsm_final_norm,     /* do the final normalization               */
     } state;
-#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
-    ecp_drbg_context drbg_ctx;
-    unsigned char drbg_seeded;
-#endif
 };
 
 /*
  * Init restart_mul sub-context
  */
-static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx )
+static void ecp_restart_rsm_init(mbedtls_ecp_restart_mul_ctx *ctx)
 {
-    mbedtls_ecp_point_init( &ctx->R );
+    mbedtls_ecp_point_init(&ctx->R);
     ctx->i = 0;
     ctx->T = NULL;
     ctx->T_size = 0;
     ctx->state = ecp_rsm_init;
-#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
-    ecp_drbg_init( &ctx->drbg_ctx );
-    ctx->drbg_seeded = 0;
-#endif
 }
 
 /*
  * Free the components of a restart_mul sub-context
  */
-static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx )
+static void ecp_restart_rsm_free(mbedtls_ecp_restart_mul_ctx *ctx)
 {
     unsigned char i;
 
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
-
-    mbedtls_ecp_point_free( &ctx->R );
-
-    if( ctx->T != NULL )
-    {
-        for( i = 0; i < ctx->T_size; i++ )
-            mbedtls_ecp_point_free( ctx->T + i );
-        mbedtls_free( ctx->T );
     }
 
-#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
-    ecp_drbg_free( &ctx->drbg_ctx );
-#endif
+    mbedtls_ecp_point_free(&ctx->R);
 
-    ecp_restart_rsm_init( ctx );
+    if (ctx->T != NULL) {
+        for (i = 0; i < ctx->T_size; i++) {
+            mbedtls_ecp_point_free(ctx->T + i);
+        }
+        mbedtls_free(ctx->T);
+    }
+
+    ecp_restart_rsm_init(ctx);
 }
 
 /*
  * Restart context for ecp_muladd()
  */
-struct mbedtls_ecp_restart_muladd
-{
+struct mbedtls_ecp_restart_muladd {
     mbedtls_ecp_point mP;       /* mP value                             */
     mbedtls_ecp_point R;        /* R intermediate result                */
     enum {                      /* what should we do next?              */
@@ -376,33 +196,33 @@
 /*
  * Init restart_muladd sub-context
  */
-static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx )
+static void ecp_restart_ma_init(mbedtls_ecp_restart_muladd_ctx *ctx)
 {
-    mbedtls_ecp_point_init( &ctx->mP );
-    mbedtls_ecp_point_init( &ctx->R );
+    mbedtls_ecp_point_init(&ctx->mP);
+    mbedtls_ecp_point_init(&ctx->R);
     ctx->state = ecp_rsma_mul1;
 }
 
 /*
  * Free the components of a restart_muladd sub-context
  */
-static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx )
+static void ecp_restart_ma_free(mbedtls_ecp_restart_muladd_ctx *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_ecp_point_free( &ctx->mP );
-    mbedtls_ecp_point_free( &ctx->R );
+    mbedtls_ecp_point_free(&ctx->mP);
+    mbedtls_ecp_point_free(&ctx->R);
 
-    ecp_restart_ma_init( ctx );
+    ecp_restart_ma_init(ctx);
 }
 
 /*
  * Initialize a restart context
  */
-void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx )
+void mbedtls_ecp_restart_init(mbedtls_ecp_restart_ctx *ctx)
 {
-    ECP_VALIDATE( ctx != NULL );
     ctx->ops_done = 0;
     ctx->depth = 0;
     ctx->rsm = NULL;
@@ -412,96 +232,108 @@
 /*
  * Free the components of a restart context
  */
-void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx )
+void mbedtls_ecp_restart_free(mbedtls_ecp_restart_ctx *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    ecp_restart_rsm_free( ctx->rsm );
-    mbedtls_free( ctx->rsm );
+    ecp_restart_rsm_free(ctx->rsm);
+    mbedtls_free(ctx->rsm);
 
-    ecp_restart_ma_free( ctx->ma );
-    mbedtls_free( ctx->ma );
+    ecp_restart_ma_free(ctx->ma);
+    mbedtls_free(ctx->ma);
 
-    mbedtls_ecp_restart_init( ctx );
+    mbedtls_ecp_restart_init(ctx);
 }
 
 /*
  * Check if we can do the next step
  */
-int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp,
-                              mbedtls_ecp_restart_ctx *rs_ctx,
-                              unsigned ops )
+int mbedtls_ecp_check_budget(const mbedtls_ecp_group *grp,
+                             mbedtls_ecp_restart_ctx *rs_ctx,
+                             unsigned ops)
 {
-    ECP_VALIDATE_RET( grp != NULL );
-
-    if( rs_ctx != NULL && ecp_max_ops != 0 )
-    {
+    if (rs_ctx != NULL && ecp_max_ops != 0) {
         /* scale depending on curve size: the chosen reference is 256-bit,
          * and multiplication is quadratic. Round to the closest integer. */
-        if( grp->pbits >= 512 )
+        if (grp->pbits >= 512) {
             ops *= 4;
-        else if( grp->pbits >= 384 )
+        } else if (grp->pbits >= 384) {
             ops *= 2;
+        }
 
         /* Avoid infinite loops: always allow first step.
          * Because of that, however, it's not generally true
          * that ops_done <= ecp_max_ops, so the check
          * ops_done > ecp_max_ops below is mandatory. */
-        if( ( rs_ctx->ops_done != 0 ) &&
-            ( rs_ctx->ops_done > ecp_max_ops ||
-              ops > ecp_max_ops - rs_ctx->ops_done ) )
-        {
-            return( MBEDTLS_ERR_ECP_IN_PROGRESS );
+        if ((rs_ctx->ops_done != 0) &&
+            (rs_ctx->ops_done > ecp_max_ops ||
+             ops > ecp_max_ops - rs_ctx->ops_done)) {
+            return MBEDTLS_ERR_ECP_IN_PROGRESS;
         }
 
         /* update running count */
         rs_ctx->ops_done += ops;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /* Call this when entering a function that needs its own sub-context */
-#define ECP_RS_ENTER( SUB )   do {                                      \
-    /* reset ops count for this call if top-level */                    \
-    if( rs_ctx != NULL && rs_ctx->depth++ == 0 )                        \
+#define ECP_RS_ENTER(SUB)   do {                                      \
+        /* reset ops count for this call if top-level */                    \
+        if (rs_ctx != NULL && rs_ctx->depth++ == 0)                        \
         rs_ctx->ops_done = 0;                                           \
                                                                         \
-    /* set up our own sub-context if needed */                          \
-    if( mbedtls_ecp_restart_is_enabled() &&                             \
-        rs_ctx != NULL && rs_ctx->SUB == NULL )                         \
-    {                                                                   \
-        rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) );      \
-        if( rs_ctx->SUB == NULL )                                       \
-            return( MBEDTLS_ERR_ECP_ALLOC_FAILED );                     \
-                                                                        \
-        ecp_restart_## SUB ##_init( rs_ctx->SUB );                      \
-    }                                                                   \
-} while( 0 )
+        /* set up our own sub-context if needed */                          \
+        if (mbedtls_ecp_restart_is_enabled() &&                             \
+            rs_ctx != NULL && rs_ctx->SUB == NULL)                         \
+        {                                                                   \
+            rs_ctx->SUB = mbedtls_calloc(1, sizeof(*rs_ctx->SUB));      \
+            if (rs_ctx->SUB == NULL)                                       \
+            return MBEDTLS_ERR_ECP_ALLOC_FAILED;                     \
+                                                                      \
+            ecp_restart_## SUB ##_init(rs_ctx->SUB);                      \
+        }                                                                   \
+} while (0)
 
 /* Call this when leaving a function that needs its own sub-context */
-#define ECP_RS_LEAVE( SUB )   do {                                      \
-    /* clear our sub-context when not in progress (done or error) */    \
-    if( rs_ctx != NULL && rs_ctx->SUB != NULL &&                        \
-        ret != MBEDTLS_ERR_ECP_IN_PROGRESS )                            \
-    {                                                                   \
-        ecp_restart_## SUB ##_free( rs_ctx->SUB );                      \
-        mbedtls_free( rs_ctx->SUB );                                    \
-        rs_ctx->SUB = NULL;                                             \
-    }                                                                   \
+#define ECP_RS_LEAVE(SUB)   do {                                      \
+        /* clear our sub-context when not in progress (done or error) */    \
+        if (rs_ctx != NULL && rs_ctx->SUB != NULL &&                        \
+            ret != MBEDTLS_ERR_ECP_IN_PROGRESS)                            \
+        {                                                                   \
+            ecp_restart_## SUB ##_free(rs_ctx->SUB);                      \
+            mbedtls_free(rs_ctx->SUB);                                    \
+            rs_ctx->SUB = NULL;                                             \
+        }                                                                   \
                                                                         \
-    if( rs_ctx != NULL )                                                \
+        if (rs_ctx != NULL)                                                \
         rs_ctx->depth--;                                                \
-} while( 0 )
+} while (0)
 
 #else /* MBEDTLS_ECP_RESTARTABLE */
 
-#define ECP_RS_ENTER( sub )     (void) rs_ctx;
-#define ECP_RS_LEAVE( sub )     (void) rs_ctx;
+#define ECP_RS_ENTER(sub)     (void) rs_ctx;
+#define ECP_RS_LEAVE(sub)     (void) rs_ctx;
 
 #endif /* MBEDTLS_ECP_RESTARTABLE */
 
+static void mpi_init_many(mbedtls_mpi *arr, size_t size)
+{
+    while (size--) {
+        mbedtls_mpi_init(arr++);
+    }
+}
+
+static void mpi_free_many(mbedtls_mpi *arr, size_t size)
+{
+    while (size--) {
+        mbedtls_mpi_free(arr++);
+    }
+}
+
 /*
  * List of supported curves:
  *  - internal ID
@@ -510,9 +342,9 @@
  *  - readable name
  *
  * Curves are listed in order: largest curves first, and for a given size,
- * fastest curves first. This provides the default order for the SSL module.
+ * fastest curves first.
  *
- * Reminder: update profiles in x509_crt.c when adding a new curves!
+ * Reminder: update profiles in x509_crt.c and ssl_tls.c when adding a new curve!
  */
 static const mbedtls_ecp_curve_info ecp_supported_curves[] =
 {
@@ -562,35 +394,33 @@
     { MBEDTLS_ECP_DP_NONE,          0,     0,      NULL                },
 };
 
-#define ECP_NB_CURVES   sizeof( ecp_supported_curves ) /    \
-                        sizeof( ecp_supported_curves[0] )
+#define ECP_NB_CURVES   sizeof(ecp_supported_curves) /    \
+    sizeof(ecp_supported_curves[0])
 
 static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
 
 /*
  * List of supported curves and associated info
  */
-const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void )
+const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list(void)
 {
-    return( ecp_supported_curves );
+    return ecp_supported_curves;
 }
 
 /*
  * List of supported curves, group ID only
  */
-const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void )
+const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list(void)
 {
     static int init_done = 0;
 
-    if( ! init_done )
-    {
+    if (!init_done) {
         size_t i = 0;
         const mbedtls_ecp_curve_info *curve_info;
 
-        for( curve_info = mbedtls_ecp_curve_list();
+        for (curve_info = mbedtls_ecp_curve_list();
              curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
-             curve_info++ )
-        {
+             curve_info++) {
             ecp_supported_grp_id[i++] = curve_info->grp_id;
         }
         ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;
@@ -598,105 +428,104 @@
         init_done = 1;
     }
 
-    return( ecp_supported_grp_id );
+    return ecp_supported_grp_id;
 }
 
 /*
  * Get the curve info for the internal identifier
  */
-const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id )
+const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id(mbedtls_ecp_group_id grp_id)
 {
     const mbedtls_ecp_curve_info *curve_info;
 
-    for( curve_info = mbedtls_ecp_curve_list();
+    for (curve_info = mbedtls_ecp_curve_list();
          curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
-         curve_info++ )
-    {
-        if( curve_info->grp_id == grp_id )
-            return( curve_info );
+         curve_info++) {
+        if (curve_info->grp_id == grp_id) {
+            return curve_info;
+        }
     }
 
-    return( NULL );
+    return NULL;
 }
 
 /*
  * Get the curve info from the TLS identifier
  */
-const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id )
+const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id(uint16_t tls_id)
 {
     const mbedtls_ecp_curve_info *curve_info;
 
-    for( curve_info = mbedtls_ecp_curve_list();
+    for (curve_info = mbedtls_ecp_curve_list();
          curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
-         curve_info++ )
-    {
-        if( curve_info->tls_id == tls_id )
-            return( curve_info );
+         curve_info++) {
+        if (curve_info->tls_id == tls_id) {
+            return curve_info;
+        }
     }
 
-    return( NULL );
+    return NULL;
 }
 
 /*
  * Get the curve info from the name
  */
-const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name )
+const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name(const char *name)
 {
     const mbedtls_ecp_curve_info *curve_info;
 
-    if( name == NULL )
-        return( NULL );
-
-    for( curve_info = mbedtls_ecp_curve_list();
-         curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
-         curve_info++ )
-    {
-        if( strcmp( curve_info->name, name ) == 0 )
-            return( curve_info );
+    if (name == NULL) {
+        return NULL;
     }
 
-    return( NULL );
+    for (curve_info = mbedtls_ecp_curve_list();
+         curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
+         curve_info++) {
+        if (strcmp(curve_info->name, name) == 0) {
+            return curve_info;
+        }
+    }
+
+    return NULL;
 }
 
 /*
  * Get the type of a curve
  */
-mbedtls_ecp_curve_type mbedtls_ecp_get_type( const mbedtls_ecp_group *grp )
+mbedtls_ecp_curve_type mbedtls_ecp_get_type(const mbedtls_ecp_group *grp)
 {
-    if( grp->G.X.p == NULL )
-        return( MBEDTLS_ECP_TYPE_NONE );
+    if (grp->G.X.p == NULL) {
+        return MBEDTLS_ECP_TYPE_NONE;
+    }
 
-    if( grp->G.Y.p == NULL )
-        return( MBEDTLS_ECP_TYPE_MONTGOMERY );
-    else
-        return( MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS );
+    if (grp->G.Y.p == NULL) {
+        return MBEDTLS_ECP_TYPE_MONTGOMERY;
+    } else {
+        return MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS;
+    }
 }
 
 /*
  * Initialize (the components of) a point
  */
-void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
+void mbedtls_ecp_point_init(mbedtls_ecp_point *pt)
 {
-    ECP_VALIDATE( pt != NULL );
-
-    mbedtls_mpi_init( &pt->X );
-    mbedtls_mpi_init( &pt->Y );
-    mbedtls_mpi_init( &pt->Z );
+    mbedtls_mpi_init(&pt->X);
+    mbedtls_mpi_init(&pt->Y);
+    mbedtls_mpi_init(&pt->Z);
 }
 
 /*
  * Initialize (the components of) a group
  */
-void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
+void mbedtls_ecp_group_init(mbedtls_ecp_group *grp)
 {
-    ECP_VALIDATE( grp != NULL );
-
     grp->id = MBEDTLS_ECP_DP_NONE;
-    mbedtls_mpi_init( &grp->P );
-    mbedtls_mpi_init( &grp->A );
-    mbedtls_mpi_init( &grp->B );
-    mbedtls_ecp_point_init( &grp->G );
-    mbedtls_mpi_init( &grp->N );
+    mbedtls_mpi_init(&grp->P);
+    mbedtls_mpi_init(&grp->A);
+    mbedtls_mpi_init(&grp->B);
+    mbedtls_ecp_point_init(&grp->G);
+    mbedtls_mpi_init(&grp->N);
     grp->pbits = 0;
     grp->nbits = 0;
     grp->h = 0;
@@ -711,297 +540,303 @@
 /*
  * Initialize (the components of) a key pair
  */
-void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
+void mbedtls_ecp_keypair_init(mbedtls_ecp_keypair *key)
 {
-    ECP_VALIDATE( key != NULL );
-
-    mbedtls_ecp_group_init( &key->grp );
-    mbedtls_mpi_init( &key->d );
-    mbedtls_ecp_point_init( &key->Q );
+    mbedtls_ecp_group_init(&key->grp);
+    mbedtls_mpi_init(&key->d);
+    mbedtls_ecp_point_init(&key->Q);
 }
 
 /*
  * Unallocate (the components of) a point
  */
-void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
+void mbedtls_ecp_point_free(mbedtls_ecp_point *pt)
 {
-    if( pt == NULL )
+    if (pt == NULL) {
         return;
+    }
 
-    mbedtls_mpi_free( &( pt->X ) );
-    mbedtls_mpi_free( &( pt->Y ) );
-    mbedtls_mpi_free( &( pt->Z ) );
+    mbedtls_mpi_free(&(pt->X));
+    mbedtls_mpi_free(&(pt->Y));
+    mbedtls_mpi_free(&(pt->Z));
+}
+
+/*
+ * Check that the comb table (grp->T) is static initialized.
+ */
+static int ecp_group_is_static_comb_table(const mbedtls_ecp_group *grp)
+{
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+    return grp->T != NULL && grp->T_size == 0;
+#else
+    (void) grp;
+    return 0;
+#endif
 }
 
 /*
  * Unallocate (the components of) a group
  */
-void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
+void mbedtls_ecp_group_free(mbedtls_ecp_group *grp)
 {
     size_t i;
 
-    if( grp == NULL )
+    if (grp == NULL) {
         return;
-
-    if( grp->h != 1 )
-    {
-        mbedtls_mpi_free( &grp->P );
-        mbedtls_mpi_free( &grp->A );
-        mbedtls_mpi_free( &grp->B );
-        mbedtls_ecp_point_free( &grp->G );
-        mbedtls_mpi_free( &grp->N );
     }
 
-    if( grp->T != NULL )
-    {
-        for( i = 0; i < grp->T_size; i++ )
-            mbedtls_ecp_point_free( &grp->T[i] );
-        mbedtls_free( grp->T );
+    if (grp->h != 1) {
+        mbedtls_mpi_free(&grp->A);
+        mbedtls_mpi_free(&grp->B);
+        mbedtls_ecp_point_free(&grp->G);
     }
 
-    mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) );
+    if (!ecp_group_is_static_comb_table(grp) && grp->T != NULL) {
+        for (i = 0; i < grp->T_size; i++) {
+            mbedtls_ecp_point_free(&grp->T[i]);
+        }
+        mbedtls_free(grp->T);
+    }
+
+    mbedtls_platform_zeroize(grp, sizeof(mbedtls_ecp_group));
 }
 
 /*
  * Unallocate (the components of) a key pair
  */
-void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
+void mbedtls_ecp_keypair_free(mbedtls_ecp_keypair *key)
 {
-    if( key == NULL )
+    if (key == NULL) {
         return;
+    }
 
-    mbedtls_ecp_group_free( &key->grp );
-    mbedtls_mpi_free( &key->d );
-    mbedtls_ecp_point_free( &key->Q );
+    mbedtls_ecp_group_free(&key->grp);
+    mbedtls_mpi_free(&key->d);
+    mbedtls_ecp_point_free(&key->Q);
 }
 
 /*
  * Copy the contents of a point
  */
-int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
+int mbedtls_ecp_copy(mbedtls_ecp_point *P, const mbedtls_ecp_point *Q)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    ECP_VALIDATE_RET( P != NULL );
-    ECP_VALIDATE_RET( Q != NULL );
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&P->X, &Q->X));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&P->Y, &Q->Y));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&P->Z, &Q->Z));
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
  * Copy the contents of a group object
  */
-int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
+int mbedtls_ecp_group_copy(mbedtls_ecp_group *dst, const mbedtls_ecp_group *src)
 {
-    ECP_VALIDATE_RET( dst != NULL );
-    ECP_VALIDATE_RET( src != NULL );
-
-    return( mbedtls_ecp_group_load( dst, src->id ) );
+    return mbedtls_ecp_group_load(dst, src->id);
 }
 
 /*
  * Set point to zero
  */
-int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
+int mbedtls_ecp_set_zero(mbedtls_ecp_point *pt)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    ECP_VALIDATE_RET( pt != NULL );
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->X, 1));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Y, 1));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Z, 0));
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
  * Tell if a point is zero
  */
-int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
+int mbedtls_ecp_is_zero(mbedtls_ecp_point *pt)
 {
-    ECP_VALIDATE_RET( pt != NULL );
-
-    return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
+    return mbedtls_mpi_cmp_int(&pt->Z, 0) == 0;
 }
 
 /*
  * Compare two points lazily
  */
-int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
-                           const mbedtls_ecp_point *Q )
+int mbedtls_ecp_point_cmp(const mbedtls_ecp_point *P,
+                          const mbedtls_ecp_point *Q)
 {
-    ECP_VALIDATE_RET( P != NULL );
-    ECP_VALIDATE_RET( Q != NULL );
-
-    if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
-        mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
-        mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
-    {
-        return( 0 );
+    if (mbedtls_mpi_cmp_mpi(&P->X, &Q->X) == 0 &&
+        mbedtls_mpi_cmp_mpi(&P->Y, &Q->Y) == 0 &&
+        mbedtls_mpi_cmp_mpi(&P->Z, &Q->Z) == 0) {
+        return 0;
     }
 
-    return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
 }
 
 /*
  * Import a non-zero point from ASCII strings
  */
-int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
-                           const char *x, const char *y )
+int mbedtls_ecp_point_read_string(mbedtls_ecp_point *P, int radix,
+                                  const char *x, const char *y)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    ECP_VALIDATE_RET( P != NULL );
-    ECP_VALIDATE_RET( x != NULL );
-    ECP_VALIDATE_RET( y != NULL );
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&P->X, radix, x));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&P->Y, radix, y));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&P->Z, 1));
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
  * Export a point into unsigned binary data (SEC1 2.3.3 and RFC7748)
  */
-int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp,
-                                    const mbedtls_ecp_point *P,
-                                    int format, size_t *olen,
-                                    unsigned char *buf, size_t buflen )
+int mbedtls_ecp_point_write_binary(const mbedtls_ecp_group *grp,
+                                   const mbedtls_ecp_point *P,
+                                   int format, size_t *olen,
+                                   unsigned char *buf, size_t buflen)
 {
     int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
     size_t plen;
-    ECP_VALIDATE_RET( grp  != NULL );
-    ECP_VALIDATE_RET( P    != NULL );
-    ECP_VALIDATE_RET( olen != NULL );
-    ECP_VALIDATE_RET( buf  != NULL );
-    ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
-                      format == MBEDTLS_ECP_PF_COMPRESSED );
+    if (format != MBEDTLS_ECP_PF_UNCOMPRESSED &&
+        format != MBEDTLS_ECP_PF_COMPRESSED) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
-    plen = mbedtls_mpi_size( &grp->P );
+    plen = mbedtls_mpi_size(&grp->P);
 
 #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
     (void) format; /* Montgomery curves always use the same point format */
-    if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
-    {
+    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
         *olen = plen;
-        if( buflen < *olen )
-            return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
+        if (buflen < *olen) {
+            return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+        }
 
-        MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary_le( &P->X, buf, plen ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary_le(&P->X, buf, plen));
     }
 #endif
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
-    if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
-    {
+    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
         /*
          * Common case: P == 0
          */
-        if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
-        {
-            if( buflen < 1 )
-                return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
+        if (mbedtls_mpi_cmp_int(&P->Z, 0) == 0) {
+            if (buflen < 1) {
+                return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+            }
 
             buf[0] = 0x00;
             *olen = 1;
 
-            return( 0 );
+            return 0;
         }
 
-        if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
-        {
+        if (format == MBEDTLS_ECP_PF_UNCOMPRESSED) {
             *olen = 2 * plen + 1;
 
-            if( buflen < *olen )
-                return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
+            if (buflen < *olen) {
+                return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+            }
 
             buf[0] = 0x04;
-            MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
-        }
-        else if( format == MBEDTLS_ECP_PF_COMPRESSED )
-        {
+            MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&P->X, buf + 1, plen));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&P->Y, buf + 1 + plen, plen));
+        } else if (format == MBEDTLS_ECP_PF_COMPRESSED) {
             *olen = plen + 1;
 
-            if( buflen < *olen )
-                return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
+            if (buflen < *olen) {
+                return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+            }
 
-            buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
+            buf[0] = 0x02 + mbedtls_mpi_get_bit(&P->Y, 0);
+            MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&P->X, buf + 1, plen));
         }
     }
 #endif
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
+#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
+static int mbedtls_ecp_sw_derive_y(const mbedtls_ecp_group *grp,
+                                   const mbedtls_mpi *X,
+                                   mbedtls_mpi *Y,
+                                   int parity_bit);
+#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
+
 /*
  * Import a point from unsigned binary data (SEC1 2.3.4 and RFC7748)
  */
-int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp,
-                                   mbedtls_ecp_point *pt,
-                                   const unsigned char *buf, size_t ilen )
+int mbedtls_ecp_point_read_binary(const mbedtls_ecp_group *grp,
+                                  mbedtls_ecp_point *pt,
+                                  const unsigned char *buf, size_t ilen)
 {
     int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
     size_t plen;
-    ECP_VALIDATE_RET( grp != NULL );
-    ECP_VALIDATE_RET( pt  != NULL );
-    ECP_VALIDATE_RET( buf != NULL );
+    if (ilen < 1) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
-    if( ilen < 1 )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
-
-    plen = mbedtls_mpi_size( &grp->P );
+    plen = mbedtls_mpi_size(&grp->P);
 
 #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
-    if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
-    {
-        if( plen != ilen )
-            return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
+        if (plen != ilen) {
+            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+        }
 
-        MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary_le( &pt->X, buf, plen ) );
-        mbedtls_mpi_free( &pt->Y );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary_le(&pt->X, buf, plen));
+        mbedtls_mpi_free(&pt->Y);
 
-        if( grp->id == MBEDTLS_ECP_DP_CURVE25519 )
+        if (grp->id == MBEDTLS_ECP_DP_CURVE25519) {
             /* Set most significant bit to 0 as prescribed in RFC7748 §5 */
-            MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &pt->X, plen * 8 - 1, 0 ) );
+            MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&pt->X, plen * 8 - 1, 0));
+        }
 
-        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Z, 1));
     }
 #endif
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
-    if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
-    {
-        if( buf[0] == 0x00 )
-        {
-            if( ilen == 1 )
-                return( mbedtls_ecp_set_zero( pt ) );
-            else
-                return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
+        if (buf[0] == 0x00) {
+            if (ilen == 1) {
+                return mbedtls_ecp_set_zero(pt);
+            } else {
+                return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+            }
         }
 
-        if( buf[0] != 0x04 )
-            return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+        if (ilen < 1 + plen) {
+            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+        }
 
-        if( ilen != 2 * plen + 1 )
-            return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&pt->X, buf + 1, plen));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Z, 1));
 
-        MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y,
-                                                  buf + 1 + plen, plen ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
+        if (buf[0] == 0x04) {
+            /* format == MBEDTLS_ECP_PF_UNCOMPRESSED */
+            if (ilen != 1 + plen * 2) {
+                return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+            }
+            return mbedtls_mpi_read_binary(&pt->Y, buf + 1 + plen, plen);
+        } else if (buf[0] == 0x02 || buf[0] == 0x03) {
+            /* format == MBEDTLS_ECP_PF_COMPRESSED */
+            if (ilen != 1 + plen) {
+                return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+            }
+            return mbedtls_ecp_sw_derive_y(grp, &pt->X, &pt->Y,
+                                           (buf[0] & 1));
+        } else {
+            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+        }
     }
 #endif
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
@@ -1010,26 +845,23 @@
  *          opaque point <1..2^8-1>;
  *      } ECPoint;
  */
-int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp,
-                                mbedtls_ecp_point *pt,
-                                const unsigned char **buf, size_t buf_len )
+int mbedtls_ecp_tls_read_point(const mbedtls_ecp_group *grp,
+                               mbedtls_ecp_point *pt,
+                               const unsigned char **buf, size_t buf_len)
 {
     unsigned char data_len;
     const unsigned char *buf_start;
-    ECP_VALIDATE_RET( grp != NULL );
-    ECP_VALIDATE_RET( pt  != NULL );
-    ECP_VALIDATE_RET( buf != NULL );
-    ECP_VALIDATE_RET( *buf != NULL );
-
     /*
      * We must have at least two bytes (1 for length, at least one for data)
      */
-    if( buf_len < 2 )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (buf_len < 2) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
     data_len = *(*buf)++;
-    if( data_len < 1 || data_len > buf_len - 1 )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (data_len < 1 || data_len > buf_len - 1) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
     /*
      * Save buffer start for read_binary and update buf
@@ -1037,7 +869,7 @@
     buf_start = *buf;
     *buf += data_len;
 
-    return( mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ) );
+    return mbedtls_ecp_point_read_binary(grp, pt, buf_start, data_len);
 }
 
 /*
@@ -1046,27 +878,27 @@
  *          opaque point <1..2^8-1>;
  *      } ECPoint;
  */
-int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
-                         int format, size_t *olen,
-                         unsigned char *buf, size_t blen )
+int mbedtls_ecp_tls_write_point(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
+                                int format, size_t *olen,
+                                unsigned char *buf, size_t blen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    ECP_VALIDATE_RET( grp  != NULL );
-    ECP_VALIDATE_RET( pt   != NULL );
-    ECP_VALIDATE_RET( olen != NULL );
-    ECP_VALIDATE_RET( buf  != NULL );
-    ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
-                      format == MBEDTLS_ECP_PF_COMPRESSED );
+    if (format != MBEDTLS_ECP_PF_UNCOMPRESSED &&
+        format != MBEDTLS_ECP_PF_COMPRESSED) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
     /*
      * buffer length must be at least one, for our length byte
      */
-    if( blen < 1 )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (blen < 1) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
-    if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format,
-                    olen, buf + 1, blen - 1) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_ecp_point_write_binary(grp, pt, format,
+                                              olen, buf + 1, blen - 1)) != 0) {
+        return ret;
+    }
 
     /*
      * write length to the first byte and update total length
@@ -1074,51 +906,46 @@
     buf[0] = (unsigned char) *olen;
     ++*olen;
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Set a group from an ECParameters record (RFC 4492)
  */
-int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp,
-                                const unsigned char **buf, size_t len )
+int mbedtls_ecp_tls_read_group(mbedtls_ecp_group *grp,
+                               const unsigned char **buf, size_t len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecp_group_id grp_id;
-    ECP_VALIDATE_RET( grp  != NULL );
-    ECP_VALIDATE_RET( buf  != NULL );
-    ECP_VALIDATE_RET( *buf != NULL );
+    if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, len)) != 0) {
+        return ret;
+    }
 
-    if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 )
-        return( ret );
-
-    return( mbedtls_ecp_group_load( grp, grp_id ) );
+    return mbedtls_ecp_group_load(grp, grp_id);
 }
 
 /*
  * Read a group id from an ECParameters record (RFC 4492) and convert it to
  * mbedtls_ecp_group_id.
  */
-int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp,
-                                   const unsigned char **buf, size_t len )
+int mbedtls_ecp_tls_read_group_id(mbedtls_ecp_group_id *grp,
+                                  const unsigned char **buf, size_t len)
 {
     uint16_t tls_id;
     const mbedtls_ecp_curve_info *curve_info;
-    ECP_VALIDATE_RET( grp  != NULL );
-    ECP_VALIDATE_RET( buf  != NULL );
-    ECP_VALIDATE_RET( *buf != NULL );
-
     /*
      * We expect at least three bytes (see below)
      */
-    if( len < 3 )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (len < 3) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
     /*
      * First byte is curve_type; only named_curve is handled
      */
-    if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (*(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
     /*
      * Next two bytes are the namedcurve value
@@ -1127,34 +954,33 @@
     tls_id <<= 8;
     tls_id |= *(*buf)++;
 
-    if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
-        return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+    if ((curve_info = mbedtls_ecp_curve_info_from_tls_id(tls_id)) == NULL) {
+        return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+    }
 
     *grp = curve_info->grp_id;
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Write the ECParameters record corresponding to a group (RFC 4492)
  */
-int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
-                         unsigned char *buf, size_t blen )
+int mbedtls_ecp_tls_write_group(const mbedtls_ecp_group *grp, size_t *olen,
+                                unsigned char *buf, size_t blen)
 {
     const mbedtls_ecp_curve_info *curve_info;
-    ECP_VALIDATE_RET( grp  != NULL );
-    ECP_VALIDATE_RET( buf  != NULL );
-    ECP_VALIDATE_RET( olen != NULL );
-
-    if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if ((curve_info = mbedtls_ecp_curve_info_from_grp_id(grp->id)) == NULL) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
     /*
      * We are going to write 3 bytes (see below)
      */
     *olen = 3;
-    if( blen < *olen )
-        return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
+    if (blen < *olen) {
+        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+    }
 
     /*
      * First byte is curve_type, always named_curve
@@ -1164,9 +990,9 @@
     /*
      * Next two bytes are the namedcurve value
      */
-    MBEDTLS_PUT_UINT16_BE( curve_info->tls_id, buf, 0 );
+    MBEDTLS_PUT_UINT16_BE(curve_info->tls_id, buf, 0);
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -1175,32 +1001,34 @@
  *
  * This function is in the critial loop for mbedtls_ecp_mul, so pay attention to perf.
  */
-static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
+static int ecp_modp(mbedtls_mpi *N, const mbedtls_ecp_group *grp)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( grp->modp == NULL )
-        return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
-
-    /* N->s < 0 is a much faster test, which fails only if N is 0 */
-    if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) ||
-        mbedtls_mpi_bitlen( N ) > 2 * grp->pbits )
-    {
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (grp->modp == NULL) {
+        return mbedtls_mpi_mod_mpi(N, N, &grp->P);
     }
 
-    MBEDTLS_MPI_CHK( grp->modp( N ) );
+    /* N->s < 0 is a much faster test, which fails only if N is 0 */
+    if ((N->s < 0 && mbedtls_mpi_cmp_int(N, 0) != 0) ||
+        mbedtls_mpi_bitlen(N) > 2 * grp->pbits) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    MBEDTLS_MPI_CHK(grp->modp(N));
 
     /* N->s < 0 is a much faster test, which fails only if N is 0 */
-    while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) );
+    while (N->s < 0 && mbedtls_mpi_cmp_int(N, 0) != 0) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(N, N, &grp->P));
+    }
 
-    while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 )
+    while (mbedtls_mpi_cmp_mpi(N, &grp->P) >= 0) {
         /* we known P, N and the result are positive */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(N, N, &grp->P));
+    }
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
@@ -1222,50 +1050,52 @@
 #define INC_MUL_COUNT
 #endif
 
-#define MOD_MUL( N )                                                    \
+#define MOD_MUL(N)                                                    \
     do                                                                  \
     {                                                                   \
-        MBEDTLS_MPI_CHK( ecp_modp( &(N), grp ) );                       \
+        MBEDTLS_MPI_CHK(ecp_modp(&(N), grp));                       \
         INC_MUL_COUNT                                                   \
-    } while( 0 )
+    } while (0)
 
-static inline int mbedtls_mpi_mul_mod( const mbedtls_ecp_group *grp,
-                                       mbedtls_mpi *X,
-                                       const mbedtls_mpi *A,
-                                       const mbedtls_mpi *B )
+static inline int mbedtls_mpi_mul_mod(const mbedtls_ecp_group *grp,
+                                      mbedtls_mpi *X,
+                                      const mbedtls_mpi *A,
+                                      const mbedtls_mpi *B)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( X, A, B ) );
-    MOD_MUL( *X );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(X, A, B));
+    MOD_MUL(*X);
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
  * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
  * N->s < 0 is a very fast test, which fails only if N is 0
  */
-#define MOD_SUB( N )                                                    \
-    while( (N).s < 0 && mbedtls_mpi_cmp_int( &(N), 0 ) != 0 )           \
-        MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &(N), &(N), &grp->P ) )
+#define MOD_SUB(N)                                                          \
+    do {                                                                      \
+        while ((N)->s < 0 && mbedtls_mpi_cmp_int((N), 0) != 0)             \
+        MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi((N), (N), &grp->P));      \
+    } while (0)
 
-#if ( defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) && \
-      !( defined(MBEDTLS_ECP_NO_FALLBACK) && \
-         defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && \
-         defined(MBEDTLS_ECP_ADD_MIXED_ALT) ) ) || \
-    ( defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) && \
-      !( defined(MBEDTLS_ECP_NO_FALLBACK) && \
-         defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) ) )
-static inline int mbedtls_mpi_sub_mod( const mbedtls_ecp_group *grp,
-                                       mbedtls_mpi *X,
-                                       const mbedtls_mpi *A,
-                                       const mbedtls_mpi *B )
+#if (defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) && \
+    !(defined(MBEDTLS_ECP_NO_FALLBACK) && \
+    defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && \
+    defined(MBEDTLS_ECP_ADD_MIXED_ALT))) || \
+    (defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) && \
+    !(defined(MBEDTLS_ECP_NO_FALLBACK) && \
+    defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)))
+static inline int mbedtls_mpi_sub_mod(const mbedtls_ecp_group *grp,
+                                      mbedtls_mpi *X,
+                                      const mbedtls_mpi *A,
+                                      const mbedtls_mpi *B)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( X, A, B ) );
-    MOD_SUB( *X );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(X, A, B));
+    MOD_SUB(X);
 cleanup:
-    return( ret );
+    return ret;
 }
 #endif /* All functions referencing mbedtls_mpi_sub_mod() are alt-implemented without fallback */
 
@@ -1274,39 +1104,213 @@
  * We known P, N and the result are positive, so sub_abs is correct, and
  * a bit faster.
  */
-#define MOD_ADD( N )                                                    \
-    while( mbedtls_mpi_cmp_mpi( &(N), &grp->P ) >= 0 )                  \
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &(N), &(N), &grp->P ) )
+#define MOD_ADD(N)                                                   \
+    while (mbedtls_mpi_cmp_mpi((N), &grp->P) >= 0)                  \
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs((N), (N), &grp->P))
 
-static inline int mbedtls_mpi_add_mod( const mbedtls_ecp_group *grp,
-                                       mbedtls_mpi *X,
-                                       const mbedtls_mpi *A,
-                                       const mbedtls_mpi *B )
+static inline int mbedtls_mpi_add_mod(const mbedtls_ecp_group *grp,
+                                      mbedtls_mpi *X,
+                                      const mbedtls_mpi *A,
+                                      const mbedtls_mpi *B)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, A, B ) );
-    MOD_ADD( *X );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, A, B));
+    MOD_ADD(X);
 cleanup:
-    return( ret );
+    return ret;
 }
 
+static inline int mbedtls_mpi_mul_int_mod(const mbedtls_ecp_group *grp,
+                                          mbedtls_mpi *X,
+                                          const mbedtls_mpi *A,
+                                          mbedtls_mpi_uint c)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(X, A, c));
+    MOD_ADD(X);
+cleanup:
+    return ret;
+}
+
+static inline int mbedtls_mpi_sub_int_mod(const mbedtls_ecp_group *grp,
+                                          mbedtls_mpi *X,
+                                          const mbedtls_mpi *A,
+                                          mbedtls_mpi_uint c)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(X, A, c));
+    MOD_SUB(X);
+cleanup:
+    return ret;
+}
+
+#define MPI_ECP_SUB_INT(X, A, c)             \
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int_mod(grp, X, A, c))
+
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) && \
-    !( defined(MBEDTLS_ECP_NO_FALLBACK) && \
-       defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && \
-       defined(MBEDTLS_ECP_ADD_MIXED_ALT) )
-static inline int mbedtls_mpi_shift_l_mod( const mbedtls_ecp_group *grp,
-                                           mbedtls_mpi *X,
-                                           size_t count )
+    !(defined(MBEDTLS_ECP_NO_FALLBACK) && \
+    defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && \
+    defined(MBEDTLS_ECP_ADD_MIXED_ALT))
+static inline int mbedtls_mpi_shift_l_mod(const mbedtls_ecp_group *grp,
+                                          mbedtls_mpi *X,
+                                          size_t count)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( X, count ) );
-    MOD_ADD( *X );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(X, count));
+    MOD_ADD(X);
 cleanup:
-    return( ret );
+    return ret;
 }
-#endif /* All functions referencing mbedtls_mpi_shift_l_mod() are alt-implemented without fallback */
+#endif \
+    /* All functions referencing mbedtls_mpi_shift_l_mod() are alt-implemented without fallback */
+
+/*
+ * Macro wrappers around ECP modular arithmetic
+ *
+ * Currently, these wrappers are defined via the bignum module.
+ */
+
+#define MPI_ECP_ADD(X, A, B)                                                  \
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mod(grp, X, A, B))
+
+#define MPI_ECP_SUB(X, A, B)                                                  \
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, X, A, B))
+
+#define MPI_ECP_MUL(X, A, B)                                                  \
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, X, A, B))
+
+#define MPI_ECP_SQR(X, A)                                                     \
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, X, A, A))
+
+#define MPI_ECP_MUL_INT(X, A, c)                                              \
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int_mod(grp, X, A, c))
+
+#define MPI_ECP_INV(dst, src)                                                 \
+    MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod((dst), (src), &grp->P))
+
+#define MPI_ECP_MOV(X, A)                                                     \
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A))
+
+#define MPI_ECP_SHIFT_L(X, count)                                             \
+    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l_mod(grp, X, count))
+
+#define MPI_ECP_LSET(X, c)                                                    \
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, c))
+
+#define MPI_ECP_CMP_INT(X, c)                                                 \
+    mbedtls_mpi_cmp_int(X, c)
+
+#define MPI_ECP_CMP(X, Y)                                                     \
+    mbedtls_mpi_cmp_mpi(X, Y)
+
+/* Needs f_rng, p_rng to be defined. */
+#define MPI_ECP_RAND(X)                                                       \
+    MBEDTLS_MPI_CHK(mbedtls_mpi_random((X), 2, &grp->P, f_rng, p_rng))
+
+/* Conditional negation
+ * Needs grp and a temporary MPI tmp to be defined. */
+#define MPI_ECP_COND_NEG(X, cond)                                        \
+    do                                                                     \
+    {                                                                      \
+        unsigned char nonzero = mbedtls_mpi_cmp_int((X), 0) != 0;        \
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&tmp, &grp->P, (X)));      \
+        MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign((X), &tmp,          \
+                                                     nonzero & cond)); \
+    } while (0)
+
+#define MPI_ECP_NEG(X) MPI_ECP_COND_NEG((X), 1)
+
+#define MPI_ECP_VALID(X)                      \
+    ((X)->p != NULL)
+
+#define MPI_ECP_COND_ASSIGN(X, Y, cond)       \
+    MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign((X), (Y), (cond)))
+
+#define MPI_ECP_COND_SWAP(X, Y, cond)       \
+    MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_swap((X), (Y), (cond)))
 
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
+
+/*
+ * Computes the right-hand side of the Short Weierstrass equation
+ * RHS = X^3 + A X + B
+ */
+static int ecp_sw_rhs(const mbedtls_ecp_group *grp,
+                      mbedtls_mpi *rhs,
+                      const mbedtls_mpi *X)
+{
+    int ret;
+
+    /* Compute X^3 + A X + B as X (X^2 + A) + B */
+    MPI_ECP_SQR(rhs, X);
+
+    /* Special case for A = -3 */
+    if (grp->A.p == NULL) {
+        MPI_ECP_SUB_INT(rhs, rhs, 3);
+    } else {
+        MPI_ECP_ADD(rhs, rhs, &grp->A);
+    }
+
+    MPI_ECP_MUL(rhs, rhs, X);
+    MPI_ECP_ADD(rhs, rhs, &grp->B);
+
+cleanup:
+    return ret;
+}
+
+/*
+ * Derive Y from X and a parity bit
+ */
+static int mbedtls_ecp_sw_derive_y(const mbedtls_ecp_group *grp,
+                                   const mbedtls_mpi *X,
+                                   mbedtls_mpi *Y,
+                                   int parity_bit)
+{
+    /* w = y^2 = x^3 + ax + b
+     * y = sqrt(w) = w^((p+1)/4) mod p   (for prime p where p = 3 mod 4)
+     *
+     * Note: this method for extracting square root does not validate that w
+     * was indeed a square so this function will return garbage in Y if X
+     * does not correspond to a point on the curve.
+     */
+
+    /* Check prerequisite p = 3 mod 4 */
+    if (mbedtls_mpi_get_bit(&grp->P, 0) != 1 ||
+        mbedtls_mpi_get_bit(&grp->P, 1) != 1) {
+        return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+    }
+
+    int ret;
+    mbedtls_mpi exp;
+    mbedtls_mpi_init(&exp);
+
+    /* use Y to store intermediate result, actually w above */
+    MBEDTLS_MPI_CHK(ecp_sw_rhs(grp, Y, X));
+
+    /* w = y^2 */ /* Y contains y^2 intermediate result */
+    /* exp = ((p+1)/4) */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&exp, &grp->P, 1));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&exp, 2));
+    /* sqrt(w) = w^((p+1)/4) mod p   (for prime p where p = 3 mod 4) */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(Y, Y /*y^2*/, &exp, &grp->P, NULL));
+
+    /* check parity bit match or else invert Y */
+    /* This quick inversion implementation is valid because Y != 0 for all
+     * Short Weierstrass curves supported by mbedtls, as each supported curve
+     * has an order that is a large prime, so each supported curve does not
+     * have any point of order 2, and a point with Y == 0 would be of order 2 */
+    if (mbedtls_mpi_get_bit(Y, 0) != parity_bit) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(Y, &grp->P, Y));
+    }
+
+cleanup:
+
+    mbedtls_mpi_free(&exp);
+    return ret;
+}
+
 /*
  * For curves in short Weierstrass form, we do all the internal operations in
  * Jacobian coordinates.
@@ -1319,46 +1323,38 @@
  * Normalize jacobian coordinates so that Z == 0 || Z == 1  (GECC 3.2.1)
  * Cost: 1N := 1I + 3M + 1S
  */
-static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
+static int ecp_normalize_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt)
 {
-    if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
-        return( 0 );
+    if (MPI_ECP_CMP_INT(&pt->Z, 0) == 0) {
+        return 0;
+    }
 
 #if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
-    if( mbedtls_internal_ecp_grp_capable( grp ) )
-        return( mbedtls_internal_ecp_normalize_jac( grp, pt ) );
+    if (mbedtls_internal_ecp_grp_capable(grp)) {
+        return mbedtls_internal_ecp_normalize_jac(grp, pt);
+    }
 #endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
 
 #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
-    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
 #else
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_mpi Zi, ZZi;
-    mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
+    mbedtls_mpi T;
+    mbedtls_mpi_init(&T);
 
-    /*
-     * X = X / Z^2  mod p
-     */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi,      &pt->Z,     &grp->P ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ZZi,     &Zi,        &Zi     ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->X,   &pt->X,     &ZZi    ) );
+    MPI_ECP_INV(&T,       &pt->Z);            /* T   <-          1 / Z   */
+    MPI_ECP_MUL(&pt->Y,   &pt->Y,     &T);    /* Y'  <- Y*T    = Y / Z   */
+    MPI_ECP_SQR(&T,       &T);                /* T   <- T^2    = 1 / Z^2 */
+    MPI_ECP_MUL(&pt->X,   &pt->X,     &T);    /* X   <- X  * T = X / Z^2 */
+    MPI_ECP_MUL(&pt->Y,   &pt->Y,     &T);    /* Y'' <- Y' * T = Y / Z^3 */
 
-    /*
-     * Y = Y / Z^3  mod p
-     */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Y,   &pt->Y,     &ZZi    ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Y,   &pt->Y,     &Zi     ) );
-
-    /*
-     * Z = 1
-     */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
+    MPI_ECP_LSET(&pt->Z, 1);
 
 cleanup:
 
-    mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
+    mbedtls_mpi_free(&T);
 
-    return( ret );
+    return ret;
 #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) */
 }
 
@@ -1373,68 +1369,72 @@
  *
  * Cost: 1N(t) := 1I + (6t - 3)M + 1S
  */
-static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
-                                   mbedtls_ecp_point *T[], size_t T_size )
+static int ecp_normalize_jac_many(const mbedtls_ecp_group *grp,
+                                  mbedtls_ecp_point *T[], size_t T_size)
 {
-    if( T_size < 2 )
-        return( ecp_normalize_jac( grp, *T ) );
+    if (T_size < 2) {
+        return ecp_normalize_jac(grp, *T);
+    }
 
 #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
-    if( mbedtls_internal_ecp_grp_capable( grp ) )
-        return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) );
+    if (mbedtls_internal_ecp_grp_capable(grp)) {
+        return mbedtls_internal_ecp_normalize_jac_many(grp, T, T_size);
+    }
 #endif
 
 #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
-    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
 #else
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i;
-    mbedtls_mpi *c, u, Zi, ZZi;
+    mbedtls_mpi *c, t;
 
-    if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL )
-        return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
+    if ((c = mbedtls_calloc(T_size, sizeof(mbedtls_mpi))) == NULL) {
+        return MBEDTLS_ERR_ECP_ALLOC_FAILED;
+    }
 
-    for( i = 0; i < T_size; i++ )
-        mbedtls_mpi_init( &c[i] );
+    mbedtls_mpi_init(&t);
 
-    mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
-
+    mpi_init_many(c, T_size);
     /*
-     * c[i] = Z_0 * ... * Z_i
+     * c[i] = Z_0 * ... * Z_i,   i = 0,..,n := T_size-1
      */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
-    for( i = 1; i < T_size; i++ )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &c[i], &c[i-1], &T[i]->Z ) );
+    MPI_ECP_MOV(&c[0], &T[0]->Z);
+    for (i = 1; i < T_size; i++) {
+        MPI_ECP_MUL(&c[i], &c[i-1], &T[i]->Z);
     }
 
     /*
-     * u = 1 / (Z_0 * ... * Z_n) mod P
+     * c[n] = 1 / (Z_0 * ... * Z_n) mod P
      */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) );
+    MPI_ECP_INV(&c[T_size-1], &c[T_size-1]);
 
-    for( i = T_size - 1; ; i-- )
-    {
-        /*
-         * Zi = 1 / Z_i mod p
-         * u = 1 / (Z_0 * ... * Z_i) mod P
+    for (i = T_size - 1;; i--) {
+        /* At the start of iteration i (note that i decrements), we have
+         * - c[j] = Z_0 * .... * Z_j        for j  < i,
+         * - c[j] = 1 / (Z_0 * .... * Z_j)  for j == i,
+         *
+         * This is maintained via
+         * - c[i-1] <- c[i] * Z_i
+         *
+         * We also derive 1/Z_i = c[i] * c[i-1] for i>0 and use that
+         * to do the actual normalization. For i==0, we already have
+         * c[0] = 1 / Z_0.
          */
-        if( i == 0 ) {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) );
-        }
-        else
-        {
-            MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &Zi, &u, &c[i-1]  ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &u,  &u, &T[i]->Z ) );
+
+        if (i > 0) {
+            /* Compute 1/Z_i and establish invariant for the next iteration. */
+            MPI_ECP_MUL(&t,      &c[i], &c[i-1]);
+            MPI_ECP_MUL(&c[i-1], &c[i], &T[i]->Z);
+        } else {
+            MPI_ECP_MOV(&t, &c[0]);
         }
 
-        /*
-         * proceed as in normalize()
-         */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ZZi,     &Zi,      &Zi  ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T[i]->X, &T[i]->X, &ZZi ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T[i]->Y, &T[i]->Y, &ZZi ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T[i]->Y, &T[i]->Y, &Zi  ) );
+        /* Now t holds 1 / Z_i; normalize as in ecp_normalize_jac() */
+        MPI_ECP_MUL(&T[i]->Y, &T[i]->Y, &t);
+        MPI_ECP_SQR(&t,       &t);
+        MPI_ECP_MUL(&T[i]->X, &T[i]->X, &t);
+        MPI_ECP_MUL(&T[i]->Y, &T[i]->Y, &t);
 
         /*
          * Post-precessing: reclaim some memory by shrinking coordinates
@@ -1442,22 +1442,23 @@
          * - shrinking other coordinates, but still keeping the same number of
          *   limbs as P, as otherwise it will too likely be regrown too fast.
          */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
-        mbedtls_mpi_free( &T[i]->Z );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(&T[i]->X, grp->P.n));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(&T[i]->Y, grp->P.n));
 
-        if( i == 0 )
+        MPI_ECP_LSET(&T[i]->Z, 1);
+
+        if (i == 0) {
             break;
+        }
     }
 
 cleanup:
 
-    mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
-    for( i = 0; i < T_size; i++ )
-        mbedtls_mpi_free( &c[i] );
-    mbedtls_free( c );
+    mbedtls_mpi_free(&t);
+    mpi_free_many(c, T_size);
+    mbedtls_free(c);
 
-    return( ret );
+    return ret;
 #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) */
 }
 
@@ -1465,25 +1466,19 @@
  * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
  * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
  */
-static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
-                            mbedtls_ecp_point *Q,
-                            unsigned char inv )
+static int ecp_safe_invert_jac(const mbedtls_ecp_group *grp,
+                               mbedtls_ecp_point *Q,
+                               unsigned char inv)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char nonzero;
-    mbedtls_mpi mQY;
+    mbedtls_mpi tmp;
+    mbedtls_mpi_init(&tmp);
 
-    mbedtls_mpi_init( &mQY );
-
-    /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
-    nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0;
-    MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
+    MPI_ECP_COND_NEG(&Q->Y, inv);
 
 cleanup:
-    mbedtls_mpi_free( &mQY );
-
-    return( ret );
+    mbedtls_mpi_free(&tmp);
+    return ret;
 }
 
 /*
@@ -1500,85 +1495,80 @@
  *             4M + 4S          (A == -3)
  *             3M + 6S + 1a     otherwise
  */
-static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
-                           const mbedtls_ecp_point *P )
+static int ecp_double_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+                          const mbedtls_ecp_point *P,
+                          mbedtls_mpi tmp[4])
 {
 #if defined(MBEDTLS_SELF_TEST)
     dbl_count++;
 #endif
 
 #if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
-    if( mbedtls_internal_ecp_grp_capable( grp ) )
-        return( mbedtls_internal_ecp_double_jac( grp, R, P ) );
+    if (mbedtls_internal_ecp_grp_capable(grp)) {
+        return mbedtls_internal_ecp_double_jac(grp, R, P);
+    }
 #endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
 
 #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
-    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
 #else
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_mpi M, S, T, U;
-
-    mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U );
 
     /* Special case for A = -3 */
-    if( grp->A.p == NULL )
-    {
-        /* M = 3(X + Z^2)(X - Z^2) */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S,  &P->Z,  &P->Z   ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &T,  &P->X,  &S      ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &U,  &P->X,  &S      ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S,  &T,     &U      ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M,  &S,     3       ) ); MOD_ADD( M );
-    }
-    else
-    {
-        /* M = 3.X^2 */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S,  &P->X,  &P->X   ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M,  &S,     3       ) ); MOD_ADD( M );
+    if (grp->A.p == NULL) {
+        /* tmp[0] <- M = 3(X + Z^2)(X - Z^2) */
+        MPI_ECP_SQR(&tmp[1],  &P->Z);
+        MPI_ECP_ADD(&tmp[2],  &P->X,  &tmp[1]);
+        MPI_ECP_SUB(&tmp[3],  &P->X,  &tmp[1]);
+        MPI_ECP_MUL(&tmp[1],  &tmp[2],     &tmp[3]);
+        MPI_ECP_MUL_INT(&tmp[0],  &tmp[1],     3);
+    } else {
+        /* tmp[0] <- M = 3.X^2 + A.Z^4 */
+        MPI_ECP_SQR(&tmp[1],  &P->X);
+        MPI_ECP_MUL_INT(&tmp[0],  &tmp[1],  3);
 
         /* Optimize away for "koblitz" curves with A = 0 */
-        if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
-        {
+        if (MPI_ECP_CMP_INT(&grp->A, 0) != 0) {
             /* M += A.Z^4 */
-            MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S,  &P->Z,  &P->Z   ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T,  &S,     &S      ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S,  &T,     &grp->A ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &M,  &M,     &S      ) );
+            MPI_ECP_SQR(&tmp[1],  &P->Z);
+            MPI_ECP_SQR(&tmp[2],  &tmp[1]);
+            MPI_ECP_MUL(&tmp[1],  &tmp[2],     &grp->A);
+            MPI_ECP_ADD(&tmp[0],  &tmp[0],     &tmp[1]);
         }
     }
 
-    /* S = 4.X.Y^2 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T,  &P->Y,  &P->Y   ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &T,  1               ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S,  &P->X,  &T      ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &S,  1               ) );
+    /* tmp[1] <- S = 4.X.Y^2 */
+    MPI_ECP_SQR(&tmp[2],  &P->Y);
+    MPI_ECP_SHIFT_L(&tmp[2],  1);
+    MPI_ECP_MUL(&tmp[1],  &P->X, &tmp[2]);
+    MPI_ECP_SHIFT_L(&tmp[1],  1);
 
-    /* U = 8.Y^4 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &U,  &T,     &T      ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &U,  1               ) );
+    /* tmp[3] <- U = 8.Y^4 */
+    MPI_ECP_SQR(&tmp[3],  &tmp[2]);
+    MPI_ECP_SHIFT_L(&tmp[3],  1);
 
-    /* T = M^2 - 2.S */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T,  &M,     &M      ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T,  &T,     &S      ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T,  &T,     &S      ) );
+    /* tmp[2] <- T = M^2 - 2.S */
+    MPI_ECP_SQR(&tmp[2],  &tmp[0]);
+    MPI_ECP_SUB(&tmp[2],  &tmp[2], &tmp[1]);
+    MPI_ECP_SUB(&tmp[2],  &tmp[2], &tmp[1]);
 
-    /* S = M(S - T) - U */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &S,  &S,     &T      ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S,  &S,     &M      ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &S,  &S,     &U      ) );
+    /* tmp[1] <- S = M(S - T) - U */
+    MPI_ECP_SUB(&tmp[1],  &tmp[1],     &tmp[2]);
+    MPI_ECP_MUL(&tmp[1],  &tmp[1],     &tmp[0]);
+    MPI_ECP_SUB(&tmp[1],  &tmp[1],     &tmp[3]);
 
-    /* U = 2.Y.Z */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &U,  &P->Y,  &P->Z   ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &U,  1               ) );
+    /* tmp[3] <- U = 2.Y.Z */
+    MPI_ECP_MUL(&tmp[3],  &P->Y,  &P->Z);
+    MPI_ECP_SHIFT_L(&tmp[3],  1);
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) );
+    /* Store results */
+    MPI_ECP_MOV(&R->X, &tmp[2]);
+    MPI_ECP_MOV(&R->Y, &tmp[1]);
+    MPI_ECP_MOV(&R->Z, &tmp[3]);
 
 cleanup:
-    mbedtls_mpi_free( &M ); mbedtls_mpi_free( &S ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &U );
 
-    return( ret );
+    return ret;
 #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) */
 }
 
@@ -1588,6 +1578,10 @@
  * The coordinates of Q must be normalized (= affine),
  * but those of P don't need to. R is not normalized.
  *
+ * P,Q,R may alias, but only at the level of EC points: they must be either
+ * equal as pointers, or disjoint (including the coordinate data buffers).
+ * Fine-grained aliasing at the level of coordinates is not supported.
+ *
  * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
  * None of these cases can happen as intermediate step in ecp_mul_comb():
  * - at each step, P, Q and R are multiples of the base point, the factor
@@ -1596,92 +1590,96 @@
  *   due to the choice of precomputed points in the modified comb method.
  * So branches for these cases do not leak secret information.
  *
- * We accept Q->Z being unset (saving memory in tables) as meaning 1.
- *
  * Cost: 1A := 8M + 3S
  */
-static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
-                          const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
+static int ecp_add_mixed(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+                         const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
+                         mbedtls_mpi tmp[4])
 {
 #if defined(MBEDTLS_SELF_TEST)
     add_count++;
 #endif
 
 #if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
-    if( mbedtls_internal_ecp_grp_capable( grp ) )
-        return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) );
+    if (mbedtls_internal_ecp_grp_capable(grp)) {
+        return mbedtls_internal_ecp_add_mixed(grp, R, P, Q);
+    }
 #endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
 
 #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_ADD_MIXED_ALT)
-    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
 #else
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
+
+    /* NOTE: Aliasing between input and output is allowed, so one has to make
+     *       sure that at the point X,Y,Z are written, {P,Q}->{X,Y,Z} are no
+     *       longer read from. */
+    mbedtls_mpi * const X = &R->X;
+    mbedtls_mpi * const Y = &R->Y;
+    mbedtls_mpi * const Z = &R->Z;
+
+    if (!MPI_ECP_VALID(&Q->Z)) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
     /*
      * Trivial cases: P == 0 or Q == 0 (case 1)
      */
-    if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
-        return( mbedtls_ecp_copy( R, Q ) );
+    if (MPI_ECP_CMP_INT(&P->Z, 0) == 0) {
+        return mbedtls_ecp_copy(R, Q);
+    }
 
-    if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 )
-        return( mbedtls_ecp_copy( R, P ) );
+    if (MPI_ECP_CMP_INT(&Q->Z, 0) == 0) {
+        return mbedtls_ecp_copy(R, P);
+    }
 
     /*
      * Make sure Q coordinates are normalized
      */
-    if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (MPI_ECP_CMP_INT(&Q->Z, 1) != 0) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
-    mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
-    mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T1,  &P->Z,  &P->Z ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T2,  &T1,    &P->Z ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T1,  &T1,    &Q->X ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T2,  &T2,    &Q->Y ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T1,  &T1,    &P->X ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T2,  &T2,    &P->Y ) );
+    MPI_ECP_SQR(&tmp[0], &P->Z);
+    MPI_ECP_MUL(&tmp[1], &tmp[0], &P->Z);
+    MPI_ECP_MUL(&tmp[0], &tmp[0], &Q->X);
+    MPI_ECP_MUL(&tmp[1], &tmp[1], &Q->Y);
+    MPI_ECP_SUB(&tmp[0], &tmp[0], &P->X);
+    MPI_ECP_SUB(&tmp[1], &tmp[1], &P->Y);
 
     /* Special cases (2) and (3) */
-    if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
-    {
-        if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 )
-        {
-            ret = ecp_double_jac( grp, R, P );
+    if (MPI_ECP_CMP_INT(&tmp[0], 0) == 0) {
+        if (MPI_ECP_CMP_INT(&tmp[1], 0) == 0) {
+            ret = ecp_double_jac(grp, R, P, tmp);
             goto cleanup;
-        }
-        else
-        {
-            ret = mbedtls_ecp_set_zero( R );
+        } else {
+            ret = mbedtls_ecp_set_zero(R);
             goto cleanup;
         }
     }
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &Z,   &P->Z,  &T1   ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T3,  &T1,    &T1   ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T4,  &T3,    &T1   ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T3,  &T3,    &P->X ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &T3 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &T1,  1     ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &X,   &T2,    &T2   ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &X,   &X,     &T1   ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &X,   &X,     &T4   ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T3,  &T3,    &X    ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T3,  &T3,    &T2   ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T4,  &T4,    &P->Y ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &Y,   &T3,    &T4   ) );
+    /* {P,Q}->Z no longer used, so OK to write to Z even if there's aliasing. */
+    MPI_ECP_MUL(Z,        &P->Z,    &tmp[0]);
+    MPI_ECP_SQR(&tmp[2],  &tmp[0]);
+    MPI_ECP_MUL(&tmp[3],  &tmp[2],  &tmp[0]);
+    MPI_ECP_MUL(&tmp[2],  &tmp[2],  &P->X);
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) );
+    MPI_ECP_MOV(&tmp[0], &tmp[2]);
+    MPI_ECP_SHIFT_L(&tmp[0], 1);
+
+    /* {P,Q}->X no longer used, so OK to write to X even if there's aliasing. */
+    MPI_ECP_SQR(X,        &tmp[1]);
+    MPI_ECP_SUB(X,        X,        &tmp[0]);
+    MPI_ECP_SUB(X,        X,        &tmp[3]);
+    MPI_ECP_SUB(&tmp[2],  &tmp[2],  X);
+    MPI_ECP_MUL(&tmp[2],  &tmp[2],  &tmp[1]);
+    MPI_ECP_MUL(&tmp[3],  &tmp[3],  &P->Y);
+    /* {P,Q}->Y no longer used, so OK to write to Y even if there's aliasing. */
+    MPI_ECP_SUB(Y,     &tmp[2],     &tmp[3]);
 
 cleanup:
 
-    mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 );
-    mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
-
-    return( ret );
+    return ret;
 #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_ADD_MIXED_ALT) */
 }
 
@@ -1692,42 +1690,46 @@
  *
  * This countermeasure was first suggested in [2].
  */
-static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
-                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+static int ecp_randomize_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
+                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
 #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
-    if( mbedtls_internal_ecp_grp_capable( grp ) )
-        return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) );
+    if (mbedtls_internal_ecp_grp_capable(grp)) {
+        return mbedtls_internal_ecp_randomize_jac(grp, pt, f_rng, p_rng);
+    }
 #endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
 
 #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
-    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
 #else
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_mpi l, ll;
+    mbedtls_mpi l;
 
-    mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
+    mbedtls_mpi_init(&l);
 
     /* Generate l such that 1 < l < p */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_random( &l, 2, &grp->P, f_rng, p_rng ) );
+    MPI_ECP_RAND(&l);
 
-    /* Z = l * Z */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Z,   &pt->Z,     &l  ) );
+    /* Z' = l * Z */
+    MPI_ECP_MUL(&pt->Z,   &pt->Z,     &l);
 
-    /* X = l^2 * X */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ll,      &l,         &l  ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->X,   &pt->X,     &ll ) );
+    /* Y' = l * Y */
+    MPI_ECP_MUL(&pt->Y,   &pt->Y,     &l);
 
-    /* Y = l^3 * Y */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ll,      &ll,        &l  ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Y,   &pt->Y,     &ll ) );
+    /* X' = l^2 * X */
+    MPI_ECP_SQR(&l,       &l);
+    MPI_ECP_MUL(&pt->X,   &pt->X,     &l);
+
+    /* Y'' = l^2 * Y' = l^3 * Y */
+    MPI_ECP_MUL(&pt->Y,   &pt->Y,     &l);
 
 cleanup:
-    mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
+    mbedtls_mpi_free(&l);
 
-    if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
+    if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
         ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
-    return( ret );
+    }
+    return ret;
 #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) */
 }
 
@@ -1739,10 +1741,10 @@
 #endif
 
 /* d = ceil( n / w ) */
-#define COMB_MAX_D      ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2
+#define COMB_MAX_D      (MBEDTLS_ECP_MAX_BITS + 1) / 2
 
 /* number of precomputed points */
-#define COMB_MAX_PRE    ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
+#define COMB_MAX_PRE    (1 << (MBEDTLS_ECP_WINDOW_SIZE - 1))
 
 /*
  * Compute the representation of m that will be used with our comb method.
@@ -1791,32 +1793,33 @@
  * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
  *   (the result will be incorrect if these assumptions are not satisfied)
  */
-static void ecp_comb_recode_core( unsigned char x[], size_t d,
-                                  unsigned char w, const mbedtls_mpi *m )
+static void ecp_comb_recode_core(unsigned char x[], size_t d,
+                                 unsigned char w, const mbedtls_mpi *m)
 {
     size_t i, j;
     unsigned char c, cc, adjust;
 
-    memset( x, 0, d+1 );
+    memset(x, 0, d+1);
 
     /* First get the classical comb values (except for x_d = 0) */
-    for( i = 0; i < d; i++ )
-        for( j = 0; j < w; j++ )
-            x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j;
+    for (i = 0; i < d; i++) {
+        for (j = 0; j < w; j++) {
+            x[i] |= mbedtls_mpi_get_bit(m, i + d * j) << j;
+        }
+    }
 
     /* Now make sure x_1 .. x_d are odd */
     c = 0;
-    for( i = 1; i <= d; i++ )
-    {
+    for (i = 1; i <= d; i++) {
         /* Add carry and update it */
         cc   = x[i] & c;
         x[i] = x[i] ^ c;
         c = cc;
 
         /* Adjust if needed, avoiding branches */
-        adjust = 1 - ( x[i] & 0x01 );
-        c   |= x[i] & ( x[i-1] * adjust );
-        x[i] = x[i] ^ ( x[i-1] * adjust );
+        adjust = 1 - (x[i] & 0x01);
+        c   |= x[i] & (x[i-1] * adjust);
+        x[i] = x[i] ^ (x[i-1] * adjust);
         x[i-1] |= adjust << 7;
     }
 }
@@ -1855,36 +1858,42 @@
  * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order
  * to minimize maximum blocking time.
  */
-static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
-                                mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
-                                unsigned char w, size_t d,
-                                mbedtls_ecp_restart_ctx *rs_ctx )
+static int ecp_precompute_comb(const mbedtls_ecp_group *grp,
+                               mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
+                               unsigned char w, size_t d,
+                               mbedtls_ecp_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char i;
     size_t j = 0;
-    const unsigned char T_size = 1U << ( w - 1 );
-    mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
+    const unsigned char T_size = 1U << (w - 1);
+    mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1] = { NULL };
+
+    mbedtls_mpi tmp[4];
+
+    mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi));
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->rsm != NULL )
-    {
-        if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
+    if (rs_ctx != NULL && rs_ctx->rsm != NULL) {
+        if (rs_ctx->rsm->state == ecp_rsm_pre_dbl) {
             goto dbl;
-        if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl )
+        }
+        if (rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl) {
             goto norm_dbl;
-        if( rs_ctx->rsm->state == ecp_rsm_pre_add )
+        }
+        if (rs_ctx->rsm->state == ecp_rsm_pre_add) {
             goto add;
-        if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add )
+        }
+        if (rs_ctx->rsm->state == ecp_rsm_pre_norm_add) {
             goto norm_add;
+        }
     }
 #else
     (void) rs_ctx;
 #endif
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->rsm != NULL )
-    {
+    if (rs_ctx != NULL && rs_ctx->rsm != NULL) {
         rs_ctx->rsm->state = ecp_rsm_pre_dbl;
 
         /* initial state for the loop */
@@ -1897,49 +1906,55 @@
      * Set T[0] = P and
      * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value)
      */
-    MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecp_copy(&T[0], P));
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
+    if (rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0) {
         j = rs_ctx->rsm->i;
-    else
+    } else
 #endif
-        j = 0;
+    j = 0;
 
-    for( ; j < d * ( w - 1 ); j++ )
-    {
-        MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL );
+    for (; j < d * (w - 1); j++) {
+        MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_DBL);
 
-        i = 1U << ( j / d );
+        i = 1U << (j / d);
         cur = T + i;
 
-        if( j % d == 0 )
-            MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
+        if (j % d == 0) {
+            MBEDTLS_MPI_CHK(mbedtls_ecp_copy(cur, T + (i >> 1)));
+        }
 
-        MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
+        MBEDTLS_MPI_CHK(ecp_double_jac(grp, cur, cur, tmp));
     }
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+    if (rs_ctx != NULL && rs_ctx->rsm != NULL) {
         rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl;
+    }
 
 norm_dbl:
 #endif
     /*
-     * Normalize current elements in T. As T has holes,
-     * use an auxiliary array of pointers to elements in T.
+     * Normalize current elements in T to allow them to be used in
+     * ecp_add_mixed() below, which requires one normalized input.
+     *
+     * As T has holes, use an auxiliary array of pointers to elements in T.
+     *
      */
     j = 0;
-    for( i = 1; i < T_size; i <<= 1 )
+    for (i = 1; i < T_size; i <<= 1) {
         TT[j++] = T + i;
+    }
 
-    MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
+    MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_INV + 6 * j - 2);
 
-    MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
+    MBEDTLS_MPI_CHK(ecp_normalize_jac_many(grp, TT, j));
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+    if (rs_ctx != NULL && rs_ctx->rsm != NULL) {
         rs_ctx->rsm->state = ecp_rsm_pre_add;
+    }
 
 add:
 #endif
@@ -1947,18 +1962,19 @@
      * Compute the remaining ones using the minimal number of additions
      * Be careful to update T[2^l] only after using it!
      */
-    MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD );
+    MBEDTLS_ECP_BUDGET((T_size - 1) * MBEDTLS_ECP_OPS_ADD);
 
-    for( i = 1; i < T_size; i <<= 1 )
-    {
+    for (i = 1; i < T_size; i <<= 1) {
         j = i;
-        while( j-- )
-            MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
+        while (j--) {
+            MBEDTLS_MPI_CHK(ecp_add_mixed(grp, &T[i + j], &T[j], &T[i], tmp));
+        }
     }
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+    if (rs_ctx != NULL && rs_ctx->rsm != NULL) {
         rs_ctx->rsm->state = ecp_rsm_pre_norm_add;
+    }
 
 norm_add:
 #endif
@@ -1967,24 +1983,37 @@
      * still need the auxiliary array for homogeneity with the previous
      * call. Also, skip T[0] which is already normalised, being a copy of P.
      */
-    for( j = 0; j + 1 < T_size; j++ )
+    for (j = 0; j + 1 < T_size; j++) {
         TT[j] = T + j + 1;
+    }
 
-    MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
+    MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_INV + 6 * j - 2);
 
-    MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
+    MBEDTLS_MPI_CHK(ecp_normalize_jac_many(grp, TT, j));
+
+    /* Free Z coordinate (=1 after normalization) to save RAM.
+     * This makes T[i] invalid as mbedtls_ecp_points, but this is OK
+     * since from this point onwards, they are only accessed indirectly
+     * via the getter function ecp_select_comb() which does set the
+     * target's Z coordinate to 1. */
+    for (i = 0; i < T_size; i++) {
+        mbedtls_mpi_free(&T[i].Z);
+    }
 
 cleanup:
+
+    mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi));
+
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
-        ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
-    {
-        if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
+    if (rs_ctx != NULL && rs_ctx->rsm != NULL &&
+        ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
+        if (rs_ctx->rsm->state == ecp_rsm_pre_dbl) {
             rs_ctx->rsm->i = j;
+        }
     }
 #endif
 
-    return( ret );
+    return ret;
 }
 
 /*
@@ -1992,28 +2021,29 @@
  *
  * See ecp_comb_recode_core() for background
  */
-static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
-                            const mbedtls_ecp_point T[], unsigned char T_size,
-                            unsigned char i )
+static int ecp_select_comb(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+                           const mbedtls_ecp_point T[], unsigned char T_size,
+                           unsigned char i)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char ii, j;
 
     /* Ignore the "sign" bit and scale down */
-    ii =  ( i & 0x7Fu ) >> 1;
+    ii =  (i & 0x7Fu) >> 1;
 
     /* Read the whole table to thwart cache-based timing attacks */
-    for( j = 0; j < T_size; j++ )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
+    for (j = 0; j < T_size; j++) {
+        MPI_ECP_COND_ASSIGN(&R->X, &T[j].X, j == ii);
+        MPI_ECP_COND_ASSIGN(&R->Y, &T[j].Y, j == ii);
     }
 
     /* Safely invert result if i is "negative" */
-    MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
+    MBEDTLS_MPI_CHK(ecp_safe_invert_jac(grp, R, i >> 7));
+
+    MPI_ECP_LSET(&R->Z, 1);
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
@@ -2022,74 +2052,70 @@
  *
  * Cost: d A + d D + 1 R
  */
-static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
-                              const mbedtls_ecp_point T[], unsigned char T_size,
-                              const unsigned char x[], size_t d,
-                              int (*f_rng)(void *, unsigned char *, size_t),
-                              void *p_rng,
-                              mbedtls_ecp_restart_ctx *rs_ctx )
+static int ecp_mul_comb_core(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+                             const mbedtls_ecp_point T[], unsigned char T_size,
+                             const unsigned char x[], size_t d,
+                             int (*f_rng)(void *, unsigned char *, size_t),
+                             void *p_rng,
+                             mbedtls_ecp_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecp_point Txi;
+    mbedtls_mpi tmp[4];
     size_t i;
 
-    mbedtls_ecp_point_init( &Txi );
+    mbedtls_ecp_point_init(&Txi);
+    mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi));
 
 #if !defined(MBEDTLS_ECP_RESTARTABLE)
     (void) rs_ctx;
 #endif
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
-        rs_ctx->rsm->state != ecp_rsm_comb_core )
-    {
+    if (rs_ctx != NULL && rs_ctx->rsm != NULL &&
+        rs_ctx->rsm->state != ecp_rsm_comb_core) {
         rs_ctx->rsm->i = 0;
         rs_ctx->rsm->state = ecp_rsm_comb_core;
     }
 
     /* new 'if' instead of nested for the sake of the 'else' branch */
-    if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
-    {
+    if (rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0) {
         /* restore current index (R already pointing to rs_ctx->rsm->R) */
         i = rs_ctx->rsm->i;
-    }
-    else
+    } else
 #endif
     {
         /* Start with a non-zero point and randomize its coordinates */
         i = d;
-        MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
-#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
-        if( f_rng != 0 )
-#endif
-            MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
+        MBEDTLS_MPI_CHK(ecp_select_comb(grp, R, T, T_size, x[i]));
+        if (f_rng != 0) {
+            MBEDTLS_MPI_CHK(ecp_randomize_jac(grp, R, f_rng, p_rng));
+        }
     }
 
-    while( i != 0 )
-    {
-        MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD );
+    while (i != 0) {
+        MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD);
         --i;
 
-        MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
-        MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) );
-        MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
+        MBEDTLS_MPI_CHK(ecp_double_jac(grp, R, R, tmp));
+        MBEDTLS_MPI_CHK(ecp_select_comb(grp, &Txi, T, T_size, x[i]));
+        MBEDTLS_MPI_CHK(ecp_add_mixed(grp, R, R, &Txi, tmp));
     }
 
 cleanup:
 
-    mbedtls_ecp_point_free( &Txi );
+    mbedtls_ecp_point_free(&Txi);
+    mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi));
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
-        ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
-    {
+    if (rs_ctx != NULL && rs_ctx->rsm != NULL &&
+        ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
         rs_ctx->rsm->i = i;
         /* no need to save R, already pointing to rs_ctx->rsm->R */
     }
 #endif
 
-    return( ret );
+    return ret;
 }
 
 /*
@@ -2104,39 +2130,40 @@
  *
  * See ecp_comb_recode_core() for background.
  */
-static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp,
-                                   const mbedtls_mpi *m,
-                                   unsigned char k[COMB_MAX_D + 1],
-                                   size_t d,
-                                   unsigned char w,
-                                   unsigned char *parity_trick )
+static int ecp_comb_recode_scalar(const mbedtls_ecp_group *grp,
+                                  const mbedtls_mpi *m,
+                                  unsigned char k[COMB_MAX_D + 1],
+                                  size_t d,
+                                  unsigned char w,
+                                  unsigned char *parity_trick)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_mpi M, mm;
 
-    mbedtls_mpi_init( &M );
-    mbedtls_mpi_init( &mm );
+    mbedtls_mpi_init(&M);
+    mbedtls_mpi_init(&mm);
 
     /* N is always odd (see above), just make extra sure */
-    if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    if (mbedtls_mpi_get_bit(&grp->N, 0) != 1) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
     /* do we need the parity trick? */
-    *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 );
+    *parity_trick = (mbedtls_mpi_get_bit(m, 0) == 0);
 
     /* execute parity fix in constant time */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&M, m));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&mm, &grp->N, m));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(&M, &mm, *parity_trick));
 
     /* actual scalar recoding */
-    ecp_comb_recode_core( k, d, w, &M );
+    ecp_comb_recode_core(k, d, w, &M);
 
 cleanup:
-    mbedtls_mpi_free( &mm );
-    mbedtls_mpi_free( &M );
+    mbedtls_mpi_free(&mm);
+    mbedtls_mpi_free(&M);
 
-    return( ret );
+    return ret;
 }
 
 /*
@@ -2146,16 +2173,16 @@
  * Scalar recoding may use a parity trick that makes us compute -m * P,
  * if that is the case we'll need to recover m * P at the end.
  */
-static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp,
-                                mbedtls_ecp_point *R,
-                                const mbedtls_mpi *m,
-                                const mbedtls_ecp_point *T,
-                                unsigned char T_size,
-                                unsigned char w,
-                                size_t d,
-                                int (*f_rng)(void *, unsigned char *, size_t),
-                                void *p_rng,
-                                mbedtls_ecp_restart_ctx *rs_ctx )
+static int ecp_mul_comb_after_precomp(const mbedtls_ecp_group *grp,
+                                      mbedtls_ecp_point *R,
+                                      const mbedtls_mpi *m,
+                                      const mbedtls_ecp_point *T,
+                                      unsigned char T_size,
+                                      unsigned char w,
+                                      size_t d,
+                                      int (*f_rng)(void *, unsigned char *, size_t),
+                                      void *p_rng,
+                                      mbedtls_ecp_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char parity_trick;
@@ -2163,27 +2190,28 @@
     mbedtls_ecp_point *RR = R;
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->rsm != NULL )
-    {
+    if (rs_ctx != NULL && rs_ctx->rsm != NULL) {
         RR = &rs_ctx->rsm->R;
 
-        if( rs_ctx->rsm->state == ecp_rsm_final_norm )
+        if (rs_ctx->rsm->state == ecp_rsm_final_norm) {
             goto final_norm;
+        }
     }
 #endif
 
-    MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w,
-                                            &parity_trick ) );
-    MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d,
-                                        f_rng, p_rng, rs_ctx ) );
-    MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) );
+    MBEDTLS_MPI_CHK(ecp_comb_recode_scalar(grp, m, k, d, w,
+                                           &parity_trick));
+    MBEDTLS_MPI_CHK(ecp_mul_comb_core(grp, RR, T, T_size, k, d,
+                                      f_rng, p_rng, rs_ctx));
+    MBEDTLS_MPI_CHK(ecp_safe_invert_jac(grp, RR, parity_trick));
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->rsm != NULL )
+    if (rs_ctx != NULL && rs_ctx->rsm != NULL) {
         rs_ctx->rsm->state = ecp_rsm_final_norm;
+    }
 
 final_norm:
-    MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
+    MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_INV);
 #endif
     /*
      * Knowledge of the jacobian coordinates may leak the last few bits of the
@@ -2196,27 +2224,27 @@
      *
      * Avoid the leak by randomizing coordinates before we normalize them.
      */
-#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
-    if( f_rng != 0 )
-#endif
-        MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) );
+    if (f_rng != 0) {
+        MBEDTLS_MPI_CHK(ecp_randomize_jac(grp, RR, f_rng, p_rng));
+    }
 
-    MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) );
+    MBEDTLS_MPI_CHK(ecp_normalize_jac(grp, RR));
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->rsm != NULL )
-        MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) );
+    if (rs_ctx != NULL && rs_ctx->rsm != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, RR));
+    }
 #endif
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
  * Pick window size based on curve size and whether we optimize for base point
  */
-static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp,
-                                           unsigned char p_eq_g )
+static unsigned char ecp_pick_window_size(const mbedtls_ecp_group *grp,
+                                          unsigned char p_eq_g)
 {
     unsigned char w;
 
@@ -2232,21 +2260,29 @@
      * Just adding one avoids upping the cost of the first mul too much,
      * and the memory cost too.
      */
-    if( p_eq_g )
+    if (p_eq_g) {
         w++;
+    }
 
     /*
-     * Make sure w is within bounds.
+     * If static comb table may not be used (!p_eq_g) or static comb table does
+     * not exists, make sure w is within bounds.
      * (The last test is useful only for very small curves in the test suite.)
+     *
+     * The user reduces MBEDTLS_ECP_WINDOW_SIZE does not changes the size of
+     * static comb table, because the size of static comb table is fixed when
+     * it is generated.
      */
-#if( MBEDTLS_ECP_WINDOW_SIZE < 6 )
-    if( w > MBEDTLS_ECP_WINDOW_SIZE )
+#if (MBEDTLS_ECP_WINDOW_SIZE < 6)
+    if ((!p_eq_g || !ecp_group_is_static_comb_table(grp)) && w > MBEDTLS_ECP_WINDOW_SIZE) {
         w = MBEDTLS_ECP_WINDOW_SIZE;
+    }
 #endif
-    if( w >= grp->nbits )
+    if (w >= grp->nbits) {
         w = 2;
+    }
 
-    return( w );
+    return w;
 }
 
 /*
@@ -2262,78 +2298,42 @@
  *
  * See comments on ecp_comb_recode_core() regarding the computation strategy.
  */
-static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
-                         const mbedtls_mpi *m, const mbedtls_ecp_point *P,
-                         int (*f_rng)(void *, unsigned char *, size_t),
-                         void *p_rng,
-                         mbedtls_ecp_restart_ctx *rs_ctx )
+static int ecp_mul_comb(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+                        const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+                        int (*f_rng)(void *, unsigned char *, size_t),
+                        void *p_rng,
+                        mbedtls_ecp_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char w, p_eq_g, i;
     size_t d;
     unsigned char T_size = 0, T_ok = 0;
     mbedtls_ecp_point *T = NULL;
-#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
-    ecp_drbg_context drbg_ctx;
 
-    ecp_drbg_init( &drbg_ctx );
-#endif
-
-    ECP_RS_ENTER( rsm );
-
-#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
-    if( f_rng == NULL )
-    {
-        /* Adjust pointers */
-        f_rng = &ecp_drbg_random;
-#if defined(MBEDTLS_ECP_RESTARTABLE)
-        if( rs_ctx != NULL && rs_ctx->rsm != NULL )
-            p_rng = &rs_ctx->rsm->drbg_ctx;
-        else
-#endif
-            p_rng = &drbg_ctx;
-
-        /* Initialize internal DRBG if necessary */
-#if defined(MBEDTLS_ECP_RESTARTABLE)
-        if( rs_ctx == NULL || rs_ctx->rsm == NULL ||
-            rs_ctx->rsm->drbg_seeded == 0 )
-#endif
-        {
-            const size_t m_len = ( grp->nbits + 7 ) / 8;
-            MBEDTLS_MPI_CHK( ecp_drbg_seed( p_rng, m, m_len ) );
-        }
-#if defined(MBEDTLS_ECP_RESTARTABLE)
-        if( rs_ctx != NULL && rs_ctx->rsm != NULL )
-            rs_ctx->rsm->drbg_seeded = 1;
-#endif
-    }
-#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
+    ECP_RS_ENTER(rsm);
 
     /* Is P the base point ? */
 #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
-    p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
-               mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
+    p_eq_g = (MPI_ECP_CMP(&P->Y, &grp->G.Y) == 0 &&
+              MPI_ECP_CMP(&P->X, &grp->G.X) == 0);
 #else
     p_eq_g = 0;
 #endif
 
     /* Pick window size and deduce related sizes */
-    w = ecp_pick_window_size( grp, p_eq_g );
-    T_size = 1U << ( w - 1 );
-    d = ( grp->nbits + w - 1 ) / w;
+    w = ecp_pick_window_size(grp, p_eq_g);
+    T_size = 1U << (w - 1);
+    d = (grp->nbits + w - 1) / w;
 
     /* Pre-computed table: do we have it already for the base point? */
-    if( p_eq_g && grp->T != NULL )
-    {
+    if (p_eq_g && grp->T != NULL) {
         /* second pointer to the same table, will be deleted on exit */
         T = grp->T;
         T_ok = 1;
-    }
-    else
+    } else
 #if defined(MBEDTLS_ECP_RESTARTABLE)
     /* Pre-computed table: do we have one in progress? complete? */
-    if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL )
-    {
+    if (rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL) {
         /* transfer ownership of T from rsm to local function */
         T = rs_ctx->rsm->T;
         rs_ctx->rsm->T = NULL;
@@ -2341,31 +2341,28 @@
 
         /* This effectively jumps to the call to mul_comb_after_precomp() */
         T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core;
-    }
-    else
+    } else
 #endif
     /* Allocate table if we didn't have any */
     {
-        T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) );
-        if( T == NULL )
-        {
+        T = mbedtls_calloc(T_size, sizeof(mbedtls_ecp_point));
+        if (T == NULL) {
             ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
             goto cleanup;
         }
 
-        for( i = 0; i < T_size; i++ )
-            mbedtls_ecp_point_init( &T[i] );
+        for (i = 0; i < T_size; i++) {
+            mbedtls_ecp_point_init(&T[i]);
+        }
 
         T_ok = 0;
     }
 
     /* Compute table (or finish computing it) if not done already */
-    if( !T_ok )
-    {
-        MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) );
+    if (!T_ok) {
+        MBEDTLS_MPI_CHK(ecp_precompute_comb(grp, T, P, w, d, rs_ctx));
 
-        if( p_eq_g )
-        {
+        if (p_eq_g) {
             /* almost transfer ownership of T to the group, but keep a copy of
              * the pointer to use for calling the next function more easily */
             grp->T = T;
@@ -2374,24 +2371,20 @@
     }
 
     /* Actual comb multiplication using precomputed points */
-    MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m,
-                                                 T, T_size, w, d,
-                                                 f_rng, p_rng, rs_ctx ) );
+    MBEDTLS_MPI_CHK(ecp_mul_comb_after_precomp(grp, R, m,
+                                               T, T_size, w, d,
+                                               f_rng, p_rng, rs_ctx));
 
 cleanup:
 
-#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
-    ecp_drbg_free( &drbg_ctx );
-#endif
-
     /* does T belong to the group? */
-    if( T == grp->T )
+    if (T == grp->T) {
         T = NULL;
+    }
 
     /* does T belong to the restart context? */
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL )
-    {
+    if (rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL) {
         /* transfer ownership of T from local function to rsm */
         rs_ctx->rsm->T_size = T_size;
         rs_ctx->rsm->T = T;
@@ -2400,24 +2393,28 @@
 #endif
 
     /* did T belong to us? then let's destroy it! */
-    if( T != NULL )
-    {
-        for( i = 0; i < T_size; i++ )
-            mbedtls_ecp_point_free( &T[i] );
-        mbedtls_free( T );
+    if (T != NULL) {
+        for (i = 0; i < T_size; i++) {
+            mbedtls_ecp_point_free(&T[i]);
+        }
+        mbedtls_free(T);
     }
 
-    /* don't free R while in progress in case R == P */
-#if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
-#endif
     /* prevent caller from using invalid value */
-    if( ret != 0 )
-        mbedtls_ecp_point_free( R );
+    int should_free_R = (ret != 0);
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    /* don't free R while in progress in case R == P */
+    if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
+        should_free_R = 0;
+    }
+#endif
+    if (should_free_R) {
+        mbedtls_ecp_point_free(R);
+    }
 
-    ECP_RS_LEAVE( rsm );
+    ECP_RS_LEAVE(rsm);
 
-    return( ret );
+    return ret;
 }
 
 #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
@@ -2435,23 +2432,24 @@
  * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
  * Cost: 1M + 1I
  */
-static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
+static int ecp_normalize_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P)
 {
 #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
-    if( mbedtls_internal_ecp_grp_capable( grp ) )
-        return( mbedtls_internal_ecp_normalize_mxz( grp, P ) );
+    if (mbedtls_internal_ecp_grp_capable(grp)) {
+        return mbedtls_internal_ecp_normalize_mxz(grp, P);
+    }
 #endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
 
 #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
-    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
 #else
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->X, &P->X, &P->Z ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
+    MPI_ECP_INV(&P->Z, &P->Z);
+    MPI_ECP_MUL(&P->X, &P->X, &P->Z);
+    MPI_ECP_LSET(&P->Z, 1);
 
 cleanup:
-    return( ret );
+    return ret;
 #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) */
 }
 
@@ -2463,33 +2461,35 @@
  * This countermeasure was first suggested in [2].
  * Cost: 2M
  */
-static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
-                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+static int ecp_randomize_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
+                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
 #if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
-    if( mbedtls_internal_ecp_grp_capable( grp ) )
-        return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ) );
+    if (mbedtls_internal_ecp_grp_capable(grp)) {
+        return mbedtls_internal_ecp_randomize_mxz(grp, P, f_rng, p_rng);
+    }
 #endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
 
 #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
-    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
 #else
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_mpi l;
-    mbedtls_mpi_init( &l );
+    mbedtls_mpi_init(&l);
 
     /* Generate l such that 1 < l < p */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_random( &l, 2, &grp->P, f_rng, p_rng ) );
+    MPI_ECP_RAND(&l);
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->X, &P->X, &l ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->Z, &P->Z, &l ) );
+    MPI_ECP_MUL(&P->X, &P->X, &l);
+    MPI_ECP_MUL(&P->Z, &P->Z, &l);
 
 cleanup:
-    mbedtls_mpi_free( &l );
+    mbedtls_mpi_free(&l);
 
-    if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
+    if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
         ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
-    return( ret );
+    }
+    return ret;
 #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) */
 }
 
@@ -2508,51 +2508,45 @@
  *
  * Cost: 5M + 4S
  */
-static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
-                               mbedtls_ecp_point *R, mbedtls_ecp_point *S,
-                               const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
-                               const mbedtls_mpi *d )
+static int ecp_double_add_mxz(const mbedtls_ecp_group *grp,
+                              mbedtls_ecp_point *R, mbedtls_ecp_point *S,
+                              const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
+                              const mbedtls_mpi *d,
+                              mbedtls_mpi T[4])
 {
 #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
-    if( mbedtls_internal_ecp_grp_capable( grp ) )
-        return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) );
+    if (mbedtls_internal_ecp_grp_capable(grp)) {
+        return mbedtls_internal_ecp_double_add_mxz(grp, R, S, P, Q, d);
+    }
 #endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
 
 #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
-    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
 #else
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
 
-    mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
-    mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
-    mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &A,    &P->X,   &P->Z ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &AA,   &A,      &A    ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &B,    &P->X,   &P->Z ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &BB,   &B,      &B    ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &E,    &AA,     &BB   ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &C,    &Q->X,   &Q->Z ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &D,    &Q->X,   &Q->Z ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &DA,   &D,      &A    ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &CB,   &C,      &B    ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &S->X, &DA,     &CB   ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S->X, &S->X,   &S->X ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &S->Z, &DA,     &CB   ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S->Z, &S->Z,   &S->Z ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S->Z, d,       &S->Z ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &R->X, &AA,     &BB   ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &R->Z, &grp->A, &E    ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &R->Z, &BB,     &R->Z ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &R->Z, &E,      &R->Z ) );
+    MPI_ECP_ADD(&T[0], &P->X,   &P->Z);   /* Pp := PX + PZ                    */
+    MPI_ECP_SUB(&T[1], &P->X,   &P->Z);   /* Pm := PX - PZ                    */
+    MPI_ECP_ADD(&T[2], &Q->X,   &Q->Z);   /* Qp := QX + XZ                    */
+    MPI_ECP_SUB(&T[3], &Q->X,   &Q->Z);   /* Qm := QX - QZ                    */
+    MPI_ECP_MUL(&T[3], &T[3],   &T[0]);   /* Qm * Pp                          */
+    MPI_ECP_MUL(&T[2], &T[2],   &T[1]);   /* Qp * Pm                          */
+    MPI_ECP_SQR(&T[0], &T[0]);            /* Pp^2                             */
+    MPI_ECP_SQR(&T[1], &T[1]);            /* Pm^2                             */
+    MPI_ECP_MUL(&R->X, &T[0],   &T[1]);   /* Pp^2 * Pm^2                      */
+    MPI_ECP_SUB(&T[0], &T[0],   &T[1]);   /* Pp^2 - Pm^2                      */
+    MPI_ECP_MUL(&R->Z, &grp->A, &T[0]);   /* A * (Pp^2 - Pm^2)                */
+    MPI_ECP_ADD(&R->Z, &T[1],   &R->Z);   /* [ A * (Pp^2-Pm^2) ] + Pm^2       */
+    MPI_ECP_ADD(&S->X, &T[3],   &T[2]);   /* Qm*Pp + Qp*Pm                    */
+    MPI_ECP_SQR(&S->X, &S->X);            /* (Qm*Pp + Qp*Pm)^2                */
+    MPI_ECP_SUB(&S->Z, &T[3],   &T[2]);   /* Qm*Pp - Qp*Pm                    */
+    MPI_ECP_SQR(&S->Z, &S->Z);            /* (Qm*Pp - Qp*Pm)^2                */
+    MPI_ECP_MUL(&S->Z, d,       &S->Z);   /* d * ( Qm*Pp - Qp*Pm )^2          */
+    MPI_ECP_MUL(&R->Z, &T[0],   &R->Z);   /* [A*(Pp^2-Pm^2)+Pm^2]*(Pp^2-Pm^2) */
 
 cleanup:
-    mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
-    mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C );
-    mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
 
-    return( ret );
+    return ret;
 #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) */
 }
 
@@ -2560,56 +2554,44 @@
  * Multiplication with Montgomery ladder in x/z coordinates,
  * for curves in Montgomery form
  */
-static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
-                        const mbedtls_mpi *m, const mbedtls_ecp_point *P,
-                        int (*f_rng)(void *, unsigned char *, size_t),
-                        void *p_rng )
+static int ecp_mul_mxz(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+                       const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i;
     unsigned char b;
     mbedtls_ecp_point RP;
     mbedtls_mpi PX;
-#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
-    ecp_drbg_context drbg_ctx;
+    mbedtls_mpi tmp[4];
+    mbedtls_ecp_point_init(&RP); mbedtls_mpi_init(&PX);
 
-    ecp_drbg_init( &drbg_ctx );
-#endif
-    mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
+    mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi));
 
-#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
-    if( f_rng == NULL )
-    {
-        const size_t m_len = ( grp->nbits + 7 ) / 8;
-        MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) );
-        f_rng = &ecp_drbg_random;
-        p_rng = &drbg_ctx;
+    if (f_rng == NULL) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
     }
-#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
 
     /* Save PX and read from P before writing to R, in case P == R */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
-    MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
+    MPI_ECP_MOV(&PX, &P->X);
+    MBEDTLS_MPI_CHK(mbedtls_ecp_copy(&RP, P));
 
     /* Set R to zero in modified x/z coordinates */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
-    mbedtls_mpi_free( &R->Y );
+    MPI_ECP_LSET(&R->X, 1);
+    MPI_ECP_LSET(&R->Z, 0);
+    mbedtls_mpi_free(&R->Y);
 
     /* RP.X might be slightly larger than P, so reduce it */
-    MOD_ADD( RP.X );
+    MOD_ADD(&RP.X);
 
     /* Randomize coordinates of the starting point */
-#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
-    if( f_rng != NULL )
-#endif
-        MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
+    MBEDTLS_MPI_CHK(ecp_randomize_mxz(grp, &RP, f_rng, p_rng));
 
     /* Loop invariant: R = result so far, RP = R + P */
-    i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
-    while( i-- > 0 )
-    {
-        b = mbedtls_mpi_get_bit( m, i );
+    i = grp->nbits + 1; /* one past the (zero-based) required msb for private keys */
+    while (i-- > 0) {
+        b = mbedtls_mpi_get_bit(m, i);
         /*
          *  if (b) R = 2R + P else R = 2R,
          * which is:
@@ -2617,11 +2599,11 @@
          *  else   double_add( R, RP, R, RP )
          * but using safe conditional swaps to avoid leaks
          */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
-        MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
+        MPI_ECP_COND_SWAP(&R->X, &RP.X, b);
+        MPI_ECP_COND_SWAP(&R->Z, &RP.Z, b);
+        MBEDTLS_MPI_CHK(ecp_double_add_mxz(grp, R, &RP, R, &RP, &PX, tmp));
+        MPI_ECP_COND_SWAP(&R->X, &RP.X, b);
+        MPI_ECP_COND_SWAP(&R->Z, &RP.Z, b);
     }
 
     /*
@@ -2635,105 +2617,115 @@
      *
      * Avoid the leak by randomizing coordinates before we normalize them.
      */
-#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
-    if( f_rng != NULL )
-#endif
-        MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
-
-    MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
+    MBEDTLS_MPI_CHK(ecp_randomize_mxz(grp, R, f_rng, p_rng));
+    MBEDTLS_MPI_CHK(ecp_normalize_mxz(grp, R));
 
 cleanup:
-#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
-    ecp_drbg_free( &drbg_ctx );
-#endif
+    mbedtls_ecp_point_free(&RP); mbedtls_mpi_free(&PX);
 
-    mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
-
-    return( ret );
+    mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi));
+    return ret;
 }
 
 #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
 
 /*
  * Restartable multiplication R = m * P
+ *
+ * This internal function can be called without an RNG in case where we know
+ * the inputs are not sensitive.
  */
-int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
-             const mbedtls_mpi *m, const mbedtls_ecp_point *P,
-             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
-             mbedtls_ecp_restart_ctx *rs_ctx )
+static int ecp_mul_restartable_internal(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+                                        const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+                                        int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                                        mbedtls_ecp_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
 #if defined(MBEDTLS_ECP_INTERNAL_ALT)
     char is_grp_capable = 0;
 #endif
-    ECP_VALIDATE_RET( grp != NULL );
-    ECP_VALIDATE_RET( R   != NULL );
-    ECP_VALIDATE_RET( m   != NULL );
-    ECP_VALIDATE_RET( P   != NULL );
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
     /* reset ops count for this call if top-level */
-    if( rs_ctx != NULL && rs_ctx->depth++ == 0 )
+    if (rs_ctx != NULL && rs_ctx->depth++ == 0) {
         rs_ctx->ops_done = 0;
+    }
 #else
     (void) rs_ctx;
 #endif
 
 #if defined(MBEDTLS_ECP_INTERNAL_ALT)
-    if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
-        MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
+    if ((is_grp_capable = mbedtls_internal_ecp_grp_capable(grp))) {
+        MBEDTLS_MPI_CHK(mbedtls_internal_ecp_init(grp));
+    }
 #endif /* MBEDTLS_ECP_INTERNAL_ALT */
 
+    int restarting = 0;
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    /* skip argument check when restarting */
-    if( rs_ctx == NULL || rs_ctx->rsm == NULL )
+    restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL);
 #endif
-    {
+    /* skip argument check when restarting */
+    if (!restarting) {
         /* check_privkey is free */
-        MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK );
+        MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_CHK);
 
         /* Common sanity checks */
-        MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) );
-        MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
+        MBEDTLS_MPI_CHK(mbedtls_ecp_check_privkey(grp, m));
+        MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P));
     }
 
     ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
 #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
-    if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
-        MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) );
+    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
+        MBEDTLS_MPI_CHK(ecp_mul_mxz(grp, R, m, P, f_rng, p_rng));
+    }
 #endif
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
-    if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
-        MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) );
+    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
+        MBEDTLS_MPI_CHK(ecp_mul_comb(grp, R, m, P, f_rng, p_rng, rs_ctx));
+    }
 #endif
 
 cleanup:
 
 #if defined(MBEDTLS_ECP_INTERNAL_ALT)
-    if( is_grp_capable )
-        mbedtls_internal_ecp_free( grp );
+    if (is_grp_capable) {
+        mbedtls_internal_ecp_free(grp);
+    }
 #endif /* MBEDTLS_ECP_INTERNAL_ALT */
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL )
+    if (rs_ctx != NULL) {
         rs_ctx->depth--;
+    }
 #endif
 
-    return( ret );
+    return ret;
+}
+
+/*
+ * Restartable multiplication R = m * P
+ */
+int mbedtls_ecp_mul_restartable(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+                                const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+                                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                                mbedtls_ecp_restart_ctx *rs_ctx)
+{
+    if (f_rng == NULL) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    return ecp_mul_restartable_internal(grp, R, m, P, f_rng, p_rng, rs_ctx);
 }
 
 /*
  * Multiplication R = m * P
  */
-int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
-             const mbedtls_mpi *m, const mbedtls_ecp_point *P,
-             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+int mbedtls_ecp_mul(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+                    const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
-    ECP_VALIDATE_RET( grp != NULL );
-    ECP_VALIDATE_RET( R   != NULL );
-    ECP_VALIDATE_RET( m   != NULL );
-    ECP_VALIDATE_RET( P   != NULL );
-    return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) );
+    return mbedtls_ecp_mul_restartable(grp, R, m, P, f_rng, p_rng, NULL);
 }
 
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
@@ -2741,48 +2733,37 @@
  * Check that an affine point is valid as a public key,
  * short weierstrass curves (SEC1 3.2.3.1)
  */
-static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
+static int ecp_check_pubkey_sw(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_mpi YY, RHS;
 
     /* pt coordinates must be normalized for our checks */
-    if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ||
-        mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
-        mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
-        mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
-        return( MBEDTLS_ERR_ECP_INVALID_KEY );
+    if (mbedtls_mpi_cmp_int(&pt->X, 0) < 0 ||
+        mbedtls_mpi_cmp_int(&pt->Y, 0) < 0 ||
+        mbedtls_mpi_cmp_mpi(&pt->X, &grp->P) >= 0 ||
+        mbedtls_mpi_cmp_mpi(&pt->Y, &grp->P) >= 0) {
+        return MBEDTLS_ERR_ECP_INVALID_KEY;
+    }
 
-    mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS );
+    mbedtls_mpi_init(&YY); mbedtls_mpi_init(&RHS);
 
     /*
      * YY = Y^2
-     * RHS = X (X^2 + A) + B = X^3 + A X + B
+     * RHS = X^3 + A X + B
      */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &YY,  &pt->Y,   &pt->Y  ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &RHS, &pt->X,   &pt->X  ) );
+    MPI_ECP_SQR(&YY,  &pt->Y);
+    MBEDTLS_MPI_CHK(ecp_sw_rhs(grp, &RHS, &pt->X));
 
-    /* Special case for A = -3 */
-    if( grp->A.p == NULL )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3       ) );  MOD_SUB( RHS );
-    }
-    else
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &RHS, &RHS, &grp->A ) );
-    }
-
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &RHS, &RHS,     &pt->X  ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &RHS, &RHS,     &grp->B ) );
-
-    if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
+    if (MPI_ECP_CMP(&YY, &RHS) != 0) {
         ret = MBEDTLS_ERR_ECP_INVALID_KEY;
+    }
 
 cleanup:
 
-    mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS );
+    mbedtls_mpi_free(&YY); mbedtls_mpi_free(&RHS);
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
 
@@ -2791,36 +2772,35 @@
  * R = m * P with shortcuts for m == 0, m == 1 and m == -1
  * NOT constant-time - ONLY for short Weierstrass!
  */
-static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
-                                      mbedtls_ecp_point *R,
-                                      const mbedtls_mpi *m,
-                                      const mbedtls_ecp_point *P,
-                                      mbedtls_ecp_restart_ctx *rs_ctx )
+static int mbedtls_ecp_mul_shortcuts(mbedtls_ecp_group *grp,
+                                     mbedtls_ecp_point *R,
+                                     const mbedtls_mpi *m,
+                                     const mbedtls_ecp_point *P,
+                                     mbedtls_ecp_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_mpi tmp;
+    mbedtls_mpi_init(&tmp);
 
-    if( mbedtls_mpi_cmp_int( m, 0 ) == 0 )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_ecp_set_zero( R ) );
-    }
-    else if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
-    }
-    else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
-        if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
-            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
-    }
-    else
-    {
-        MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P,
-                                                      NULL, NULL, rs_ctx ) );
+    if (mbedtls_mpi_cmp_int(m, 0) == 0) {
+        MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P));
+        MBEDTLS_MPI_CHK(mbedtls_ecp_set_zero(R));
+    } else if (mbedtls_mpi_cmp_int(m, 1) == 0) {
+        MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P));
+        MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P));
+    } else if (mbedtls_mpi_cmp_int(m, -1) == 0) {
+        MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P));
+        MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P));
+        MPI_ECP_NEG(&R->Y);
+    } else {
+        MBEDTLS_MPI_CHK(ecp_mul_restartable_internal(grp, R, m, P,
+                                                     NULL, NULL, rs_ctx));
     }
 
 cleanup:
-    return( ret );
+    mbedtls_mpi_free(&tmp);
+
+    return ret;
 }
 
 /*
@@ -2828,119 +2808,120 @@
  * NOT constant-time
  */
 int mbedtls_ecp_muladd_restartable(
-             mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
-             const mbedtls_mpi *m, const mbedtls_ecp_point *P,
-             const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
-             mbedtls_ecp_restart_ctx *rs_ctx )
+    mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+    const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+    const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
+    mbedtls_ecp_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecp_point mP;
     mbedtls_ecp_point *pmP = &mP;
     mbedtls_ecp_point *pR = R;
+    mbedtls_mpi tmp[4];
 #if defined(MBEDTLS_ECP_INTERNAL_ALT)
     char is_grp_capable = 0;
 #endif
-    ECP_VALIDATE_RET( grp != NULL );
-    ECP_VALIDATE_RET( R   != NULL );
-    ECP_VALIDATE_RET( m   != NULL );
-    ECP_VALIDATE_RET( P   != NULL );
-    ECP_VALIDATE_RET( n   != NULL );
-    ECP_VALIDATE_RET( Q   != NULL );
+    if (mbedtls_ecp_get_type(grp) != MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
+        return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+    }
 
-    if( mbedtls_ecp_get_type( grp ) != MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
-        return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+    mbedtls_ecp_point_init(&mP);
+    mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi));
 
-    mbedtls_ecp_point_init( &mP );
-
-    ECP_RS_ENTER( ma );
+    ECP_RS_ENTER(ma);
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->ma != NULL )
-    {
+    if (rs_ctx != NULL && rs_ctx->ma != NULL) {
         /* redirect intermediate results to restart context */
         pmP = &rs_ctx->ma->mP;
         pR  = &rs_ctx->ma->R;
 
         /* jump to next operation */
-        if( rs_ctx->ma->state == ecp_rsma_mul2 )
+        if (rs_ctx->ma->state == ecp_rsma_mul2) {
             goto mul2;
-        if( rs_ctx->ma->state == ecp_rsma_add )
+        }
+        if (rs_ctx->ma->state == ecp_rsma_add) {
             goto add;
-        if( rs_ctx->ma->state == ecp_rsma_norm )
+        }
+        if (rs_ctx->ma->state == ecp_rsma_norm) {
             goto norm;
+        }
     }
 #endif /* MBEDTLS_ECP_RESTARTABLE */
 
-    MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecp_mul_shortcuts(grp, pmP, m, P, rs_ctx));
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->ma != NULL )
+    if (rs_ctx != NULL && rs_ctx->ma != NULL) {
         rs_ctx->ma->state = ecp_rsma_mul2;
+    }
 
 mul2:
 #endif
-    MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR,  n, Q, rs_ctx ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecp_mul_shortcuts(grp, pR,  n, Q, rs_ctx));
 
 #if defined(MBEDTLS_ECP_INTERNAL_ALT)
-    if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
-        MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
+    if ((is_grp_capable = mbedtls_internal_ecp_grp_capable(grp))) {
+        MBEDTLS_MPI_CHK(mbedtls_internal_ecp_init(grp));
+    }
 #endif /* MBEDTLS_ECP_INTERNAL_ALT */
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->ma != NULL )
+    if (rs_ctx != NULL && rs_ctx->ma != NULL) {
         rs_ctx->ma->state = ecp_rsma_add;
+    }
 
 add:
 #endif
-    MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD );
-    MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) );
+    MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_ADD);
+    MBEDTLS_MPI_CHK(ecp_add_mixed(grp, pR, pmP, pR, tmp));
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->ma != NULL )
+    if (rs_ctx != NULL && rs_ctx->ma != NULL) {
         rs_ctx->ma->state = ecp_rsma_norm;
+    }
 
 norm:
 #endif
-    MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
-    MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) );
+    MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_INV);
+    MBEDTLS_MPI_CHK(ecp_normalize_jac(grp, pR));
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && rs_ctx->ma != NULL )
-        MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) );
+    if (rs_ctx != NULL && rs_ctx->ma != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, pR));
+    }
 #endif
 
 cleanup:
+
+    mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi));
+
 #if defined(MBEDTLS_ECP_INTERNAL_ALT)
-    if( is_grp_capable )
-        mbedtls_internal_ecp_free( grp );
+    if (is_grp_capable) {
+        mbedtls_internal_ecp_free(grp);
+    }
 #endif /* MBEDTLS_ECP_INTERNAL_ALT */
 
-    mbedtls_ecp_point_free( &mP );
+    mbedtls_ecp_point_free(&mP);
 
-    ECP_RS_LEAVE( ma );
+    ECP_RS_LEAVE(ma);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Linear combination
  * NOT constant-time
  */
-int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
-             const mbedtls_mpi *m, const mbedtls_ecp_point *P,
-             const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
+int mbedtls_ecp_muladd(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
+                       const mbedtls_mpi *m, const mbedtls_ecp_point *P,
+                       const mbedtls_mpi *n, const mbedtls_ecp_point *Q)
 {
-    ECP_VALIDATE_RET( grp != NULL );
-    ECP_VALIDATE_RET( R   != NULL );
-    ECP_VALIDATE_RET( m   != NULL );
-    ECP_VALIDATE_RET( P   != NULL );
-    ECP_VALIDATE_RET( n   != NULL );
-    ECP_VALIDATE_RET( Q   != NULL );
-    return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) );
+    return mbedtls_ecp_muladd_restartable(grp, R, m, P, n, Q, NULL);
 }
 #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
 
 #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
 #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
-#define ECP_MPI_INIT(s, n, p) {s, 0, (n), (mbedtls_mpi_uint *)(p)}
+#define ECP_MPI_INIT(s, n, p) {s, (n), (mbedtls_mpi_uint *)(p), 0}
 #define ECP_MPI_INIT_ARRAY(x)   \
     ECP_MPI_INIT(1, sizeof(x) / sizeof(mbedtls_mpi_uint), x)
 /*
@@ -2949,21 +2930,21 @@
  * See ecp_check_pubkey_x25519().
  */
 static const mbedtls_mpi_uint x25519_bad_point_1[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00 ),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00),
 };
 static const mbedtls_mpi_uint x25519_bad_point_2[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57 ),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57),
 };
 static const mbedtls_mpi ecp_x25519_bad_point_1 = ECP_MPI_INIT_ARRAY(
-        x25519_bad_point_1 );
+    x25519_bad_point_1);
 static const mbedtls_mpi ecp_x25519_bad_point_2 = ECP_MPI_INIT_ARRAY(
-        x25519_bad_point_2 );
+    x25519_bad_point_2);
 #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
 
 /*
@@ -2972,40 +2953,37 @@
  * https://eprint.iacr.org/2017/806.pdf
  * Those points are never sent by an honest peer.
  */
-static int ecp_check_bad_points_mx( const mbedtls_mpi *X, const mbedtls_mpi *P,
-                                    const mbedtls_ecp_group_id grp_id )
+static int ecp_check_bad_points_mx(const mbedtls_mpi *X, const mbedtls_mpi *P,
+                                   const mbedtls_ecp_group_id grp_id)
 {
     int ret;
     mbedtls_mpi XmP;
 
-    mbedtls_mpi_init( &XmP );
+    mbedtls_mpi_init(&XmP);
 
     /* Reduce X mod P so that we only need to check values less than P.
      * We know X < 2^256 so we can proceed by subtraction. */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &XmP, X ) );
-    while( mbedtls_mpi_cmp_mpi( &XmP, P ) >= 0 )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &XmP, &XmP, P ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&XmP, X));
+    while (mbedtls_mpi_cmp_mpi(&XmP, P) >= 0) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&XmP, &XmP, P));
+    }
 
     /* Check against the known bad values that are less than P. For Curve448
      * these are 0, 1 and -1. For Curve25519 we check the values less than P
      * from the following list: https://cr.yp.to/ecdh.html#validate */
-    if( mbedtls_mpi_cmp_int( &XmP, 1 ) <= 0 ) /* takes care of 0 and 1 */
-    {
+    if (mbedtls_mpi_cmp_int(&XmP, 1) <= 0) {  /* takes care of 0 and 1 */
         ret = MBEDTLS_ERR_ECP_INVALID_KEY;
         goto cleanup;
     }
 
 #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
-    if( grp_id == MBEDTLS_ECP_DP_CURVE25519 )
-    {
-        if( mbedtls_mpi_cmp_mpi( &XmP, &ecp_x25519_bad_point_1 ) == 0 )
-        {
+    if (grp_id == MBEDTLS_ECP_DP_CURVE25519) {
+        if (mbedtls_mpi_cmp_mpi(&XmP, &ecp_x25519_bad_point_1) == 0) {
             ret = MBEDTLS_ERR_ECP_INVALID_KEY;
             goto cleanup;
         }
 
-        if( mbedtls_mpi_cmp_mpi( &XmP, &ecp_x25519_bad_point_2 ) == 0 )
-        {
+        if (mbedtls_mpi_cmp_mpi(&XmP, &ecp_x25519_bad_point_2) == 0) {
             ret = MBEDTLS_ERR_ECP_INVALID_KEY;
             goto cleanup;
         }
@@ -3015,9 +2993,8 @@
 #endif
 
     /* Final check: check if XmP + 1 is P (final because it changes XmP!) */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &XmP, &XmP, 1 ) );
-    if( mbedtls_mpi_cmp_mpi( &XmP, P ) == 0 )
-    {
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&XmP, &XmP, 1));
+    if (mbedtls_mpi_cmp_mpi(&XmP, P) == 0) {
         ret = MBEDTLS_ERR_ECP_INVALID_KEY;
         goto cleanup;
     }
@@ -3025,102 +3002,102 @@
     ret = 0;
 
 cleanup:
-    mbedtls_mpi_free( &XmP );
+    mbedtls_mpi_free(&XmP);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Check validity of a public key for Montgomery curves with x-only schemes
  */
-static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
+static int ecp_check_pubkey_mx(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt)
 {
     /* [Curve25519 p. 5] Just check X is the correct number of bytes */
     /* Allow any public value, if it's too big then we'll just reduce it mod p
      * (RFC 7748 sec. 5 para. 3). */
-    if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
-        return( MBEDTLS_ERR_ECP_INVALID_KEY );
+    if (mbedtls_mpi_size(&pt->X) > (grp->nbits + 7) / 8) {
+        return MBEDTLS_ERR_ECP_INVALID_KEY;
+    }
 
     /* Implicit in all standards (as they don't consider negative numbers):
      * X must be non-negative. This is normally ensured by the way it's
      * encoded for transmission, but let's be extra sure. */
-    if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 )
-        return( MBEDTLS_ERR_ECP_INVALID_KEY );
+    if (mbedtls_mpi_cmp_int(&pt->X, 0) < 0) {
+        return MBEDTLS_ERR_ECP_INVALID_KEY;
+    }
 
-    return( ecp_check_bad_points_mx( &pt->X, &grp->P, grp->id ) );
+    return ecp_check_bad_points_mx(&pt->X, &grp->P, grp->id);
 }
 #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
 
 /*
  * Check that a point is valid as a public key
  */
-int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp,
-                              const mbedtls_ecp_point *pt )
+int mbedtls_ecp_check_pubkey(const mbedtls_ecp_group *grp,
+                             const mbedtls_ecp_point *pt)
 {
-    ECP_VALIDATE_RET( grp != NULL );
-    ECP_VALIDATE_RET( pt  != NULL );
-
     /* Must use affine coordinates */
-    if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
-        return( MBEDTLS_ERR_ECP_INVALID_KEY );
+    if (mbedtls_mpi_cmp_int(&pt->Z, 1) != 0) {
+        return MBEDTLS_ERR_ECP_INVALID_KEY;
+    }
 
 #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
-    if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
-        return( ecp_check_pubkey_mx( grp, pt ) );
+    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
+        return ecp_check_pubkey_mx(grp, pt);
+    }
 #endif
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
-    if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
-        return( ecp_check_pubkey_sw( grp, pt ) );
+    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
+        return ecp_check_pubkey_sw(grp, pt);
+    }
 #endif
-    return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
 }
 
 /*
  * Check that an mbedtls_mpi is valid as a private key
  */
-int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp,
-                               const mbedtls_mpi *d )
+int mbedtls_ecp_check_privkey(const mbedtls_ecp_group *grp,
+                              const mbedtls_mpi *d)
 {
-    ECP_VALIDATE_RET( grp != NULL );
-    ECP_VALIDATE_RET( d   != NULL );
-
 #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
-    if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
-    {
+    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
         /* see RFC 7748 sec. 5 para. 5 */
-        if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
-            mbedtls_mpi_get_bit( d, 1 ) != 0 ||
-            mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
-            return( MBEDTLS_ERR_ECP_INVALID_KEY );
+        if (mbedtls_mpi_get_bit(d, 0) != 0 ||
+            mbedtls_mpi_get_bit(d, 1) != 0 ||
+            mbedtls_mpi_bitlen(d) - 1 != grp->nbits) {  /* mbedtls_mpi_bitlen is one-based! */
+            return MBEDTLS_ERR_ECP_INVALID_KEY;
+        }
 
         /* see [Curve25519] page 5 */
-        if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 )
-            return( MBEDTLS_ERR_ECP_INVALID_KEY );
+        if (grp->nbits == 254 && mbedtls_mpi_get_bit(d, 2) != 0) {
+            return MBEDTLS_ERR_ECP_INVALID_KEY;
+        }
 
-        return( 0 );
+        return 0;
     }
 #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
-    if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
-    {
+    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
         /* see SEC1 3.2 */
-        if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
-            mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
-            return( MBEDTLS_ERR_ECP_INVALID_KEY );
-        else
-            return( 0 );
+        if (mbedtls_mpi_cmp_int(d, 1) < 0 ||
+            mbedtls_mpi_cmp_mpi(d, &grp->N) >= 0) {
+            return MBEDTLS_ERR_ECP_INVALID_KEY;
+        } else {
+            return 0;
+        }
     }
 #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
 
-    return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
 }
 
 #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
 MBEDTLS_STATIC_TESTABLE
-int mbedtls_ecp_gen_privkey_mx( size_t high_bit,
-                                mbedtls_mpi *d,
-                                int (*f_rng)(void *, unsigned char *, size_t),
-                                void *p_rng )
+int mbedtls_ecp_gen_privkey_mx(size_t high_bit,
+                               mbedtls_mpi *d,
+                               int (*f_rng)(void *, unsigned char *, size_t),
+                               void *p_rng)
 {
     int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
     size_t n_random_bytes = high_bit / 8 + 1;
@@ -3129,38 +3106,36 @@
     /* Generate a (high_bit+1)-bit random number by generating just enough
      * random bytes, then shifting out extra bits from the top (necessary
      * when (high_bit+1) is not a multiple of 8). */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_random_bytes,
-                                              f_rng, p_rng ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_random_bytes - high_bit - 1 ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(d, n_random_bytes,
+                                            f_rng, p_rng));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(d, 8 * n_random_bytes - high_bit - 1));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, high_bit, 1 ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(d, high_bit, 1));
 
     /* Make sure the last two bits are unset for Curve448, three bits for
        Curve25519 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
-    if( high_bit == 254 )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(d, 0, 0));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(d, 1, 0));
+    if (high_bit == 254) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(d, 2, 0));
     }
 
 cleanup:
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
 
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
 static int mbedtls_ecp_gen_privkey_sw(
     const mbedtls_mpi *N, mbedtls_mpi *d,
-    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
-    int ret = mbedtls_mpi_random( d, 1, N, f_rng, p_rng );
-    switch( ret )
-    {
+    int ret = mbedtls_mpi_random(d, 1, N, f_rng, p_rng);
+    switch (ret) {
         case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE:
-            return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
+            return MBEDTLS_ERR_ECP_RANDOM_FAILED;
         default:
-            return( ret );
+            return ret;
     }
 }
 #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
@@ -3168,260 +3143,293 @@
 /*
  * Generate a private key
  */
-int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
-                     mbedtls_mpi *d,
-                     int (*f_rng)(void *, unsigned char *, size_t),
-                     void *p_rng )
+int mbedtls_ecp_gen_privkey(const mbedtls_ecp_group *grp,
+                            mbedtls_mpi *d,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng)
 {
-    ECP_VALIDATE_RET( grp   != NULL );
-    ECP_VALIDATE_RET( d     != NULL );
-    ECP_VALIDATE_RET( f_rng != NULL );
-
 #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
-    if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
-        return( mbedtls_ecp_gen_privkey_mx( grp->nbits, d, f_rng, p_rng ) );
+    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
+        return mbedtls_ecp_gen_privkey_mx(grp->nbits, d, f_rng, p_rng);
+    }
 #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
 
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
-    if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
-        return( mbedtls_ecp_gen_privkey_sw( &grp->N, d, f_rng, p_rng ) );
+    if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
+        return mbedtls_ecp_gen_privkey_sw(&grp->N, d, f_rng, p_rng);
+    }
 #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
 
-    return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+    return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
 }
 
 /*
  * Generate a keypair with configurable base point
  */
-int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
-                     const mbedtls_ecp_point *G,
-                     mbedtls_mpi *d, mbedtls_ecp_point *Q,
-                     int (*f_rng)(void *, unsigned char *, size_t),
-                     void *p_rng )
+int mbedtls_ecp_gen_keypair_base(mbedtls_ecp_group *grp,
+                                 const mbedtls_ecp_point *G,
+                                 mbedtls_mpi *d, mbedtls_ecp_point *Q,
+                                 int (*f_rng)(void *, unsigned char *, size_t),
+                                 void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    ECP_VALIDATE_RET( grp   != NULL );
-    ECP_VALIDATE_RET( d     != NULL );
-    ECP_VALIDATE_RET( G     != NULL );
-    ECP_VALIDATE_RET( Q     != NULL );
-    ECP_VALIDATE_RET( f_rng != NULL );
-
-    MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
-    MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng));
+    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(grp, Q, d, G, f_rng, p_rng));
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /*
  * Generate key pair, wrapper for conventional base point
  */
-int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
-                             mbedtls_mpi *d, mbedtls_ecp_point *Q,
-                             int (*f_rng)(void *, unsigned char *, size_t),
-                             void *p_rng )
+int mbedtls_ecp_gen_keypair(mbedtls_ecp_group *grp,
+                            mbedtls_mpi *d, mbedtls_ecp_point *Q,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng)
 {
-    ECP_VALIDATE_RET( grp   != NULL );
-    ECP_VALIDATE_RET( d     != NULL );
-    ECP_VALIDATE_RET( Q     != NULL );
-    ECP_VALIDATE_RET( f_rng != NULL );
-
-    return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
+    return mbedtls_ecp_gen_keypair_base(grp, &grp->G, d, Q, f_rng, p_rng);
 }
 
 /*
  * Generate a keypair, prettier wrapper
  */
-int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
-                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+int mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
+                        int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    ECP_VALIDATE_RET( key   != NULL );
-    ECP_VALIDATE_RET( f_rng != NULL );
+    if ((ret = mbedtls_ecp_group_load(&key->grp, grp_id)) != 0) {
+        return ret;
+    }
 
-    if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
-        return( ret );
-
-    return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
+    return mbedtls_ecp_gen_keypair(&key->grp, &key->d, &key->Q, f_rng, p_rng);
 }
 
 #define ECP_CURVE25519_KEY_SIZE 32
+#define ECP_CURVE448_KEY_SIZE   56
 /*
  * Read a private key.
  */
-int mbedtls_ecp_read_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
-                          const unsigned char *buf, size_t buflen )
+int mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
+                         const unsigned char *buf, size_t buflen)
 {
     int ret = 0;
 
-    ECP_VALIDATE_RET( key  != NULL );
-    ECP_VALIDATE_RET( buf  != NULL );
-
-    if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_ecp_group_load(&key->grp, grp_id)) != 0) {
+        return ret;
+    }
 
     ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
 
 #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
-    if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
-    {
+    if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
         /*
-         * If it is Curve25519 curve then mask the key as mandated by RFC7748
+         * Mask the key as mandated by RFC7748 for Curve25519 and Curve448.
          */
-        if( grp_id == MBEDTLS_ECP_DP_CURVE25519 )
-        {
-            if( buflen != ECP_CURVE25519_KEY_SIZE )
+        if (grp_id == MBEDTLS_ECP_DP_CURVE25519) {
+            if (buflen != ECP_CURVE25519_KEY_SIZE) {
                 return MBEDTLS_ERR_ECP_INVALID_KEY;
+            }
 
-            MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary_le( &key->d, buf, buflen ) );
+            MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary_le(&key->d, buf, buflen));
 
             /* Set the three least significant bits to 0 */
-            MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 0, 0 ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 1, 0 ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 2, 0 ) );
+            MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 0, 0));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 1, 0));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 2, 0));
 
             /* Set the most significant bit to 0 */
             MBEDTLS_MPI_CHK(
-                    mbedtls_mpi_set_bit( &key->d,
-                                         ECP_CURVE25519_KEY_SIZE * 8 - 1, 0 )
-                    );
+                mbedtls_mpi_set_bit(&key->d,
+                                    ECP_CURVE25519_KEY_SIZE * 8 - 1, 0)
+                );
 
             /* Set the second most significant bit to 1 */
             MBEDTLS_MPI_CHK(
-                    mbedtls_mpi_set_bit( &key->d,
-                                         ECP_CURVE25519_KEY_SIZE * 8 - 2, 1 )
-                    );
+                mbedtls_mpi_set_bit(&key->d,
+                                    ECP_CURVE25519_KEY_SIZE * 8 - 2, 1)
+                );
+        } else if (grp_id == MBEDTLS_ECP_DP_CURVE448) {
+            if (buflen != ECP_CURVE448_KEY_SIZE) {
+                return MBEDTLS_ERR_ECP_INVALID_KEY;
+            }
+
+            MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary_le(&key->d, buf, buflen));
+
+            /* Set the two least significant bits to 0 */
+            MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 0, 0));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 1, 0));
+
+            /* Set the most significant bit to 1 */
+            MBEDTLS_MPI_CHK(
+                mbedtls_mpi_set_bit(&key->d,
+                                    ECP_CURVE448_KEY_SIZE * 8 - 1, 1)
+                );
         }
-        else
-            ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
     }
 
 #endif
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
-    if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &key->d, buf, buflen ) );
+    if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&key->d, buf, buflen));
 
-        MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( &key->grp, &key->d ) );
+        MBEDTLS_MPI_CHK(mbedtls_ecp_check_privkey(&key->grp, &key->d));
     }
 
 #endif
 cleanup:
 
-    if( ret != 0 )
-        mbedtls_mpi_free( &key->d );
+    if (ret != 0) {
+        mbedtls_mpi_free(&key->d);
+    }
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Write a private key.
  */
-int mbedtls_ecp_write_key( mbedtls_ecp_keypair *key,
-                           unsigned char *buf, size_t buflen )
+int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key,
+                          unsigned char *buf, size_t buflen)
 {
     int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
 
-    ECP_VALIDATE_RET( key != NULL );
-    ECP_VALIDATE_RET( buf != NULL );
-
 #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
-    if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
-    {
-        if( key->grp.id == MBEDTLS_ECP_DP_CURVE25519 )
-        {
-            if( buflen < ECP_CURVE25519_KEY_SIZE )
+    if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
+        if (key->grp.id == MBEDTLS_ECP_DP_CURVE25519) {
+            if (buflen < ECP_CURVE25519_KEY_SIZE) {
                 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+            }
 
-            MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary_le( &key->d, buf, buflen ) );
+        } else if (key->grp.id == MBEDTLS_ECP_DP_CURVE448) {
+            if (buflen < ECP_CURVE448_KEY_SIZE) {
+                return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+            }
         }
-        else
-            ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary_le(&key->d, buf, buflen));
     }
-
 #endif
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
-    if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &key->d, buf, buflen ) );
+    if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&key->d, buf, buflen));
     }
 
 #endif
 cleanup:
 
-    return( ret );
+    return ret;
 }
 
 
 /*
  * Check a public-private key pair
  */
-int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
+int mbedtls_ecp_check_pub_priv(
+    const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv,
+    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecp_point Q;
     mbedtls_ecp_group grp;
-    ECP_VALIDATE_RET( pub != NULL );
-    ECP_VALIDATE_RET( prv != NULL );
-
-    if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
+    if (pub->grp.id == MBEDTLS_ECP_DP_NONE ||
         pub->grp.id != prv->grp.id ||
-        mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
-        mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
-        mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
-    {
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+        mbedtls_mpi_cmp_mpi(&pub->Q.X, &prv->Q.X) ||
+        mbedtls_mpi_cmp_mpi(&pub->Q.Y, &prv->Q.Y) ||
+        mbedtls_mpi_cmp_mpi(&pub->Q.Z, &prv->Q.Z)) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
     }
 
-    mbedtls_ecp_point_init( &Q );
-    mbedtls_ecp_group_init( &grp );
+    mbedtls_ecp_point_init(&Q);
+    mbedtls_ecp_group_init(&grp);
 
     /* mbedtls_ecp_mul() needs a non-const group... */
-    mbedtls_ecp_group_copy( &grp, &prv->grp );
+    mbedtls_ecp_group_copy(&grp, &prv->grp);
 
     /* Also checks d is valid */
-    MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&grp, &Q, &prv->d, &prv->grp.G, f_rng, p_rng));
 
-    if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
-        mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
-        mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
-    {
+    if (mbedtls_mpi_cmp_mpi(&Q.X, &prv->Q.X) ||
+        mbedtls_mpi_cmp_mpi(&Q.Y, &prv->Q.Y) ||
+        mbedtls_mpi_cmp_mpi(&Q.Z, &prv->Q.Z)) {
         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
         goto cleanup;
     }
 
 cleanup:
-    mbedtls_ecp_point_free( &Q );
-    mbedtls_ecp_group_free( &grp );
+    mbedtls_ecp_point_free(&Q);
+    mbedtls_ecp_group_free(&grp);
 
-    return( ret );
+    return ret;
+}
+
+/*
+ * Export generic key-pair parameters.
+ */
+int mbedtls_ecp_export(const mbedtls_ecp_keypair *key, mbedtls_ecp_group *grp,
+                       mbedtls_mpi *d, mbedtls_ecp_point *Q)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if ((ret = mbedtls_ecp_group_copy(grp, &key->grp)) != 0) {
+        return ret;
+    }
+
+    if ((ret = mbedtls_mpi_copy(d, &key->d)) != 0) {
+        return ret;
+    }
+
+    if ((ret = mbedtls_ecp_copy(Q, &key->Q)) != 0) {
+        return ret;
+    }
+
+    return 0;
 }
 
 #if defined(MBEDTLS_SELF_TEST)
 
+/*
+ * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
+ *
+ * This is the linear congruential generator from numerical recipes,
+ * except we only use the low byte as the output. See
+ * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
+ */
+static int self_test_rng(void *ctx, unsigned char *out, size_t len)
+{
+    static uint32_t state = 42;
+
+    (void) ctx;
+
+    for (size_t i = 0; i < len; i++) {
+        state = state * 1664525u + 1013904223u;
+        out[i] = (unsigned char) state;
+    }
+
+    return 0;
+}
+
 /* Adjust the exponent to be a valid private point for the specified curve.
  * This is sometimes necessary because we use a single set of exponents
  * for all curves but the validity of values depends on the curve. */
-static int self_test_adjust_exponent( const mbedtls_ecp_group *grp,
-                                      mbedtls_mpi *m )
+static int self_test_adjust_exponent(const mbedtls_ecp_group *grp,
+                                     mbedtls_mpi *m)
 {
     int ret = 0;
-    switch( grp->id )
-    {
-        /* If Curve25519 is available, then that's what we use for the
-         * Montgomery test, so we don't need the adjustment code. */
-#if ! defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+    switch (grp->id) {
+    /* If Curve25519 is available, then that's what we use for the
+     * Montgomery test, so we don't need the adjustment code. */
+#if !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
 #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
         case MBEDTLS_ECP_DP_CURVE448:
             /* Move highest bit from 254 to N-1. Setting bit N-1 is
              * necessary to enforce the highest-bit-set constraint. */
-            MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( m, 254, 0 ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( m, grp->nbits, 1 ) );
+            MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(m, 254, 0));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(m, grp->nbits, 1));
             /* Copy second-highest bit from 253 to N-2. This is not
              * necessary but improves the test variety a bit. */
             MBEDTLS_MPI_CHK(
-                mbedtls_mpi_set_bit( m, grp->nbits - 1,
-                                     mbedtls_mpi_get_bit( m, 253 ) ) );
+                mbedtls_mpi_set_bit(m, grp->nbits - 1,
+                                    mbedtls_mpi_get_bit(m, 253)));
             break;
 #endif
 #endif /* ! defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) */
@@ -3432,18 +3440,18 @@
             goto cleanup;
     }
 cleanup:
-    return( ret );
+    return ret;
 }
 
 /* Calculate R = m.P for each m in exponents. Check that the number of
  * basic operations doesn't depend on the value of m. */
-static int self_test_point( int verbose,
-                            mbedtls_ecp_group *grp,
-                            mbedtls_ecp_point *R,
-                            mbedtls_mpi *m,
-                            const mbedtls_ecp_point *P,
-                            const char *const *exponents,
-                            size_t n_exponents )
+static int self_test_point(int verbose,
+                           mbedtls_ecp_group *grp,
+                           mbedtls_ecp_point *R,
+                           mbedtls_mpi *m,
+                           const mbedtls_ecp_point *P,
+                           const char *const *exponents,
+                           size_t n_exponents)
 {
     int ret = 0;
     size_t i = 0;
@@ -3452,12 +3460,11 @@
     dbl_count = 0;
     mul_count = 0;
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( m, 16, exponents[0] ) );
-    MBEDTLS_MPI_CHK( self_test_adjust_exponent( grp, m ) );
-    MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(m, 16, exponents[0]));
+    MBEDTLS_MPI_CHK(self_test_adjust_exponent(grp, m));
+    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(grp, R, m, P, self_test_rng, NULL));
 
-    for( i = 1; i < n_exponents; i++ )
-    {
+    for (i = 1; i < n_exponents; i++) {
         add_c_prev = add_count;
         dbl_c_prev = dbl_count;
         mul_c_prev = mul_count;
@@ -3465,34 +3472,33 @@
         dbl_count = 0;
         mul_count = 0;
 
-        MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( m, 16, exponents[i] ) );
-        MBEDTLS_MPI_CHK( self_test_adjust_exponent( grp, m ) );
-        MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(m, 16, exponents[i]));
+        MBEDTLS_MPI_CHK(self_test_adjust_exponent(grp, m));
+        MBEDTLS_MPI_CHK(mbedtls_ecp_mul(grp, R, m, P, self_test_rng, NULL));
 
-        if( add_count != add_c_prev ||
+        if (add_count != add_c_prev ||
             dbl_count != dbl_c_prev ||
-            mul_count != mul_c_prev )
-        {
+            mul_count != mul_c_prev) {
             ret = 1;
             break;
         }
     }
 
 cleanup:
-    if( verbose != 0 )
-    {
-        if( ret != 0 )
-            mbedtls_printf( "failed (%u)\n", (unsigned int) i );
-        else
-            mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        if (ret != 0) {
+            mbedtls_printf("failed (%u)\n", (unsigned int) i);
+        } else {
+            mbedtls_printf("passed\n");
+        }
     }
-    return( ret );
+    return ret;
 }
 
 /*
  * Checkup routine
  */
-int mbedtls_ecp_self_test( int verbose )
+int mbedtls_ecp_self_test(int verbose)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecp_group grp;
@@ -3528,77 +3534,85 @@
     };
 #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
 
-    mbedtls_ecp_group_init( &grp );
-    mbedtls_ecp_point_init( &R );
-    mbedtls_ecp_point_init( &P );
-    mbedtls_mpi_init( &m );
+    mbedtls_ecp_group_init(&grp);
+    mbedtls_ecp_point_init(&R);
+    mbedtls_ecp_point_init(&P);
+    mbedtls_mpi_init(&m);
 
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
     /* Use secp192r1 if available, or any available curve */
 #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
-    MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP192R1));
 #else
-    MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&grp, mbedtls_ecp_curve_list()->grp_id));
 #endif
 
-    if( verbose != 0 )
-        mbedtls_printf( "  ECP SW test #1 (constant op_count, base point G): " );
+    if (verbose != 0) {
+        mbedtls_printf("  ECP SW test #1 (constant op_count, base point G): ");
+    }
     /* Do a dummy multiplication first to trigger precomputation */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) );
-    MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
-    ret = self_test_point( verbose,
-                           &grp, &R, &m, &grp.G,
-                           sw_exponents,
-                           sizeof( sw_exponents ) / sizeof( sw_exponents[0] ));
-    if( ret != 0 )
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&m, 2));
+    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&grp, &P, &m, &grp.G, self_test_rng, NULL));
+    ret = self_test_point(verbose,
+                          &grp, &R, &m, &grp.G,
+                          sw_exponents,
+                          sizeof(sw_exponents) / sizeof(sw_exponents[0]));
+    if (ret != 0) {
         goto cleanup;
+    }
 
-    if( verbose != 0 )
-        mbedtls_printf( "  ECP SW test #2 (constant op_count, other point): " );
+    if (verbose != 0) {
+        mbedtls_printf("  ECP SW test #2 (constant op_count, other point): ");
+    }
     /* We computed P = 2G last time, use it */
-    ret = self_test_point( verbose,
-                           &grp, &R, &m, &P,
-                           sw_exponents,
-                           sizeof( sw_exponents ) / sizeof( sw_exponents[0] ));
-    if( ret != 0 )
+    ret = self_test_point(verbose,
+                          &grp, &R, &m, &P,
+                          sw_exponents,
+                          sizeof(sw_exponents) / sizeof(sw_exponents[0]));
+    if (ret != 0) {
         goto cleanup;
+    }
 
-    mbedtls_ecp_group_free( &grp );
-    mbedtls_ecp_point_free( &R );
+    mbedtls_ecp_group_free(&grp);
+    mbedtls_ecp_point_free(&R);
 #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
 
 #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
-    if( verbose != 0 )
-        mbedtls_printf( "  ECP Montgomery test (constant op_count): " );
+    if (verbose != 0) {
+        mbedtls_printf("  ECP Montgomery test (constant op_count): ");
+    }
 #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
-    MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_CURVE25519 ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_CURVE25519));
 #elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
-    MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_CURVE448 ) );
+    MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_CURVE448));
 #else
 #error "MBEDTLS_ECP_MONTGOMERY_ENABLED is defined, but no curve is supported for self-test"
 #endif
-    ret = self_test_point( verbose,
-                           &grp, &R, &m, &grp.G,
-                           m_exponents,
-                           sizeof( m_exponents ) / sizeof( m_exponents[0] ));
-    if( ret != 0 )
+    ret = self_test_point(verbose,
+                          &grp, &R, &m, &grp.G,
+                          m_exponents,
+                          sizeof(m_exponents) / sizeof(m_exponents[0]));
+    if (ret != 0) {
         goto cleanup;
+    }
 #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
 
 cleanup:
 
-    if( ret < 0 && verbose != 0 )
-        mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
+    if (ret < 0 && verbose != 0) {
+        mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret);
+    }
 
-    mbedtls_ecp_group_free( &grp );
-    mbedtls_ecp_point_free( &R );
-    mbedtls_ecp_point_free( &P );
-    mbedtls_mpi_free( &m );
+    mbedtls_ecp_group_free(&grp);
+    mbedtls_ecp_point_free(&R);
+    mbedtls_ecp_point_free(&P);
+    mbedtls_mpi_free(&m);
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
-    return( ret );
+    return ret;
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/lib/libmbedtls/mbedtls/library/ecp_curves.c b/lib/libmbedtls/mbedtls/library/ecp_curves.c
index ea43e1f..f9b452b 100644
--- a/lib/libmbedtls/mbedtls/library/ecp_curves.c
+++ b/lib/libmbedtls/mbedtls/library/ecp_curves.c
@@ -24,8 +24,9 @@
 #include "mbedtls/ecp.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
-#include "mbedtls/bn_mul.h"
 
+#include "bn_mul.h"
+#include "bignum_core.h"
 #include "ecp_invasive.h"
 
 #include <string.h>
@@ -33,492 +34,20 @@
 #if !defined(MBEDTLS_ECP_ALT)
 
 /* Parameter validation macros based on platform_util.h */
-#define ECP_VALIDATE_RET( cond )    \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
-#define ECP_VALIDATE( cond )        \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
+#define ECP_VALIDATE_RET(cond)    \
+    MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA)
+#define ECP_VALIDATE(cond)        \
+    MBEDTLS_INTERNAL_VALIDATE(cond)
 
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
-    !defined(inline) && !defined(__cplusplus)
-#define inline __inline
-#endif
-
-#define ECP_MPI_INIT(s, n, p) {s, (n), (mbedtls_mpi_uint *)(p)}
+#define ECP_MPI_INIT(s, n, p) { s, (n), (mbedtls_mpi_uint *) (p) }
 
 #define ECP_MPI_INIT_ARRAY(x)   \
     ECP_MPI_INIT(1, sizeof(x) / sizeof(mbedtls_mpi_uint), x)
 
-/*
- * Note: the constants are in little-endian order
- * to be directly usable in MPIs
- */
-
-/*
- * Domain parameters for secp192r1
- */
-#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
-static const mbedtls_mpi_uint secp192r1_p[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-};
-static const mbedtls_mpi_uint secp192r1_b[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ),
-};
-static const mbedtls_mpi_uint secp192r1_gx[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ),
-};
-static const mbedtls_mpi_uint secp192r1_gy[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ),
-};
-static const mbedtls_mpi_uint secp192r1_n[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-};
-#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
-
-/*
- * Domain parameters for secp224r1
- */
-#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
-static const mbedtls_mpi_uint secp224r1_p[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
-};
-static const mbedtls_mpi_uint secp224r1_b[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ),
-    MBEDTLS_BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ),
-};
-static const mbedtls_mpi_uint secp224r1_gx[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ),
-    MBEDTLS_BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ),
-};
-static const mbedtls_mpi_uint secp224r1_gy[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ),
-    MBEDTLS_BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ),
-};
-static const mbedtls_mpi_uint secp224r1_n[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ),
-};
-#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
-
-/*
- * Domain parameters for secp256r1
- */
-#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
-static const mbedtls_mpi_uint secp256r1_p[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
-};
-static const mbedtls_mpi_uint secp256r1_b[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ),
-};
-static const mbedtls_mpi_uint secp256r1_gx[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ),
-};
-static const mbedtls_mpi_uint secp256r1_gy[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ),
-};
-static const mbedtls_mpi_uint secp256r1_n[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
-};
-#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
-
-/*
- * Domain parameters for secp384r1
- */
-#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
-static const mbedtls_mpi_uint secp384r1_p[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-};
-static const mbedtls_mpi_uint secp384r1_b[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ),
-};
-static const mbedtls_mpi_uint secp384r1_gx[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ),
-};
-static const mbedtls_mpi_uint secp384r1_gy[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ),
-};
-static const mbedtls_mpi_uint secp384r1_n[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-};
-#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
-
-/*
- * Domain parameters for secp521r1
- */
-#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
-static const mbedtls_mpi_uint secp521r1_p[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_2( 0xFF, 0x01 ),
-};
-static const mbedtls_mpi_uint secp521r1_b[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ),
-    MBEDTLS_BYTES_TO_T_UINT_2( 0x51, 0x00 ),
-};
-static const mbedtls_mpi_uint secp521r1_gx[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ),
-    MBEDTLS_BYTES_TO_T_UINT_2( 0xC6, 0x00 ),
-};
-static const mbedtls_mpi_uint secp521r1_gy[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ),
-    MBEDTLS_BYTES_TO_T_UINT_2( 0x18, 0x01 ),
-};
-static const mbedtls_mpi_uint secp521r1_n[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_2( 0xFF, 0x01 ),
-};
-#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
-
-#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
-static const mbedtls_mpi_uint secp192k1_p[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-};
-static const mbedtls_mpi_uint secp192k1_a[] = {
-    MBEDTLS_BYTES_TO_T_UINT_2( 0x00, 0x00 ),
-};
-static const mbedtls_mpi_uint secp192k1_b[] = {
-    MBEDTLS_BYTES_TO_T_UINT_2( 0x03, 0x00 ),
-};
-static const mbedtls_mpi_uint secp192k1_gx[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ),
-};
-static const mbedtls_mpi_uint secp192k1_gy[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ),
-};
-static const mbedtls_mpi_uint secp192k1_n[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-};
-#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
-
-#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
-static const mbedtls_mpi_uint secp224k1_p[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ),
-};
-static const mbedtls_mpi_uint secp224k1_a[] = {
-    MBEDTLS_BYTES_TO_T_UINT_2( 0x00, 0x00 ),
-};
-static const mbedtls_mpi_uint secp224k1_b[] = {
-    MBEDTLS_BYTES_TO_T_UINT_2( 0x05, 0x00 ),
-};
-static const mbedtls_mpi_uint secp224k1_gx[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ),
-    MBEDTLS_BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ),
-};
-static const mbedtls_mpi_uint secp224k1_gy[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ),
-    MBEDTLS_BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ),
-};
-static const mbedtls_mpi_uint secp224k1_n[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ),
-};
-#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
-
-#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
-static const mbedtls_mpi_uint secp256k1_p[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-};
-static const mbedtls_mpi_uint secp256k1_a[] = {
-    MBEDTLS_BYTES_TO_T_UINT_2( 0x00, 0x00 ),
-};
-static const mbedtls_mpi_uint secp256k1_b[] = {
-    MBEDTLS_BYTES_TO_T_UINT_2( 0x07, 0x00 ),
-};
-static const mbedtls_mpi_uint secp256k1_gx[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ),
-};
-static const mbedtls_mpi_uint secp256k1_gy[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ),
-};
-static const mbedtls_mpi_uint secp256k1_n[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
-};
-#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
-
-/*
- * Domain parameters for brainpoolP256r1 (RFC 5639 3.4)
- */
-#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
-static const mbedtls_mpi_uint brainpoolP256r1_p[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ),
-};
-static const mbedtls_mpi_uint brainpoolP256r1_a[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ),
-};
-static const mbedtls_mpi_uint brainpoolP256r1_b[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ),
-};
-static const mbedtls_mpi_uint brainpoolP256r1_gx[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ),
-};
-static const mbedtls_mpi_uint brainpoolP256r1_gy[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ),
-};
-static const mbedtls_mpi_uint brainpoolP256r1_n[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ),
-};
-#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */
-
-/*
- * Domain parameters for brainpoolP384r1 (RFC 5639 3.6)
- */
-#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
-static const mbedtls_mpi_uint brainpoolP384r1_p[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ),
-};
-static const mbedtls_mpi_uint brainpoolP384r1_a[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ),
-};
-static const mbedtls_mpi_uint brainpoolP384r1_b[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ),
-};
-static const mbedtls_mpi_uint brainpoolP384r1_gx[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ),
-};
-static const mbedtls_mpi_uint brainpoolP384r1_gy[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ),
-};
-static const mbedtls_mpi_uint brainpoolP384r1_n[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ),
-};
-#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */
-
-/*
- * Domain parameters for brainpoolP512r1 (RFC 5639 3.7)
- */
-#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
-static const mbedtls_mpi_uint brainpoolP512r1_p[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ),
-};
-static const mbedtls_mpi_uint brainpoolP512r1_a[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ),
-};
-static const mbedtls_mpi_uint brainpoolP512r1_b[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ),
-};
-static const mbedtls_mpi_uint brainpoolP512r1_gx[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ),
-};
-static const mbedtls_mpi_uint brainpoolP512r1_gy[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ),
-};
-static const mbedtls_mpi_uint brainpoolP512r1_n[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ),
-    MBEDTLS_BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ),
-};
-#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
+#define ECP_POINT_INIT_XY_Z0(x, y) { \
+        ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(1, 0, NULL) }
+#define ECP_POINT_INIT_XY_Z1(x, y) { \
+        ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(1, 1, mpi_one) }
 
 #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) ||   \
     defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \
@@ -533,9 +62,4449 @@
     defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
 /* For these curves, we build the group parameters dynamically. */
 #define ECP_LOAD_GROUP
+static mbedtls_mpi_uint mpi_one[] = { 1 };
 #endif
 
-#if defined(ECP_LOAD_GROUP)
+/*
+ * Note: the constants are in little-endian order
+ * to be directly usable in MPIs
+ */
+
+/*
+ * Domain parameters for secp192r1
+ */
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
+static const mbedtls_mpi_uint secp192r1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+static const mbedtls_mpi_uint secp192r1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64),
+};
+static const mbedtls_mpi_uint secp192r1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18),
+};
+static const mbedtls_mpi_uint secp192r1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07),
+};
+static const mbedtls_mpi_uint secp192r1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint secp192r1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18),
+};
+static const mbedtls_mpi_uint secp192r1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07),
+};
+static const mbedtls_mpi_uint secp192r1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x9E, 0xE3, 0x60, 0x59, 0xD1, 0xC4, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBD, 0x22, 0xD7, 0x2D, 0x07, 0xBD, 0xB6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x2A, 0xCF, 0x33, 0xF0, 0xBE, 0xD1, 0xED),
+};
+static const mbedtls_mpi_uint secp192r1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x71, 0x4B, 0xA8, 0xED, 0x7E, 0xC9, 0x1A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x2A, 0xF6, 0xDF, 0x0E, 0xE8, 0x4C, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x35, 0xF7, 0x8A, 0xC3, 0xEC, 0xDE, 0x1E),
+};
+static const mbedtls_mpi_uint secp192r1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0xC2, 0x1D, 0x32, 0x8F, 0x10, 0xFB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x2D, 0x17, 0xF3, 0xE4, 0xFE, 0xD8, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x45, 0x10, 0x70, 0x2C, 0x3E, 0x52, 0x3E),
+};
+static const mbedtls_mpi_uint secp192r1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF1, 0x04, 0x5D, 0xEE, 0xD4, 0x56, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xB7, 0x38, 0x27, 0x61, 0xAA, 0x81, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0xD7, 0x0E, 0x29, 0x0E, 0x11, 0x14),
+};
+static const mbedtls_mpi_uint secp192r1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x35, 0x52, 0xC6, 0x31, 0xB7, 0x27, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xD4, 0x15, 0x98, 0x0F, 0xE7, 0xF3, 0x6A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x31, 0x70, 0x35, 0x09, 0xA0, 0x2B, 0xC2),
+};
+static const mbedtls_mpi_uint secp192r1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x75, 0xA7, 0x4C, 0x88, 0xCF, 0x5B, 0xE4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x17, 0x48, 0x8D, 0xF2, 0xF0, 0x86, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCF, 0xFE, 0x6B, 0xB0, 0xA5, 0x06, 0xAB),
+};
+static const mbedtls_mpi_uint secp192r1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x6A, 0xDC, 0x9A, 0x6D, 0x7B, 0x47, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xFC, 0x51, 0x12, 0x62, 0x66, 0x0B, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x40, 0x93, 0xA0, 0xB5, 0x5A, 0x58, 0xD7),
+};
+static const mbedtls_mpi_uint secp192r1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCB, 0xAF, 0xDC, 0x0B, 0xA1, 0x26, 0xFB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x36, 0x9D, 0xA3, 0xD7, 0x3B, 0xAD, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x3B, 0x05, 0x9A, 0xA8, 0xAA, 0x69, 0xB2),
+};
+static const mbedtls_mpi_uint secp192r1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD9, 0xD1, 0x4D, 0x4A, 0x6E, 0x96, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x66, 0x32, 0x39, 0xC6, 0x57, 0x7D, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xA0, 0x36, 0xC2, 0x45, 0xF9, 0x00, 0x62),
+};
+static const mbedtls_mpi_uint secp192r1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xEF, 0x59, 0x46, 0xDC, 0x60, 0xD9, 0x8F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xB0, 0xE9, 0x41, 0xA4, 0x87, 0x76, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xD4, 0x0E, 0xB2, 0xFA, 0x16, 0x56, 0xDC),
+};
+static const mbedtls_mpi_uint secp192r1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x62, 0xD2, 0xB1, 0x34, 0xB2, 0xF1, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xED, 0x55, 0xC5, 0x47, 0xB5, 0x07, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF6, 0x2F, 0x94, 0xC3, 0xDD, 0x54, 0x2F),
+};
+static const mbedtls_mpi_uint secp192r1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xA6, 0xD4, 0x8C, 0xA9, 0xCE, 0x4D, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x4B, 0x46, 0xCC, 0xB2, 0x55, 0xC8, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x31, 0xED, 0x89, 0x65, 0x59, 0x55),
+};
+static const mbedtls_mpi_uint secp192r1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x0A, 0xD1, 0x1A, 0xC5, 0xF6, 0xEA, 0x43),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xFC, 0x0C, 0x1A, 0xFB, 0xA0, 0xC8, 0x70),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xFD, 0x53, 0x6F, 0x6D, 0xBF, 0xBA, 0xAF),
+};
+static const mbedtls_mpi_uint secp192r1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xB0, 0x7D, 0x83, 0x96, 0xE3, 0xCB, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x6E, 0x55, 0x2C, 0x20, 0x53, 0x2F, 0x46),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x66, 0x00, 0x17, 0x08, 0xFE, 0xAC, 0x31),
+};
+static const mbedtls_mpi_uint secp192r1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x12, 0x97, 0x3A, 0xC7, 0x57, 0x45, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x25, 0x99, 0x00, 0xF6, 0x97, 0xB4, 0x64),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x74, 0xE6, 0xE6, 0xA3, 0xDF, 0x9C, 0xCC),
+};
+static const mbedtls_mpi_uint secp192r1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xF4, 0x76, 0xD5, 0x5F, 0x2A, 0xFD, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x80, 0x7E, 0x3E, 0xE5, 0xE8, 0xD6, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xAD, 0x1E, 0x70, 0x79, 0x3E, 0x3D, 0x83),
+};
+static const mbedtls_mpi_uint secp192r1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x15, 0xBB, 0xB3, 0x42, 0x6A, 0xA1, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x58, 0xCB, 0x43, 0x25, 0x00, 0x14, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x4E, 0x93, 0x11, 0xE0, 0x32, 0x54, 0x98),
+};
+static const mbedtls_mpi_uint secp192r1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x52, 0xA2, 0xB4, 0x57, 0x32, 0xB9, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x43, 0xA1, 0xB1, 0xFB, 0x01, 0xE1, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xFB, 0x5A, 0x11, 0xB8, 0xC2, 0x03, 0xE5),
+};
+static const mbedtls_mpi_uint secp192r1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x2B, 0x71, 0x26, 0x4E, 0x7C, 0xC5, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF5, 0xD3, 0xA8, 0xE4, 0x95, 0x48, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAE, 0xD9, 0x5D, 0x9F, 0x6A, 0x22, 0xAD),
+};
+static const mbedtls_mpi_uint secp192r1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xCC, 0xA3, 0x4D, 0xA0, 0x1C, 0x34, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x3C, 0x62, 0xF8, 0x5E, 0xA6, 0x58, 0x7D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x6E, 0x66, 0x8A, 0x3D, 0x17, 0xFF, 0x0F),
+};
+static const mbedtls_mpi_uint secp192r1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xCD, 0xA8, 0xDD, 0xD1, 0x20, 0x5C, 0xEA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xFE, 0x17, 0xE2, 0xCF, 0xEA, 0x63, 0xDE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x51, 0xC9, 0x16, 0xDE, 0xB4, 0xB2, 0xDD),
+};
+static const mbedtls_mpi_uint secp192r1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBE, 0x12, 0xD7, 0xA3, 0x0A, 0x50, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x87, 0xC5, 0x8A, 0x76, 0x57, 0x07, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x1F, 0xC6, 0x1B, 0x66, 0xC4, 0x3D, 0x8A),
+};
+static const mbedtls_mpi_uint secp192r1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xA4, 0x85, 0x13, 0x8F, 0xA7, 0x35, 0x19),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x0D, 0xFD, 0xFF, 0x1B, 0xD1, 0xD6, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x7A, 0xD0, 0xC3, 0xB4, 0xEF, 0x39, 0x66),
+};
+static const mbedtls_mpi_uint secp192r1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xFE, 0xA5, 0x9C, 0x34, 0x30, 0x49, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xC5, 0x39, 0x26, 0x06, 0xE3, 0x01, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x2B, 0x66, 0xFC, 0x95, 0x5F, 0x35, 0xF7),
+};
+static const mbedtls_mpi_uint secp192r1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xCF, 0x54, 0x63, 0x99, 0x57, 0x05, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x6F, 0x00, 0x5F, 0x65, 0x08, 0x47, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x2A, 0x90, 0x6D, 0x67, 0xC6, 0xBC, 0x45),
+};
+static const mbedtls_mpi_uint secp192r1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x4D, 0x88, 0x0A, 0x35, 0x9E, 0x33, 0x9C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x17, 0x0C, 0xF8, 0xE1, 0x7A, 0x49, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x44, 0x06, 0x8F, 0x0B, 0x70, 0x2F, 0x71),
+};
+static const mbedtls_mpi_uint secp192r1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4B, 0xCB, 0xF9, 0x8E, 0x6A, 0xDA, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x43, 0xA1, 0x3F, 0xCE, 0x17, 0xD2, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x0D, 0xD2, 0x6C, 0x82, 0x37, 0xE5, 0xFC),
+};
+static const mbedtls_mpi_uint secp192r1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x3C, 0xF4, 0x92, 0xB4, 0x8A, 0x95, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x96, 0xF1, 0x0A, 0x34, 0x2F, 0x74, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0xAA, 0xBA, 0x86, 0x77, 0x4F, 0xA2),
+};
+static const mbedtls_mpi_uint secp192r1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x7F, 0xEF, 0x60, 0x50, 0x80, 0xD7, 0xD4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xAC, 0xC9, 0xFE, 0xEC, 0x0A, 0x1A, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x2F, 0xBE, 0x91, 0xD7, 0xB7, 0x38, 0x48),
+};
+static const mbedtls_mpi_uint secp192r1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xAE, 0x85, 0x98, 0xFE, 0x05, 0x7F, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBE, 0xFD, 0x11, 0x31, 0x3D, 0x14, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x75, 0xE8, 0x30, 0x01, 0xCB, 0x9B, 0x1C),
+};
+static const mbedtls_ecp_point secp192r1_T[16] = {
+    ECP_POINT_INIT_XY_Z1(secp192r1_T_0_X, secp192r1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_1_X, secp192r1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_2_X, secp192r1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_3_X, secp192r1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_4_X, secp192r1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_5_X, secp192r1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_6_X, secp192r1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_7_X, secp192r1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_8_X, secp192r1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_9_X, secp192r1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_10_X, secp192r1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_11_X, secp192r1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_12_X, secp192r1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_13_X, secp192r1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_14_X, secp192r1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_15_X, secp192r1_T_15_Y),
+};
+#else
+#define secp192r1_T NULL
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
+
+/*
+ * Domain parameters for secp224r1
+ */
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+static const mbedtls_mpi_uint secp224r1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C),
+    MBEDTLS_BYTES_TO_T_UINT_4(0x85, 0x0A, 0x05, 0xB4),
+};
+static const mbedtls_mpi_uint secp224r1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_4(0xBD, 0x0C, 0x0E, 0xB7),
+};
+static const mbedtls_mpi_uint secp224r1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_4(0x88, 0x63, 0x37, 0xBD),
+};
+static const mbedtls_mpi_uint secp224r1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF),
+};
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint secp224r1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x0C, 0x0E, 0xB7, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x63, 0x37, 0xBD, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF9, 0xB8, 0xD0, 0x3D, 0xD2, 0xD3, 0xFA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xFD, 0x99, 0x26, 0x19, 0xFE, 0x13, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x0E, 0x4C, 0x48, 0x7C, 0xA2, 0x17, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA3, 0x13, 0x57, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x16, 0x5C, 0x8F, 0xAA, 0xED, 0x0F, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xC5, 0x43, 0x34, 0x93, 0x05, 0x2A, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE3, 0x6C, 0xCA, 0xC6, 0x14, 0xC2, 0x25),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x43, 0x6C, 0xD7, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x5A, 0x98, 0x1E, 0xC8, 0xA5, 0x42, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x49, 0x56, 0x78, 0xF8, 0xEF, 0xED, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xBB, 0x64, 0xB6, 0x4C, 0x54, 0x5F, 0xD1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x0C, 0x33, 0xCC, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x79, 0xCB, 0x2E, 0x08, 0xFF, 0xD8, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x1F, 0xD4, 0xD7, 0x57, 0xE9, 0x39, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xD6, 0x3B, 0x0A, 0x1C, 0x87, 0xB7, 0x6A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x30, 0xD8, 0x05, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x79, 0x74, 0x9A, 0xE6, 0xBB, 0xC2, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x5B, 0xA6, 0x67, 0xC1, 0x91, 0xE7, 0x64),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xDF, 0x38, 0x82, 0x19, 0x2C, 0x4C, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x2E, 0x39, 0xC5, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x36, 0x78, 0x4E, 0xAE, 0x5B, 0x02, 0x76),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF6, 0x8B, 0xF8, 0xF4, 0x92, 0x6B, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x4D, 0x71, 0x35, 0xE7, 0x0C, 0x2C, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xA5, 0x1F, 0xAE, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x1C, 0x4B, 0xDF, 0x5B, 0xF2, 0x51, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0xB1, 0x5A, 0xC6, 0x0F, 0x0E, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x24, 0x09, 0x62, 0xAF, 0xFC, 0xDB, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xE1, 0x80, 0x55, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x82, 0xFE, 0xAD, 0xC3, 0xE5, 0xCF, 0xD8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xA2, 0x62, 0x17, 0x76, 0xF0, 0x5A, 0xFA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB8, 0xE5, 0xAC, 0xB7, 0x66, 0x38, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xFD, 0x86, 0x05, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0x0C, 0x3C, 0xD1, 0x66, 0xB0, 0xF1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x59, 0xB4, 0x8D, 0x90, 0x10, 0xB7, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x47, 0x9B, 0xE6, 0x55, 0x8A, 0xE4, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x49, 0xDB, 0x78, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x97, 0xED, 0xDE, 0xFF, 0xB3, 0xDF, 0x48),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xB9, 0x83, 0xB7, 0xEB, 0xBE, 0x40, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xD3, 0xD3, 0xCD, 0x0E, 0x82, 0x79, 0x3D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x83, 0x1B, 0xF0, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x22, 0xBB, 0x54, 0xD3, 0x31, 0x56, 0xFC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0xE5, 0xE0, 0x89, 0x96, 0x8E, 0x71),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xEF, 0x0A, 0xED, 0xD0, 0x11, 0x4A, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x00, 0x57, 0x27, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCA, 0x3D, 0xF7, 0x64, 0x9B, 0x6E, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xE3, 0x70, 0x6B, 0x41, 0xD7, 0xED, 0x8F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x44, 0x44, 0x80, 0xCE, 0x13, 0x37, 0x92),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x73, 0x80, 0x79, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x4D, 0x70, 0x7D, 0x31, 0x0F, 0x1C, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x35, 0x88, 0x47, 0xC4, 0x24, 0x78, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF0, 0xCD, 0x91, 0x81, 0xB3, 0xDE, 0xB6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xCE, 0xC6, 0xF7, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x9C, 0x2D, 0xE8, 0xD2, 0x00, 0x8F, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x5E, 0x7C, 0x0E, 0x0C, 0x6E, 0x58, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x81, 0x21, 0xCE, 0x43, 0xF4, 0x24, 0x3D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xBC, 0xF0, 0xF4, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x10, 0xC2, 0x74, 0x4A, 0x8F, 0x8A, 0xCF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x67, 0xF4, 0x2B, 0x38, 0x2B, 0x35, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0C, 0xA9, 0xFA, 0x77, 0x5C, 0xBD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x19, 0x2B, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x3E, 0x96, 0x22, 0x53, 0xE1, 0xE9, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x13, 0xBC, 0xA1, 0x16, 0xEC, 0x01, 0x1A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x00, 0xC9, 0x7A, 0xC3, 0x73, 0xA5, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xF4, 0x5E, 0xC1, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x95, 0xD6, 0xD9, 0x32, 0x30, 0x2B, 0xD0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x42, 0x09, 0x05, 0x61, 0x2A, 0x7E, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x84, 0xA2, 0x05, 0x88, 0x64, 0x65, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2D, 0x90, 0xB3, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE7, 0x2E, 0x85, 0x55, 0x80, 0x7C, 0x79),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC1, 0xAC, 0x78, 0xB4, 0xAF, 0xFB, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xC3, 0x28, 0x8E, 0x79, 0x18, 0x1F, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x46, 0xCF, 0x49, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x5F, 0xA8, 0x6C, 0x46, 0x83, 0x43, 0xFA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xA9, 0x93, 0x11, 0xB6, 0x07, 0x57, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x2A, 0x9D, 0x03, 0x89, 0x7E, 0xD7, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x8C, 0x62, 0xCF, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x2C, 0x13, 0x59, 0xCC, 0xFA, 0x84, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB9, 0x48, 0xBC, 0x57, 0xC7, 0xB3, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x0A, 0x38, 0x24, 0x2E, 0x3A, 0x28, 0x25),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x0A, 0x43, 0xB8, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x25, 0xAB, 0xC1, 0xEE, 0x70, 0x3C, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xDB, 0x45, 0x1D, 0x4A, 0x80, 0x75, 0x35),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1F, 0x4D, 0x2D, 0x9A, 0x05, 0xF4, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x10, 0xF0, 0x5A, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x95, 0xE1, 0xDC, 0x15, 0x86, 0xC3, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xDC, 0x27, 0xD1, 0x56, 0xA1, 0x14, 0x0D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x0B, 0xD6, 0x77, 0x4E, 0x44, 0xA2, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x42, 0x71, 0x1F, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x86, 0xB2, 0xB0, 0xC8, 0x2F, 0x7B, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xEF, 0xCB, 0xDB, 0xBC, 0x9E, 0x3B, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x03, 0x86, 0xDD, 0x5B, 0xF5, 0x8D, 0x46),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x95, 0x79, 0xD6, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x32, 0x14, 0xDA, 0x9B, 0x4F, 0x07, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x3E, 0xFB, 0x06, 0xEE, 0xA7, 0x40, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x1F, 0xDF, 0x71, 0x61, 0xFD, 0x8B, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x8B, 0xAB, 0x8B, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x34, 0xB3, 0xB4, 0xBC, 0x9F, 0xB0, 0x5E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x58, 0x48, 0xA8, 0x77, 0xBB, 0x13, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC6, 0xF7, 0x34, 0xCC, 0x89, 0x21, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x33, 0xDD, 0x1F, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x81, 0xEF, 0xA4, 0xF2, 0x10, 0x0B, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF7, 0x6E, 0x72, 0x4A, 0xDF, 0xDD, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x23, 0x0A, 0x53, 0x03, 0x16, 0x62, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x76, 0xFD, 0x3C, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x14, 0xA1, 0xFA, 0xA0, 0x18, 0xBE, 0x07),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2A, 0xE1, 0xD7, 0xB0, 0x6C, 0xA0, 0xDE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xC0, 0xB0, 0xC6, 0x63, 0x24, 0xCD, 0x4E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x38, 0x2C, 0xB1, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCD, 0x7D, 0x20, 0x0C, 0xFE, 0xAC, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x9F, 0xA2, 0xB6, 0x45, 0xF7, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x99, 0xF3, 0xD2, 0x20, 0x02, 0xEB, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x5B, 0x7B, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xDD, 0x77, 0x91, 0x60, 0xEA, 0xFD, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xD3, 0xB5, 0xD6, 0x90, 0x17, 0x0E, 0x1A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xF4, 0x28, 0xC1, 0xF2, 0x53, 0xF6, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x58, 0xDC, 0x61, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x20, 0x01, 0xFB, 0xF1, 0xBD, 0x5F, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x7F, 0x06, 0xDA, 0x11, 0xCB, 0xBA, 0xA6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x41, 0x00, 0xA4, 0x1B, 0x30, 0x33, 0x79),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xFF, 0x27, 0xCA, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_ecp_point secp224r1_T[16] = {
+    ECP_POINT_INIT_XY_Z1(secp224r1_T_0_X, secp224r1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_1_X, secp224r1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_2_X, secp224r1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_3_X, secp224r1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_4_X, secp224r1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_5_X, secp224r1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_6_X, secp224r1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_7_X, secp224r1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_8_X, secp224r1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_9_X, secp224r1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_10_X, secp224r1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_11_X, secp224r1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_12_X, secp224r1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_13_X, secp224r1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_14_X, secp224r1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_15_X, secp224r1_T_15_Y),
+};
+#else
+#define secp224r1_T NULL
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
+
+/*
+ * Domain parameters for secp256r1
+ */
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+static const mbedtls_mpi_uint secp256r1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+static const mbedtls_mpi_uint secp256r1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A),
+};
+static const mbedtls_mpi_uint secp256r1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B),
+};
+static const mbedtls_mpi_uint secp256r1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F),
+};
+static const mbedtls_mpi_uint secp256r1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint secp256r1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B),
+};
+static const mbedtls_mpi_uint secp256r1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F),
+};
+static const mbedtls_mpi_uint secp256r1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xC8, 0xBA, 0x04, 0xB7, 0x4B, 0xD2, 0xF7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC6, 0x23, 0x3A, 0xA0, 0x09, 0x3A, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x9D, 0x4C, 0xF9, 0x58, 0x23, 0xCC, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xED, 0x7B, 0x29, 0x87, 0x0F, 0xFA, 0x3C),
+};
+static const mbedtls_mpi_uint secp256r1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x69, 0xF2, 0x40, 0x0B, 0xA3, 0x98, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xA8, 0x48, 0x02, 0x0D, 0x1C, 0x12, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xAF, 0x09, 0x83, 0x80, 0xAA, 0x58, 0xA7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x12, 0xBE, 0x70, 0x94, 0x76, 0xE3, 0xE4),
+};
+static const mbedtls_mpi_uint secp256r1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x7D, 0xEF, 0x86, 0xFF, 0xE3, 0x37, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x86, 0x8B, 0x08, 0x27, 0x7C, 0xD7, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x54, 0x4C, 0x25, 0x4F, 0x9A, 0xFE, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xFD, 0xF0, 0x6D, 0x37, 0x03, 0x69, 0xD6),
+};
+static const mbedtls_mpi_uint secp256r1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xD5, 0xDA, 0xAD, 0x92, 0x49, 0xF0, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x73, 0x43, 0x9E, 0xAF, 0xA7, 0xD1, 0xF3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x41, 0x07, 0xDF, 0x78, 0x95, 0x3E, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x3D, 0xD1, 0xE6, 0x3C, 0xA5, 0xE2, 0x20),
+};
+static const mbedtls_mpi_uint secp256r1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x6A, 0x5D, 0x52, 0x35, 0xD7, 0xBF, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xA2, 0xBE, 0x96, 0xF4, 0xF8, 0x02, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x20, 0x49, 0x54, 0xEA, 0xB3, 0x82, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0xDB, 0xEA, 0x02, 0xD1, 0x75, 0x1C, 0x62),
+};
+static const mbedtls_mpi_uint secp256r1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x85, 0xF4, 0x9E, 0x4C, 0xDC, 0x39, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x6D, 0xC4, 0x57, 0xD8, 0x03, 0x5D, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x7F, 0x2D, 0x52, 0x6F, 0xC9, 0xDA, 0x4F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x64, 0xFA, 0xB4, 0xFE, 0xA4, 0xC4, 0xD7),
+};
+static const mbedtls_mpi_uint secp256r1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x37, 0xB9, 0xC0, 0xAA, 0x59, 0xC6, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x58, 0xD9, 0xED, 0x58, 0x99, 0x65, 0xF7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x7D, 0x26, 0x8C, 0x4A, 0xF9, 0x05, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x73, 0x9A, 0xC9, 0xE7, 0x46, 0xDC, 0x00),
+};
+static const mbedtls_mpi_uint secp256r1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xD0, 0x55, 0xDF, 0x00, 0x0A, 0xF5, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xBF, 0x56, 0x81, 0x2D, 0x20, 0xEB, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC1, 0x28, 0x52, 0xAB, 0xE3, 0xD1, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x34, 0x79, 0x45, 0x57, 0xA5, 0x12, 0x03),
+};
+static const mbedtls_mpi_uint secp256r1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCF, 0xB8, 0x7E, 0xF7, 0x92, 0x96, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x01, 0x8C, 0x0D, 0x23, 0xF2, 0xE3, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x2E, 0xE3, 0x84, 0x52, 0x7A, 0x34, 0x76),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xA1, 0xB0, 0x15, 0x90, 0xE2, 0x53, 0x3C),
+};
+static const mbedtls_mpi_uint secp256r1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x98, 0xE7, 0xFA, 0xA5, 0x7D, 0x8B, 0x53),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x35, 0xD2, 0x00, 0xD1, 0x1B, 0x9F, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x69, 0x08, 0x9A, 0x72, 0xF0, 0xA9, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xFE, 0x0E, 0x14, 0xDA, 0x7C, 0x0E, 0xD3),
+};
+static const mbedtls_mpi_uint secp256r1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF6, 0xE8, 0xF8, 0x87, 0xF7, 0xFC, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xBE, 0x7F, 0x3F, 0x7A, 0x2B, 0xD7, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x32, 0xF2, 0x2D, 0x94, 0x6D, 0x42, 0xFD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x9A, 0xE3, 0x5F, 0x42, 0xBB, 0x84, 0xED),
+};
+static const mbedtls_mpi_uint secp256r1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x95, 0x29, 0x73, 0xA1, 0x67, 0x3E, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x30, 0x54, 0x35, 0x8E, 0x0A, 0xDD, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xD7, 0xA1, 0x97, 0x61, 0x3B, 0xF8, 0x0C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x33, 0x3C, 0x58, 0x55, 0x34, 0x23, 0xA3),
+};
+static const mbedtls_mpi_uint secp256r1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x5D, 0x16, 0x5F, 0x7B, 0xBC, 0xBB, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xEE, 0x4E, 0x8A, 0xC1, 0x51, 0xCC, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0D, 0x4D, 0x1B, 0x53, 0x23, 0x1D, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x2A, 0x38, 0x66, 0x52, 0x84, 0xE1, 0x95),
+};
+static const mbedtls_mpi_uint secp256r1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x9B, 0x83, 0x0A, 0x81, 0x4F, 0xAD, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xFF, 0x42, 0x41, 0x6E, 0xA9, 0xA2, 0xA0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA1, 0x4F, 0x1F, 0x89, 0x82, 0xAA, 0x3E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xB8, 0x0F, 0x6B, 0x8F, 0x8C, 0xD6, 0x68),
+};
+static const mbedtls_mpi_uint secp256r1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0xB3, 0xBB, 0x51, 0x69, 0xA2, 0x11, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x4F, 0x0F, 0x8D, 0xBD, 0x26, 0x0F, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xCB, 0xEC, 0x6B, 0x34, 0xC3, 0x3D, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x5D, 0x1E, 0x10, 0xD5, 0x44, 0xE2, 0x54),
+};
+static const mbedtls_mpi_uint secp256r1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x9E, 0xB1, 0xF1, 0x6E, 0x4C, 0xAD, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE3, 0xC2, 0x58, 0xC0, 0xFB, 0x34, 0x43),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x9C, 0xDF, 0x35, 0x07, 0x41, 0xBD, 0x19),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x10, 0xEC, 0x0E, 0xEC, 0xBB, 0xD6),
+};
+static const mbedtls_mpi_uint secp256r1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xCF, 0xEF, 0x3F, 0x83, 0x1A, 0x88, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x29, 0xB5, 0xB9, 0xE0, 0xC9, 0xA3, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x46, 0x1E, 0x77, 0xCD, 0x7E, 0xB3, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x21, 0xD0, 0xD4, 0xA3, 0x16, 0x08, 0xEE),
+};
+static const mbedtls_mpi_uint secp256r1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xCA, 0xA8, 0xB3, 0xBF, 0x29, 0x99, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF2, 0x05, 0xC1, 0xCF, 0x5D, 0x91, 0x48),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x01, 0x49, 0xDB, 0x82, 0xDF, 0x5F, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x06, 0x90, 0xAD, 0xE3, 0x38, 0xA4, 0xC4),
+};
+static const mbedtls_mpi_uint secp256r1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xD2, 0x3A, 0xE8, 0x03, 0xC5, 0x6D, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x35, 0xD0, 0xAE, 0x1D, 0x7A, 0x9F, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x1E, 0xD2, 0xCB, 0xAC, 0x88, 0x27, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x9C, 0xE0, 0x31, 0xDD, 0x99, 0x86),
+};
+static const mbedtls_mpi_uint secp256r1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF9, 0x9B, 0x32, 0x96, 0x41, 0x58, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x5A, 0x2A, 0xB8, 0x96, 0x0E, 0xB2, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x78, 0x2C, 0xC7, 0x08, 0x99, 0x19, 0x24),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x59, 0x28, 0xE9, 0x84, 0x54, 0xE6, 0x16),
+};
+static const mbedtls_mpi_uint secp256r1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x38, 0x30, 0xDB, 0x70, 0x2C, 0x0A, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x5C, 0x9D, 0xE9, 0xD5, 0x46, 0x0B, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x0B, 0x60, 0x4B, 0x37, 0x7D, 0xB9, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x24, 0xF3, 0x3D, 0x79, 0x7F, 0x6C, 0x18),
+};
+static const mbedtls_mpi_uint secp256r1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7F, 0xE5, 0x1C, 0x4F, 0x60, 0x24, 0xF7, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xD8, 0xE2, 0x91, 0x7F, 0x89, 0x49, 0x92),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xA7, 0x2E, 0x8D, 0x6A, 0xB3, 0x39, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x89, 0xB5, 0x9A, 0xB8, 0x8D, 0x42, 0x9C),
+};
+static const mbedtls_mpi_uint secp256r1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x45, 0xE6, 0x4B, 0x3F, 0x4F, 0x1E, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x65, 0x5E, 0x59, 0x22, 0xCC, 0x72, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x93, 0x1A, 0x27, 0x1E, 0x34, 0xC5, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xF2, 0xA5, 0x58, 0x5C, 0x15, 0x2E, 0xC6),
+};
+static const mbedtls_mpi_uint secp256r1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x7F, 0xBA, 0x58, 0x5A, 0x84, 0x6F, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA6, 0x36, 0x7E, 0xDC, 0xF7, 0xE1, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x4D, 0xAA, 0xEE, 0x57, 0x76, 0x3A, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x7E, 0x26, 0x18, 0x22, 0x23, 0x9F, 0xFF),
+};
+static const mbedtls_mpi_uint secp256r1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x4C, 0x64, 0xC7, 0x55, 0x02, 0x3F, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x02, 0x90, 0xBB, 0xC3, 0xEC, 0x30, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x6F, 0x64, 0xF4, 0x16, 0x69, 0x48, 0xA4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x44, 0x9C, 0x95, 0x0C, 0x7D, 0x67, 0x5E),
+};
+static const mbedtls_mpi_uint secp256r1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x91, 0x8B, 0xD8, 0xD0, 0xD7, 0xE7, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF9, 0x48, 0x62, 0x6F, 0xA8, 0x93, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x3A, 0x99, 0x02, 0xD5, 0x0B, 0x3D, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xD3, 0x00, 0x31, 0xE6, 0x0C, 0x9F, 0x44),
+};
+static const mbedtls_mpi_uint secp256r1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xB2, 0xAA, 0xFD, 0x88, 0x15, 0xDF, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0x35, 0x27, 0x31, 0x44, 0xCD, 0xC0, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xF8, 0x91, 0xA5, 0x71, 0x94, 0x84, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xCB, 0xD0, 0x93, 0xE9, 0x88, 0xDA, 0xE4),
+};
+static const mbedtls_mpi_uint secp256r1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC6, 0x39, 0x16, 0x5D, 0xA3, 0x1E, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x07, 0x37, 0x26, 0x36, 0x2A, 0xFE, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xBC, 0xF3, 0xD0, 0xDE, 0x50, 0xFC, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x2E, 0x06, 0x10, 0x15, 0x4D, 0xFA, 0xF7),
+};
+static const mbedtls_mpi_uint secp256r1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x65, 0x69, 0x5B, 0x66, 0xA2, 0x75, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x16, 0x00, 0x5A, 0xB0, 0x30, 0x25, 0x1A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xFB, 0x86, 0x42, 0x80, 0xC1, 0xC4, 0x76),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x1D, 0x83, 0x8E, 0x94, 0x01, 0x5F, 0x82),
+};
+static const mbedtls_mpi_uint secp256r1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x37, 0x70, 0xEF, 0x1F, 0xA1, 0xF0, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x5B, 0xCE, 0xC4, 0x9B, 0x6F, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x11, 0x11, 0x24, 0x4F, 0x4C, 0x79, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x3A, 0x72, 0xBC, 0xFE, 0x72, 0x58, 0x43),
+};
+static const mbedtls_ecp_point secp256r1_T[16] = {
+    ECP_POINT_INIT_XY_Z1(secp256r1_T_0_X, secp256r1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_1_X, secp256r1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_2_X, secp256r1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_3_X, secp256r1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_4_X, secp256r1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_5_X, secp256r1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_6_X, secp256r1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_7_X, secp256r1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_8_X, secp256r1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_9_X, secp256r1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_10_X, secp256r1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_11_X, secp256r1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_12_X, secp256r1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_13_X, secp256r1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_14_X, secp256r1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_15_X, secp256r1_T_15_Y),
+};
+#else
+#define secp256r1_T NULL
+#endif
+
+#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+
+/*
+ * Domain parameters for secp384r1
+ */
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+static const mbedtls_mpi_uint secp384r1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+static const mbedtls_mpi_uint secp384r1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3),
+};
+static const mbedtls_mpi_uint secp384r1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA),
+};
+static const mbedtls_mpi_uint secp384r1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36),
+};
+static const mbedtls_mpi_uint secp384r1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint secp384r1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA),
+};
+static const mbedtls_mpi_uint secp384r1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36),
+};
+static const mbedtls_mpi_uint secp384r1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x92, 0x00, 0x2C, 0x78, 0xDB, 0x1F, 0x37),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF3, 0xEB, 0xB7, 0x06, 0xF7, 0xB6, 0xBC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBC, 0x2C, 0xCF, 0xD8, 0xED, 0x53, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x75, 0x7B, 0xA3, 0xAB, 0xC3, 0x2C, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x9D, 0x78, 0x41, 0xF6, 0x76, 0x84, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x56, 0xE8, 0x52, 0xB3, 0xCB, 0xA8, 0xBD),
+};
+static const mbedtls_mpi_uint secp384r1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xF2, 0xAE, 0xA4, 0xB6, 0x89, 0x1B, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0xCE, 0x1C, 0x7C, 0xF6, 0x50, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xEB, 0x90, 0xE6, 0x4D, 0xC7, 0xD4, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x49, 0x2D, 0x8A, 0x01, 0x99, 0x60, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x80, 0x9B, 0x9B, 0x6A, 0xB0, 0x07, 0xD9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xA2, 0xEE, 0x59, 0xBE, 0x95, 0xBC, 0x23),
+};
+static const mbedtls_mpi_uint secp384r1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x9D, 0x56, 0xAE, 0x59, 0xFB, 0x1F, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xAC, 0x91, 0x80, 0x87, 0xA8, 0x6E, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x08, 0xA7, 0x08, 0x94, 0x32, 0xFC, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x29, 0x9E, 0x84, 0xF4, 0xE5, 0x6E, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x21, 0xB9, 0x50, 0x24, 0xF8, 0x9C, 0xC7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x04, 0x01, 0xC2, 0xFB, 0x77, 0x3E, 0xDE),
+};
+static const mbedtls_mpi_uint secp384r1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x38, 0xEE, 0xE3, 0xC7, 0x9D, 0xEC, 0xA6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x88, 0xCF, 0x43, 0xFA, 0x92, 0x5E, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xCA, 0x43, 0xF8, 0x3B, 0x49, 0x7E, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xE7, 0xEB, 0x17, 0x45, 0x86, 0xC2, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x69, 0x57, 0x32, 0xE0, 0x9C, 0xD1, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x10, 0xB8, 0x4D, 0xB8, 0xF4, 0x0D, 0xE3),
+};
+static const mbedtls_mpi_uint secp384r1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0xDC, 0x9A, 0xB2, 0x79, 0x39, 0x27, 0x16),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x71, 0xE4, 0x3B, 0x4D, 0x60, 0x0C, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xBD, 0x19, 0x40, 0xFA, 0x19, 0x2A, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xF8, 0x1E, 0x43, 0xA1, 0x50, 0x8D, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x18, 0x7C, 0x41, 0xFA, 0x7C, 0x1B, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x24, 0xC4, 0xE9, 0xB7, 0xD3, 0xAD),
+};
+static const mbedtls_mpi_uint secp384r1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x01, 0x3D, 0x63, 0x54, 0x45, 0x6F, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xB2, 0x19, 0xA3, 0x86, 0x1D, 0x42, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x02, 0x87, 0x18, 0x92, 0x52, 0x1A, 0x71),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x18, 0xB1, 0x5D, 0x18, 0x1B, 0x37, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x74, 0x61, 0xBA, 0x18, 0xAF, 0x40, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7D, 0x3C, 0x52, 0x0F, 0x07, 0xB0, 0x6F),
+};
+static const mbedtls_mpi_uint secp384r1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x39, 0x13, 0xAA, 0x60, 0x15, 0x99, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x00, 0xCB, 0xC6, 0xB1, 0xDB, 0x97, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xFA, 0x60, 0xB8, 0x24, 0xE4, 0x7D, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x75, 0xB3, 0x70, 0xB2, 0x83, 0xB1, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xE3, 0x6C, 0xCD, 0x33, 0x62, 0x7A, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x30, 0xDC, 0x0F, 0x9F, 0xBB, 0xB8, 0xAA),
+};
+static const mbedtls_mpi_uint secp384r1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD5, 0x0A, 0x60, 0x81, 0xB9, 0xC5, 0x16),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xAA, 0x2F, 0xD6, 0xF2, 0x73, 0xDF, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x7B, 0x74, 0xC9, 0xB3, 0x5B, 0x95, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x04, 0xEB, 0x15, 0xC8, 0x5F, 0x00, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x50, 0x20, 0x28, 0xD1, 0x01, 0xAF, 0xF0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x4F, 0x31, 0x81, 0x2F, 0x94, 0x48),
+};
+static const mbedtls_mpi_uint secp384r1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2F, 0xD8, 0xB6, 0x63, 0x7C, 0xE9, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x8C, 0xB9, 0x14, 0xD9, 0x37, 0x63, 0xDE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x02, 0xB8, 0x46, 0xAD, 0xCE, 0x7B, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x47, 0x2D, 0x66, 0xA7, 0xE9, 0x33, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF9, 0x93, 0x94, 0xA8, 0x48, 0xB3, 0x4F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x4A, 0xAC, 0x51, 0x08, 0x72, 0x2F, 0x1A),
+};
+static const mbedtls_mpi_uint secp384r1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xAD, 0xA0, 0xF9, 0x81, 0xE1, 0x78, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9A, 0x63, 0xD8, 0xBA, 0x79, 0x1A, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x31, 0x7B, 0x7A, 0x5A, 0x5D, 0x7D, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x96, 0x12, 0x4B, 0x19, 0x09, 0xE0, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8A, 0x57, 0xEE, 0x4E, 0x6E, 0x7E, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x9D, 0x69, 0xDC, 0xB3, 0xDA, 0xD8, 0x08),
+};
+static const mbedtls_mpi_uint secp384r1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x49, 0x03, 0x03, 0x33, 0x6F, 0x28, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xDB, 0xA7, 0x05, 0x8C, 0xF3, 0x4D, 0xFB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x92, 0xB1, 0xA8, 0xEC, 0x0D, 0x64, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0xFC, 0xFD, 0xD0, 0x4B, 0x88, 0x1B, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x9C, 0x51, 0x69, 0xCE, 0x71, 0x73, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5A, 0x14, 0x23, 0x1A, 0x46, 0x63, 0x5F),
+};
+static const mbedtls_mpi_uint secp384r1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x4C, 0x70, 0x44, 0x18, 0xCD, 0xEF, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x49, 0xDD, 0x64, 0x7E, 0x7E, 0x4D, 0x92),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x32, 0x7C, 0x09, 0xD0, 0x3F, 0xD6, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE0, 0x4F, 0x65, 0x0C, 0x7A, 0x54, 0x3E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFA, 0xFB, 0x4A, 0xB4, 0x79, 0x5A, 0x8C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x1B, 0x2B, 0xDA, 0xBC, 0x9A, 0x74),
+};
+static const mbedtls_mpi_uint secp384r1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xAC, 0x56, 0xF7, 0x5F, 0x51, 0x68, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xE0, 0x1D, 0xBC, 0x13, 0x4E, 0xAC, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF5, 0xC5, 0xE6, 0xD2, 0x88, 0xBA, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x0E, 0x28, 0x23, 0x58, 0x67, 0xFA, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x80, 0x4B, 0xD8, 0xC4, 0xDF, 0x15, 0xE4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x0E, 0x58, 0xE6, 0x2C, 0x59, 0xC2, 0x03),
+};
+static const mbedtls_mpi_uint secp384r1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x26, 0x27, 0x99, 0x16, 0x2B, 0x22, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF3, 0x8F, 0xC3, 0x2A, 0x9B, 0xFC, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2E, 0x83, 0x3D, 0xFE, 0x9E, 0x3C, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0xCD, 0x2D, 0xC1, 0x49, 0x38, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x42, 0x8B, 0x33, 0x89, 0x1F, 0xEA, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x1D, 0x13, 0xD7, 0x50, 0xBB, 0x3E, 0xEB),
+};
+static const mbedtls_mpi_uint secp384r1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x9A, 0x52, 0xD2, 0x54, 0x7C, 0x97, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x6E, 0xED, 0xD9, 0x87, 0x50, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x35, 0x7E, 0x16, 0x40, 0x15, 0x83, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x2B, 0xA4, 0xAB, 0x03, 0x91, 0xEA, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x47, 0x39, 0xEF, 0x05, 0x59, 0xD0, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x24, 0x0D, 0x76, 0x11, 0x53, 0x08, 0xAF),
+};
+static const mbedtls_mpi_uint secp384r1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x2F, 0xDD, 0xBD, 0x50, 0x48, 0xB1, 0xE5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x1C, 0x84, 0x55, 0x78, 0x14, 0xEB, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x5E, 0x3E, 0xA6, 0xAF, 0xF6, 0xC7, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x11, 0xE2, 0x65, 0xCA, 0x41, 0x95, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x83, 0xD8, 0xE6, 0x4D, 0x22, 0x06, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x7F, 0x25, 0x2A, 0xAA, 0x28, 0x46, 0x97),
+};
+static const mbedtls_mpi_uint secp384r1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xDB, 0x15, 0x56, 0x84, 0xCB, 0xC0, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xDB, 0x0E, 0x08, 0xC9, 0xF5, 0xD4, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x62, 0xD0, 0x1A, 0x7C, 0x13, 0xD5, 0x07),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xAD, 0x53, 0xE0, 0x32, 0x21, 0xA0, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x38, 0x81, 0x21, 0x23, 0x0E, 0xD2, 0xBB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x51, 0x05, 0xD0, 0x1E, 0x82, 0xA9, 0x71),
+};
+static const mbedtls_mpi_uint secp384r1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xC3, 0x27, 0xBF, 0xC6, 0xAA, 0xB7, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x65, 0x45, 0xDF, 0xB9, 0x46, 0x17, 0x46),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x38, 0x3F, 0xB2, 0xB1, 0x5D, 0xCA, 0x1C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x29, 0x6C, 0x63, 0xE9, 0xD7, 0x48, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xF1, 0xD7, 0x99, 0x8C, 0xC2, 0x05, 0x99),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE6, 0x5E, 0x82, 0x6D, 0xE5, 0x7E, 0xD5),
+};
+static const mbedtls_mpi_uint secp384r1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x61, 0xFA, 0x7D, 0x01, 0xDB, 0xB6, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC6, 0x58, 0x39, 0xF4, 0xC6, 0x82, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0x7A, 0x80, 0x08, 0xCD, 0xAA, 0xD8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x8C, 0xC6, 0x3F, 0x3C, 0xA5, 0x68, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xF5, 0xD5, 0x17, 0xAE, 0x36, 0xD8, 0x8A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xAD, 0x92, 0xC5, 0x57, 0x6C, 0xDA, 0x91),
+};
+static const mbedtls_mpi_uint secp384r1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x67, 0x17, 0xC0, 0x40, 0x78, 0x8C, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x9F, 0xF4, 0xAA, 0xDA, 0x5C, 0x7E, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xDB, 0x42, 0x3E, 0x72, 0x64, 0xA0, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xF9, 0x41, 0x17, 0x43, 0xE3, 0xE8, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xDD, 0xCC, 0x43, 0x7E, 0x16, 0x05, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x4B, 0xCF, 0x48, 0x8F, 0x41, 0x90, 0xE5),
+};
+static const mbedtls_mpi_uint secp384r1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x0C, 0x6B, 0x9D, 0x22, 0x04, 0xBC, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x63, 0x79, 0x2F, 0x6A, 0x0E, 0x8A, 0xDE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x67, 0x3F, 0x02, 0xB8, 0x91, 0x7F, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x14, 0x64, 0xA0, 0x33, 0xF4, 0x6B, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x44, 0x71, 0x87, 0xB8, 0x88, 0x3F, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x2B, 0x85, 0x05, 0xC5, 0x44, 0x53, 0x15),
+};
+static const mbedtls_mpi_uint secp384r1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x2B, 0xFE, 0xD1, 0x1C, 0x73, 0xE3, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x33, 0xA1, 0xD3, 0x69, 0x1C, 0x9D, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x5A, 0xBA, 0xB6, 0xAE, 0x1B, 0x94, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x74, 0x90, 0x5C, 0x57, 0xB0, 0x3A, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x2F, 0x93, 0x20, 0x24, 0x54, 0x1D, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x78, 0x9D, 0x71, 0x67, 0x5D, 0x49, 0x98),
+};
+static const mbedtls_mpi_uint secp384r1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xC8, 0x0E, 0x11, 0x8D, 0xE0, 0x8F, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x7F, 0x79, 0x6C, 0x5F, 0xB7, 0xBC, 0xB1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xE1, 0x83, 0x3C, 0x12, 0xBB, 0xEE, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC2, 0xC4, 0x1B, 0x41, 0x71, 0xB9, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0xEE, 0xBB, 0x1D, 0x89, 0x50, 0x88, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x1C, 0x55, 0x74, 0xEB, 0xDE, 0x92, 0x3F),
+};
+static const mbedtls_mpi_uint secp384r1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x38, 0x92, 0x06, 0x19, 0xD0, 0xB3, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x99, 0x26, 0xA3, 0x5F, 0xE2, 0xC1, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xFC, 0xFD, 0xC3, 0xB6, 0x26, 0x24, 0x8F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xAD, 0xE7, 0x49, 0xB7, 0x64, 0x4B, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x4E, 0x95, 0xAD, 0x07, 0xFE, 0xB6, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x15, 0xE7, 0x2D, 0x19, 0xA9, 0x08, 0x10),
+};
+static const mbedtls_mpi_uint secp384r1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xBD, 0xAC, 0x0A, 0x3F, 0x6B, 0xFF, 0xFA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xE4, 0x74, 0x14, 0xD9, 0x70, 0x1D, 0x71),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xB0, 0x71, 0xBB, 0xD8, 0x18, 0x96, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xB8, 0x19, 0x90, 0x80, 0xB5, 0xEE, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x21, 0x20, 0xA6, 0x17, 0x48, 0x03, 0x6F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0xBB, 0x6D, 0x94, 0x20, 0x34, 0xF1),
+};
+static const mbedtls_mpi_uint secp384r1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x82, 0x67, 0x4B, 0x8E, 0x4E, 0xBE, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xDA, 0x77, 0xF8, 0x23, 0x55, 0x2B, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x02, 0xDE, 0x25, 0x35, 0x2D, 0x74, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0C, 0xB8, 0x0B, 0x39, 0xBA, 0xAD, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x0E, 0x28, 0x4D, 0xE1, 0x3D, 0xE4, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xEC, 0x0A, 0xD4, 0xB8, 0xC4, 0x8D, 0xB0),
+};
+static const mbedtls_mpi_uint secp384r1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x68, 0xCE, 0xC2, 0x55, 0x4D, 0x0C, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x20, 0x93, 0x32, 0x90, 0xD6, 0xAE, 0x47),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x78, 0xAB, 0x43, 0x9E, 0xEB, 0x73, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x97, 0xC3, 0x83, 0xA6, 0x3C, 0xF1, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x25, 0x25, 0x66, 0x08, 0x26, 0xFA, 0x4B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xFB, 0x44, 0x5D, 0x82, 0xEC, 0x3B, 0xAC),
+};
+static const mbedtls_mpi_uint secp384r1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x90, 0xEA, 0xB5, 0x04, 0x99, 0xD0, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0xF2, 0x22, 0xA0, 0xEB, 0xFD, 0x45, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA4, 0x81, 0x32, 0xFC, 0xFA, 0xEE, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xBB, 0xA4, 0x6A, 0x77, 0x41, 0x5C, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x1E, 0xAA, 0x4F, 0xF0, 0x10, 0xB3, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x74, 0x13, 0x14, 0x9E, 0x90, 0xD7, 0xE6),
+};
+static const mbedtls_mpi_uint secp384r1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xBD, 0x70, 0x4F, 0xA8, 0xD1, 0x06, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4E, 0x2E, 0x68, 0xFC, 0x35, 0xFA, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x53, 0x75, 0xED, 0xF2, 0x5F, 0xC2, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x87, 0x6B, 0x9F, 0x05, 0xE2, 0x22, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x1A, 0xA8, 0xB7, 0x03, 0x9E, 0x6D, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD0, 0x69, 0x88, 0xA8, 0x39, 0x9E, 0x3A),
+};
+static const mbedtls_mpi_uint secp384r1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xEF, 0x68, 0xFE, 0xEC, 0x24, 0x08, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x4B, 0x92, 0x0D, 0xB7, 0x34, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF4, 0xDD, 0x1A, 0xA0, 0x4A, 0xE4, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x63, 0x4F, 0x4F, 0xCE, 0xBB, 0xD6, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xEE, 0x8D, 0xDF, 0x3F, 0x73, 0xB7, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x06, 0xB6, 0x80, 0x4D, 0x81, 0xD9, 0x53),
+};
+static const mbedtls_mpi_uint secp384r1_T_16_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF5, 0x13, 0xDF, 0x13, 0x19, 0x97, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xF9, 0xB3, 0x33, 0x66, 0x82, 0x21, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xFC, 0x39, 0x16, 0x23, 0x43, 0x76, 0x0E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x48, 0x25, 0xA1, 0x64, 0x95, 0x1C, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xAC, 0x15, 0x57, 0xD9, 0xDE, 0xA0, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x5F, 0xB8, 0x3D, 0x48, 0x91, 0x24, 0xCC),
+};
+static const mbedtls_mpi_uint secp384r1_T_16_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xF2, 0xC8, 0x54, 0xD1, 0x32, 0xBD, 0xC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x3B, 0xF0, 0xAA, 0x9D, 0xD8, 0xF4, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xC3, 0xBB, 0x6C, 0x66, 0xAC, 0x25, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x25, 0x10, 0xB2, 0xE1, 0x41, 0xDE, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xE8, 0x30, 0xB8, 0x37, 0xBC, 0x2A, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x57, 0x01, 0x4A, 0x1E, 0x78, 0x9F, 0x85),
+};
+static const mbedtls_mpi_uint secp384r1_T_17_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x19, 0xCD, 0x12, 0x0B, 0x51, 0x4F, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x4B, 0x3D, 0x24, 0xA4, 0x16, 0x59, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xEB, 0xD3, 0x59, 0x2E, 0x75, 0x7C, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB9, 0xB4, 0xA5, 0xD9, 0x2E, 0x29, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x16, 0x05, 0x75, 0x02, 0xB3, 0x06, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x7C, 0x9F, 0x79, 0x91, 0xF1, 0x4F, 0x23),
+};
+static const mbedtls_mpi_uint secp384r1_T_17_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x98, 0x7C, 0x84, 0xE1, 0xFF, 0x30, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE2, 0xC2, 0x5F, 0x55, 0x40, 0xBD, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x65, 0x87, 0x3F, 0xC4, 0xC2, 0x24, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x30, 0x0A, 0x60, 0x15, 0xD1, 0x24, 0x48),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x99, 0xD9, 0xB6, 0xAE, 0xB1, 0xAF, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x80, 0xEE, 0xA2, 0x0F, 0x74, 0xB9, 0xF3),
+};
+static const mbedtls_mpi_uint secp384r1_T_18_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xE6, 0x0F, 0x37, 0xC1, 0x10, 0x99, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xAD, 0x9D, 0x5D, 0x80, 0x01, 0xA6, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x0F, 0x10, 0x2A, 0x9D, 0x20, 0x38, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x60, 0xCB, 0xCE, 0x5A, 0xA0, 0xA7, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xCF, 0x14, 0xDF, 0xBF, 0xE5, 0x74, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x12, 0x1A, 0xDD, 0x59, 0x02, 0x5D, 0xC6),
+};
+static const mbedtls_mpi_uint secp384r1_T_18_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0xF8, 0xF5, 0xB6, 0x13, 0x4D, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x45, 0xB1, 0x93, 0xB3, 0xA2, 0x79, 0xDC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xF6, 0xCF, 0xF7, 0xE6, 0x29, 0x9C, 0xCC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x50, 0x65, 0x80, 0xBC, 0x59, 0x0A, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xF0, 0x24, 0x35, 0xA2, 0x46, 0xF0, 0x0C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x26, 0xC0, 0x9D, 0x61, 0x56, 0x62, 0x67),
+};
+static const mbedtls_mpi_uint secp384r1_T_19_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xBB, 0xC2, 0x24, 0x43, 0x2E, 0x37, 0x54),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xF7, 0xCE, 0x35, 0xFC, 0x77, 0xF3, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x34, 0x96, 0xD5, 0x4A, 0x76, 0x9D, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x3B, 0x0F, 0xEA, 0xA8, 0x12, 0x0B, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x3F, 0x5D, 0x2D, 0x1C, 0xD4, 0x9E, 0xFB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x2E, 0xDD, 0xC7, 0x6E, 0xAB, 0xAF, 0xDC),
+};
+static const mbedtls_mpi_uint secp384r1_T_19_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB2, 0x7B, 0x0C, 0x9A, 0x83, 0x8E, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x51, 0x90, 0x92, 0x79, 0x32, 0x19, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x89, 0xF9, 0xD0, 0xCF, 0x2C, 0xA5, 0x8F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x50, 0x21, 0xDE, 0x50, 0x41, 0x9D, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x7D, 0x2B, 0x9E, 0x9D, 0x95, 0xA8, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA5, 0x20, 0x87, 0x88, 0x97, 0x5F, 0xAA),
+};
+static const mbedtls_mpi_uint secp384r1_T_20_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x59, 0xB4, 0x66, 0x7E, 0xE8, 0x5A, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x5C, 0x7E, 0xB2, 0xAD, 0xD9, 0xC9, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x97, 0x49, 0xA3, 0x13, 0x83, 0x07, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x26, 0xC7, 0x13, 0x35, 0x0D, 0xB0, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x60, 0xAB, 0xFA, 0x4B, 0x93, 0x18, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2D, 0x1C, 0x31, 0x4C, 0xE4, 0x61, 0xAE),
+};
+static const mbedtls_mpi_uint secp384r1_T_20_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x4D, 0x1E, 0x51, 0x59, 0x6E, 0x91, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x54, 0x4D, 0x51, 0xED, 0x36, 0xCC, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xA8, 0x56, 0xC7, 0x78, 0x27, 0x33, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB7, 0x95, 0xC9, 0x8B, 0xC8, 0x6A, 0xBC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xE9, 0x13, 0x96, 0xB3, 0xE1, 0xF9, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x46, 0xB0, 0x5E, 0xC3, 0x94, 0x03, 0x05),
+};
+static const mbedtls_mpi_uint secp384r1_T_21_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x5B, 0x29, 0x30, 0x41, 0x1A, 0x9E, 0xB6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xCA, 0x83, 0x31, 0x5B, 0xA7, 0xCB, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x41, 0x50, 0x44, 0x4D, 0x64, 0x31, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x84, 0xC2, 0x5D, 0x97, 0xA5, 0x3C, 0x18),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x0F, 0xA5, 0xFD, 0x8E, 0x5A, 0x47, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x58, 0x02, 0x2D, 0x40, 0xB1, 0x0B, 0xBA),
+};
+static const mbedtls_mpi_uint secp384r1_T_21_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x33, 0x8C, 0x67, 0xCE, 0x23, 0x43, 0x99),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x53, 0x47, 0x72, 0x44, 0x1F, 0x5B, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xC1, 0xD9, 0xA4, 0x50, 0x88, 0x63, 0x18),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xF2, 0x75, 0x69, 0x73, 0x00, 0xC4, 0x31),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x90, 0x1D, 0xDF, 0x1A, 0x00, 0xD8, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xB1, 0x89, 0x48, 0xA8, 0x70, 0x62, 0xEF),
+};
+static const mbedtls_mpi_uint secp384r1_T_22_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x8A, 0x55, 0x50, 0x7B, 0xEF, 0x8A, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1B, 0x23, 0x48, 0x23, 0x63, 0x91, 0xB6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x04, 0x54, 0x3C, 0x24, 0x9B, 0xC7, 0x9A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x38, 0xC3, 0x84, 0xFB, 0xFF, 0x9F, 0x49),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x2A, 0xE0, 0x6D, 0x68, 0x8A, 0x5C, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x93, 0x53, 0x85, 0xA1, 0x0D, 0xAF, 0x63),
+};
+static const mbedtls_mpi_uint secp384r1_T_22_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x88, 0x95, 0x4C, 0x0B, 0xD0, 0x06, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xAF, 0x8D, 0x49, 0xA2, 0xC8, 0xB4, 0xE0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x76, 0x53, 0x09, 0x88, 0x43, 0x87, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA4, 0x77, 0x3F, 0x5E, 0x21, 0xB4, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x9E, 0x86, 0x64, 0xCC, 0x91, 0xC1, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x17, 0x56, 0xCB, 0xC3, 0x7D, 0x5B, 0xB1),
+};
+static const mbedtls_mpi_uint secp384r1_T_23_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x74, 0x9F, 0xB5, 0x91, 0x21, 0xB1, 0x1C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xED, 0xE1, 0x11, 0xEF, 0x45, 0xAF, 0xC1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x31, 0xBE, 0xB2, 0xBC, 0x72, 0x65, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x4B, 0x8C, 0x77, 0xCE, 0x1E, 0x42, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC9, 0xAA, 0xB9, 0xD9, 0x86, 0x99, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x23, 0x80, 0xC6, 0x4E, 0x35, 0x0B, 0x6D),
+};
+static const mbedtls_mpi_uint secp384r1_T_23_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xD8, 0xA2, 0x0A, 0x39, 0x32, 0x1D, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xC8, 0x86, 0xF1, 0x12, 0x9A, 0x4A, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xF1, 0x7C, 0xAA, 0x70, 0x8E, 0xBC, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x01, 0x47, 0x8F, 0xDD, 0x8B, 0xA5, 0xC8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x08, 0x21, 0xF4, 0xAB, 0xC7, 0xF5, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x76, 0xA5, 0x95, 0xC4, 0x0F, 0x88, 0x1D),
+};
+static const mbedtls_mpi_uint secp384r1_T_24_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x42, 0x2A, 0x52, 0xCD, 0x75, 0x51, 0x49),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x36, 0xE5, 0x04, 0x2B, 0x44, 0xC6, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xEE, 0x16, 0x13, 0x07, 0x83, 0xB5, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x59, 0xC6, 0xA2, 0x19, 0x05, 0xD3, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8B, 0xA8, 0x16, 0x09, 0xB7, 0xEA, 0xD6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xEE, 0x14, 0xAF, 0xB5, 0xFD, 0xD0, 0xEF),
+};
+static const mbedtls_mpi_uint secp384r1_T_24_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x7C, 0xCA, 0x71, 0x3E, 0x6E, 0x66, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x31, 0x0E, 0x3F, 0xE5, 0x91, 0xC4, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x3D, 0xC2, 0x3E, 0x95, 0x37, 0x58, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x1F, 0x02, 0x03, 0xF3, 0xEF, 0xEE, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x5B, 0x1A, 0xFC, 0x38, 0xCD, 0xE8, 0x24),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x57, 0x42, 0x85, 0xC6, 0x21, 0x68, 0x71),
+};
+static const mbedtls_mpi_uint secp384r1_T_25_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA2, 0x4A, 0x66, 0xB1, 0x0A, 0xE6, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x0C, 0x94, 0x9D, 0x5E, 0x99, 0xB2, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x03, 0x40, 0xCA, 0xB2, 0xB3, 0x30, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0x48, 0x27, 0x34, 0x1E, 0xE2, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x72, 0x5B, 0xAC, 0xC1, 0x6D, 0xE3, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAB, 0x46, 0xCB, 0xEA, 0x5E, 0x4B, 0x0B),
+};
+static const mbedtls_mpi_uint secp384r1_T_25_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x08, 0xAD, 0x4E, 0x51, 0x9F, 0x2A, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5C, 0x7D, 0x4C, 0xD6, 0xCF, 0xDD, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x76, 0x26, 0xE0, 0x8B, 0x10, 0xD9, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA7, 0x23, 0x4E, 0x5F, 0xD2, 0x42, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xE5, 0xA4, 0xEC, 0x77, 0x21, 0x34, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x14, 0x65, 0xEA, 0x4A, 0x85, 0xC3, 0x2F),
+};
+static const mbedtls_mpi_uint secp384r1_T_26_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xD8, 0x40, 0x27, 0x73, 0x15, 0x7E, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xBB, 0x53, 0x7E, 0x0F, 0x40, 0xC8, 0xD4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x37, 0x19, 0x73, 0xEF, 0x5A, 0x5E, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x73, 0x2B, 0x49, 0x7E, 0xAC, 0x97, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xB2, 0xC3, 0x1E, 0x0E, 0xE7, 0xD2, 0x21),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x08, 0xD6, 0xDD, 0xAC, 0x21, 0xD6, 0x3E),
+};
+static const mbedtls_mpi_uint secp384r1_T_26_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x26, 0xBE, 0x6D, 0x6D, 0xF2, 0x38, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6C, 0x31, 0xA7, 0x49, 0x50, 0x3A, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x99, 0xC6, 0xF5, 0xD2, 0xC2, 0x30, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE4, 0xF6, 0x8B, 0x8B, 0x97, 0xE9, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x21, 0xB7, 0x0D, 0xFC, 0x15, 0x54, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x83, 0x1C, 0xA4, 0xCD, 0x6B, 0x9D, 0xF2),
+};
+static const mbedtls_mpi_uint secp384r1_T_27_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE8, 0x4C, 0x48, 0xE4, 0xAA, 0x69, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x7A, 0x27, 0xFC, 0x37, 0x96, 0x1A, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xE7, 0x30, 0xA5, 0xCF, 0x13, 0x46, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xD8, 0xAF, 0x74, 0x23, 0x4D, 0x56, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3D, 0x44, 0x14, 0x1B, 0x97, 0x83, 0xF0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x47, 0xD7, 0x5F, 0xFD, 0x98, 0x38, 0xF7),
+};
+static const mbedtls_mpi_uint secp384r1_T_27_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x73, 0x64, 0x36, 0xFD, 0x7B, 0xC1, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x5D, 0x32, 0xD2, 0x47, 0x94, 0x89, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xE9, 0x30, 0xAC, 0x06, 0xC8, 0x65, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x6C, 0xB9, 0x1B, 0xF7, 0x61, 0x49, 0x53),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xFF, 0x32, 0x43, 0x80, 0xDA, 0xA6, 0xB1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF8, 0x04, 0x01, 0x95, 0x35, 0xCE, 0x21),
+};
+static const mbedtls_mpi_uint secp384r1_T_28_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x06, 0x46, 0x0D, 0x51, 0xE2, 0xD8, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x57, 0x1D, 0x6F, 0x79, 0xA0, 0xCD, 0xA6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xFB, 0x36, 0xCA, 0xAD, 0xF5, 0x9E, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x7A, 0x1D, 0x9E, 0x1D, 0x95, 0x48, 0xDC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x26, 0xA5, 0xB7, 0x15, 0x2C, 0xC2, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x42, 0x72, 0xAA, 0x11, 0xDC, 0xC9, 0xB6),
+};
+static const mbedtls_mpi_uint secp384r1_T_28_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x6C, 0x64, 0xA7, 0x62, 0x3C, 0xAB, 0xD4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x6A, 0x44, 0xD8, 0x60, 0xC0, 0xA8, 0x80),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x76, 0x58, 0x12, 0x57, 0x3C, 0x89, 0x46),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x4F, 0x83, 0xCE, 0xCB, 0xB8, 0xD0, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0x04, 0xB0, 0xAD, 0xEB, 0xFA, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA4, 0xC3, 0x41, 0x44, 0x4E, 0x65, 0x3E),
+};
+static const mbedtls_mpi_uint secp384r1_T_29_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x16, 0xA9, 0x1C, 0xE7, 0x65, 0x20, 0xC1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x53, 0x32, 0xF8, 0xC0, 0xA6, 0xBD, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF0, 0xE6, 0x57, 0x31, 0xCC, 0x26, 0x6F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xE3, 0x54, 0x1C, 0x34, 0xD3, 0x17, 0xBC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xAE, 0xED, 0xFB, 0xCD, 0xE7, 0x1E, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x16, 0x1C, 0x34, 0x40, 0x00, 0x1F, 0xB6),
+};
+static const mbedtls_mpi_uint secp384r1_T_29_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x32, 0x00, 0xC2, 0xD4, 0x3B, 0x1A, 0x09),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xE0, 0x99, 0x8F, 0x0C, 0x4A, 0x16, 0x44),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x73, 0x18, 0x1B, 0xD4, 0x94, 0x29, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA4, 0x2D, 0xB1, 0x9D, 0x74, 0x32, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xF4, 0xB1, 0x0C, 0x37, 0x62, 0x8B, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xFF, 0xDA, 0xE2, 0x35, 0xA3, 0xB6, 0x42),
+};
+static const mbedtls_mpi_uint secp384r1_T_30_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x49, 0x99, 0x65, 0xC5, 0xED, 0x16, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x42, 0x9A, 0xF3, 0xA7, 0x4E, 0x6F, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x0A, 0x7E, 0xC0, 0xD7, 0x4E, 0x07, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x7A, 0x31, 0x69, 0xA6, 0xB9, 0x15, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xE0, 0x72, 0xA4, 0x3F, 0xB9, 0xF8, 0x0C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x75, 0x32, 0x85, 0xA2, 0xDE, 0x37, 0x12),
+};
+static const mbedtls_mpi_uint secp384r1_T_30_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC0, 0x0D, 0xCF, 0x25, 0x41, 0xA4, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xFC, 0xB2, 0x48, 0xC3, 0x85, 0x83, 0x4B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBE, 0x0B, 0x58, 0x2D, 0x7A, 0x9A, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xF3, 0x81, 0x18, 0x1B, 0x74, 0x4F, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x43, 0xA3, 0x0A, 0x16, 0x8B, 0xA3, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x18, 0x81, 0x7B, 0x8D, 0xA2, 0x35, 0x77),
+};
+static const mbedtls_mpi_uint secp384r1_T_31_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xC4, 0x3F, 0x2C, 0xE7, 0x5F, 0x99, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2B, 0xB7, 0xB6, 0xAD, 0x5A, 0x56, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x00, 0xA4, 0x48, 0xC8, 0xE8, 0xBA, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xA1, 0xB5, 0x13, 0x5A, 0xCD, 0x99, 0x9C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x95, 0xAD, 0xFC, 0xE2, 0x7E, 0xE7, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x6B, 0xD1, 0x34, 0x99, 0x53, 0x63, 0x0B),
+};
+static const mbedtls_mpi_uint secp384r1_T_31_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x8A, 0x77, 0x5D, 0x2B, 0xAB, 0x01, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x85, 0xD0, 0xD5, 0x49, 0x83, 0x4D, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xC6, 0x91, 0x30, 0x3B, 0x00, 0xAF, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x61, 0x07, 0xE1, 0xB6, 0xE2, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x43, 0x41, 0xFE, 0x9B, 0xB6, 0xF0, 0xA5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x97, 0xAE, 0xAD, 0x89, 0x88, 0x9E, 0x41),
+};
+static const mbedtls_ecp_point secp384r1_T[32] = {
+    ECP_POINT_INIT_XY_Z1(secp384r1_T_0_X, secp384r1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_1_X, secp384r1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_2_X, secp384r1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_3_X, secp384r1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_4_X, secp384r1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_5_X, secp384r1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_6_X, secp384r1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_7_X, secp384r1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_8_X, secp384r1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_9_X, secp384r1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_10_X, secp384r1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_11_X, secp384r1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_12_X, secp384r1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_13_X, secp384r1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_14_X, secp384r1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_15_X, secp384r1_T_15_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_16_X, secp384r1_T_16_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_17_X, secp384r1_T_17_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_18_X, secp384r1_T_18_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_19_X, secp384r1_T_19_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_20_X, secp384r1_T_20_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_21_X, secp384r1_T_21_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_22_X, secp384r1_T_22_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_23_X, secp384r1_T_23_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_24_X, secp384r1_T_24_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_25_X, secp384r1_T_25_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_26_X, secp384r1_T_26_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_27_X, secp384r1_T_27_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_28_X, secp384r1_T_28_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_29_X, secp384r1_T_29_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_30_X, secp384r1_T_30_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_31_X, secp384r1_T_31_Y),
+};
+#else
+#define secp384r1_T NULL
+#endif
+
+#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+
+/*
+ * Domain parameters for secp521r1
+ */
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+static const mbedtls_mpi_uint secp521r1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01),
+};
+static const mbedtls_mpi_uint secp521r1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_2(0x51, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_2(0xC6, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_2(0x18, 0x01),
+};
+static const mbedtls_mpi_uint secp521r1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01),
+};
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint secp521r1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xB1, 0x2D, 0xEB, 0x27, 0x2F, 0xE8, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x4B, 0x44, 0x25, 0xDB, 0x5C, 0x5F, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x85, 0x28, 0x78, 0x2E, 0x75, 0x34, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x57, 0x0F, 0x73, 0x78, 0x7A, 0xE3, 0x53),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD8, 0xEC, 0xDC, 0xDA, 0x04, 0xAD, 0xAB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x8A, 0x09, 0xF3, 0x58, 0x79, 0xD8, 0x29),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x03, 0xCB, 0x50, 0x1A, 0x7F, 0x56, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA6, 0x78, 0x38, 0x85, 0x67, 0x0B, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xD5, 0xD2, 0x22, 0xC4, 0x00, 0x3B, 0xBA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x93, 0x0E, 0x7B, 0x85, 0x51, 0xC3, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA6, 0x5F, 0x54, 0x49, 0x02, 0x81, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xE9, 0x6B, 0x3A, 0x92, 0xE7, 0x72, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x5F, 0x28, 0x9E, 0x91, 0x27, 0x88, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x28, 0x31, 0xB3, 0x84, 0xCA, 0x12, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xF9, 0xAC, 0x22, 0x10, 0x0A, 0x64, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xC6, 0x33, 0x1F, 0x69, 0x19, 0x18, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x48, 0xB8, 0xC7, 0x37, 0x5A, 0x00, 0x36),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xCC, 0x32, 0xE0, 0xEE, 0x03, 0xC2, 0xBA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x29, 0xC2, 0xE4, 0x6E, 0x24, 0x20, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x6B, 0x7F, 0x7B, 0xF9, 0xB0, 0xB8, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x7B, 0x3C, 0xE1, 0x19, 0xA1, 0x23, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE3, 0xC2, 0x53, 0xC0, 0x07, 0x13, 0xA9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFE, 0x36, 0x35, 0x9F, 0x5E, 0x59, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x55, 0x89, 0x84, 0xBC, 0xEF, 0xA2, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x1A, 0x08, 0x67, 0xB4, 0xE7, 0x22, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x26, 0xDF, 0x81, 0x3C, 0x5F, 0x1C, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x4D, 0xD0, 0x0A, 0x48, 0x06, 0xF4, 0x48),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x18, 0x39, 0xF7, 0xD1, 0x20, 0x77, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x8F, 0x44, 0x13, 0xCB, 0x78, 0x11, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE2, 0x49, 0xEA, 0x43, 0x79, 0x08, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xD1, 0xD8, 0x73, 0x2C, 0x71, 0x2F, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE5, 0xE7, 0xF4, 0x46, 0xAB, 0x20, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x0B, 0xB9, 0x71, 0x1A, 0x27, 0xB7, 0xA7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xA2, 0x2C, 0xD1, 0xDA, 0xBC, 0xC1, 0xBD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xA3, 0x10, 0x1F, 0x90, 0xF2, 0xA5, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xFB, 0x20, 0xF4, 0xC0, 0x70, 0xC0, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xA7, 0x99, 0xF0, 0xA5, 0xD3, 0x09, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xE8, 0x14, 0x39, 0xBE, 0xCB, 0x60, 0xAF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD6, 0x14, 0xA9, 0xC9, 0x20, 0xC3, 0xEA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x5B, 0xFD, 0x2D, 0x96, 0xBC, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x04, 0x45, 0xBE, 0xCE, 0x75, 0x95, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xDA, 0x58, 0x49, 0x35, 0x09, 0x8D, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xF0, 0xC0, 0x36, 0xF2, 0xA6, 0x2D, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFC, 0x3D, 0xA8, 0xFB, 0x3C, 0xD2, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x4D, 0x71, 0x09, 0x18, 0x42, 0xF0, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xC1, 0xCE, 0x9E, 0x6A, 0x49, 0x60, 0x12),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xB1, 0x00, 0xF7, 0xA1, 0x7A, 0x31, 0xB4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC3, 0x86, 0xCD, 0x20, 0x4A, 0x17, 0x86),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xAB, 0x8B, 0x47, 0x8D, 0xAA, 0xA6, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x97, 0xF0, 0xBC, 0x2D, 0xDC, 0x9D, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x86, 0xB0, 0x74, 0xB2, 0xF4, 0xF6, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBD, 0xAC, 0xE3, 0x8F, 0x43, 0x5C, 0xB1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xC3, 0xE2, 0x6E, 0x25, 0x49, 0xCD, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5E, 0x08, 0xB3, 0xB9, 0xAC, 0x5F, 0xD1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xB7, 0xD1, 0xF4, 0xDC, 0x19, 0xE9, 0xC8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xE4, 0xFA, 0xE1, 0x36, 0x3E, 0xED, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0x92, 0x84, 0x6E, 0x48, 0x03, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x95, 0xEF, 0x8F, 0xB2, 0x82, 0x6B, 0x1C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFA, 0xB9, 0x55, 0x23, 0xFE, 0x09, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x79, 0x85, 0x4B, 0x0E, 0xD4, 0x35, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x27, 0x45, 0x81, 0xE0, 0x88, 0x52, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x63, 0xA2, 0x4B, 0xBC, 0x5D, 0xB1, 0x92),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x8C, 0x83, 0xD9, 0x3E, 0xD3, 0x42, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x03, 0x3A, 0x31, 0xBA, 0xE9, 0x3A, 0xD1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x10, 0xCD, 0x2D, 0x00, 0xFE, 0x32, 0xA7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x6E, 0x1F, 0xDA, 0xF8, 0x6F, 0x4D, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x79, 0x7D, 0x09, 0xE5, 0xD3, 0x03, 0x21),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC3, 0xBE, 0xDF, 0x07, 0x65, 0x49, 0xCC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0x33, 0xEF, 0xAE, 0x4F, 0x04, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xE9, 0x9B, 0xFE, 0xBF, 0xE6, 0x85, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xBA, 0xAA, 0x06, 0xC4, 0xC6, 0xB8, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x83, 0x01, 0xA9, 0xF6, 0x51, 0xE7, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xA6, 0x15, 0x8E, 0xAB, 0x1F, 0x10, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x08, 0x27, 0x1A, 0xA1, 0x21, 0xAD, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x09, 0x90, 0x6E, 0x50, 0x90, 0x9A, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x9A, 0xFE, 0xD7, 0xA1, 0xF5, 0xA2, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x7D, 0xE3, 0xDC, 0x21, 0xFB, 0xA4, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBF, 0x07, 0xFF, 0x45, 0xDF, 0x51, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x5C, 0x34, 0x02, 0x62, 0x9B, 0x08, 0x12),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xCE, 0x9A, 0x6A, 0xEC, 0x75, 0xF6, 0x46),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x59, 0xF4, 0x78, 0x3C, 0x60, 0xB1, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x37, 0x84, 0x6A, 0xDC, 0xF2, 0x9A, 0x7D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9A, 0x9A, 0x15, 0x36, 0xE0, 0x2B, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x38, 0x9C, 0x50, 0x3D, 0x1E, 0x37, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x79, 0xF0, 0x92, 0xF2, 0x8B, 0x18, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE0, 0x82, 0x1E, 0x80, 0x82, 0x4B, 0xD7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xBB, 0x59, 0x6B, 0x8A, 0x77, 0x41, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xF9, 0xD4, 0xB8, 0x4A, 0x82, 0xCF, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x8C, 0xC8, 0x9B, 0x72, 0x9E, 0xF7, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xCE, 0xE9, 0x77, 0x0A, 0x19, 0x59, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xA1, 0x41, 0x6A, 0x72, 0x4B, 0xB4, 0xDC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x35, 0x43, 0xE2, 0x8C, 0xBE, 0x0D, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xEB, 0xAD, 0xF3, 0xA9, 0xA6, 0x68, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2F, 0xE2, 0x48, 0x0C, 0xDB, 0x1F, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x1E, 0x60, 0x9B, 0x2A, 0xD2, 0xC1, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x64, 0xB5, 0xD2, 0xF6, 0xF6, 0x6E, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x3D, 0x30, 0x78, 0x10, 0x18, 0x41, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x1D, 0x1C, 0xE0, 0x6D, 0x83, 0xD1, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x03, 0x0B, 0xF5, 0x2F, 0x6C, 0x04, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x3E, 0xD5, 0xFC, 0x31, 0x5B, 0x3A, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x82, 0x2F, 0xFB, 0xFE, 0xF8, 0x76, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x26, 0xDA, 0x9C, 0x36, 0xF5, 0x93, 0xD1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xE7, 0x6E, 0xD2, 0x7D, 0x81, 0x09, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x03, 0xF9, 0x58, 0x48, 0x24, 0xA2, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x79, 0x0C, 0x8E, 0x6B, 0x95, 0xF3, 0xC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x10, 0x5C, 0x87, 0x03, 0x39, 0xCF, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xF0, 0xF7, 0xC1, 0x07, 0xA4, 0xF4, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE8, 0x02, 0x89, 0x65, 0xC4, 0x72, 0x36),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x88, 0xEA, 0x96, 0x67, 0x0B, 0x5D, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x75, 0x60, 0xA8, 0xBD, 0x74, 0xDF, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xE5, 0x71, 0x50, 0x67, 0xD0, 0xD2, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFC, 0xE5, 0xC7, 0x77, 0xB0, 0x7F, 0x8C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x86, 0x69, 0xCD, 0x0D, 0x9A, 0xBD, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x17, 0xBC, 0xBB, 0x59, 0x85, 0x7D, 0x0E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA8, 0x76, 0xAC, 0x80, 0xA9, 0x72, 0xE0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0xC1, 0xE2, 0x4D, 0xAF, 0xF9, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x97, 0x8E, 0x74, 0xC4, 0x4B, 0xB2, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD8, 0xF6, 0xF3, 0xAF, 0x2F, 0x52, 0xE5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x57, 0xF4, 0xCE, 0xEE, 0x43, 0xED, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x46, 0x38, 0xDE, 0x20, 0xFD, 0x59, 0x18),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x18, 0xE8, 0x58, 0xB9, 0x76, 0x2C, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x54, 0xE4, 0xFE, 0xC7, 0xBC, 0x31, 0x37),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF8, 0x89, 0xEE, 0x70, 0xB5, 0xB0, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x22, 0x26, 0x9A, 0x53, 0xB9, 0x38, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xA7, 0x19, 0x8C, 0x74, 0x7E, 0x88, 0x46),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xDA, 0x0A, 0xE8, 0xDA, 0xA5, 0xBE, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x5C, 0xF7, 0xB1, 0x0C, 0x72, 0xFB, 0x09),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xE2, 0x23, 0xE7, 0x46, 0xB7, 0xE0, 0x91),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x36, 0xBC, 0xBD, 0x48, 0x11, 0x8E, 0x72),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xBB, 0xA1, 0xF7, 0x0B, 0x9E, 0xBF, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x28, 0xE1, 0xA2, 0x8F, 0xFC, 0xFC, 0xD6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xFE, 0x19, 0x0A, 0xE5, 0xE7, 0x69, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xCD, 0x12, 0xF5, 0xBE, 0xD3, 0x04, 0xF1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA8, 0x0D, 0x81, 0x59, 0xC4, 0x79, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xF3, 0x4B, 0x92, 0x65, 0xC3, 0x31, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xB5, 0x4F, 0x4D, 0x91, 0xD4, 0xE2, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x09, 0x41, 0x79, 0x1D, 0x4D, 0x0D, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x31, 0x18, 0xBA, 0xA0, 0xF2, 0x6E, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x5B, 0x4D, 0x4F, 0xAF, 0xC9, 0x8C, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x9C, 0x06, 0x68, 0xDE, 0xD8, 0x29),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x04, 0xE1, 0xB5, 0x9D, 0x00, 0xBC, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x95, 0x92, 0x8D, 0x72, 0xD3, 0x37, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x4B, 0x27, 0xA2, 0xE8, 0xA4, 0x26, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x45, 0x9C, 0xA9, 0xCB, 0x9F, 0xBA, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x7E, 0x1B, 0x64, 0xF4, 0xE8, 0xA5, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x20, 0xA9, 0xCA, 0xF3, 0x89, 0xE5, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xED, 0xFC, 0xAB, 0xD9, 0x0A, 0xB9, 0x07),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6F, 0x46, 0x7C, 0xCD, 0x78, 0xFF, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAB, 0x71, 0x5A, 0x94, 0xAB, 0x20, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x2E, 0xEE, 0x87, 0x57, 0x1F, 0xAD, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x4C, 0x3D, 0xFB, 0x7E, 0xA1, 0x8B, 0x07),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xCF, 0x07, 0x86, 0xBA, 0x53, 0x37, 0xCF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x26, 0xB2, 0xB9, 0xE2, 0x91, 0xE3, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xC9, 0x54, 0x84, 0x08, 0x3D, 0x0B, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x77, 0x2F, 0x64, 0x45, 0x99, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x96, 0x16, 0x1F, 0xDB, 0x96, 0x28, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x2B, 0x8D, 0xFF, 0xA2, 0x4F, 0x55, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE6, 0x48, 0xBD, 0x99, 0x3D, 0x12, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x84, 0x59, 0xDA, 0xB9, 0xB6, 0x66, 0x12),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x78, 0x41, 0x92, 0xDF, 0xF4, 0x3F, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x86, 0x6F, 0x4F, 0xBF, 0x67, 0xDF, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x2B, 0x1E, 0x5F, 0x00, 0xEA, 0xF6, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xB9, 0x6A, 0x89, 0xD8, 0xC0, 0xD7, 0xA7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x9A, 0x32, 0x23, 0xA0, 0x02, 0x91, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x7F, 0x6A, 0x15, 0x64, 0x6A, 0x8B, 0xBB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x57, 0x82, 0x58, 0xA9, 0x56, 0xB5, 0xFB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x50, 0x92, 0x60, 0xCC, 0x81, 0x24, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x3D, 0xAD, 0xDA, 0xD9, 0x51, 0x3E, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xFE, 0x8F, 0xB0, 0x0B, 0xDE, 0x2E, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xD2, 0xBE, 0xEF, 0xAC, 0x76, 0x71, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xE8, 0x72, 0x0B, 0xAC, 0xFE, 0xCA, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0xC7, 0xFC, 0xE3, 0x3C, 0x7C, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x04, 0xA7, 0xB9, 0x9B, 0x93, 0xC0, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x48, 0x4B, 0x8E, 0x32, 0xC5, 0xF0, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x42, 0x07, 0xC1, 0xF2, 0xF1, 0x72, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x37, 0x54, 0x9C, 0x88, 0xD2, 0x62, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x19, 0x8A, 0x89, 0x58, 0xA2, 0x0F, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xCC, 0x4C, 0x97, 0x30, 0x66, 0x34, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x6A, 0x1E, 0x1F, 0xDB, 0xC9, 0x5E, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x4D, 0x49, 0xFF, 0x9B, 0x9C, 0xAC, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xE4, 0x4B, 0xF2, 0xD4, 0x1A, 0xD2, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xDA, 0xE8, 0x61, 0x9F, 0xC8, 0x49, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xCB, 0xF2, 0x2D, 0x85, 0xF6, 0x8D, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xC5, 0xCD, 0x2C, 0x79, 0xC6, 0x0E, 0x4F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x1D, 0x55, 0x0F, 0xF8, 0x22, 0x9F, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x56, 0xBA, 0xE7, 0x57, 0x32, 0xEC, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x9A, 0xC6, 0x4C, 0x09, 0xC4, 0x52, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x1E, 0x6F, 0xF4, 0x7D, 0x27, 0xDD, 0xAF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x11, 0x16, 0xEC, 0x79, 0x83, 0xAD, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x4E, 0x92, 0x1F, 0x19, 0x7D, 0x65, 0xDC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xFF, 0x78, 0x15, 0x45, 0x63, 0x32, 0xE4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x91, 0xD0, 0x78, 0x58, 0xDA, 0x50, 0x47),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xDE, 0x40, 0xF6, 0x41, 0xB4, 0x3B, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x8D, 0xE0, 0xE1, 0xA9, 0xF0, 0x35, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xD4, 0xBA, 0x7B, 0xCC, 0x1B, 0x3A, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x5A, 0x2E, 0x74, 0x47, 0x14, 0xC3, 0x4D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xF0, 0x8B, 0x06, 0x15, 0x8E, 0x0E, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xD2, 0xEB, 0x97, 0x50, 0x7D, 0x31, 0xFC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x93, 0x4C, 0xDB, 0x97, 0x79, 0x44, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xA2, 0xA0, 0x0B, 0xC8, 0x3A, 0x8A, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x50, 0x92, 0x9E, 0x24, 0x1F, 0xCB, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x16, 0xC9, 0xC5, 0x3D, 0x5A, 0xAF, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xE3, 0x97, 0xE4, 0xA8, 0x50, 0xF6, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x57, 0x97, 0x42, 0x78, 0x92, 0x49, 0x0D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEB, 0x62, 0x24, 0xFB, 0x8F, 0x32, 0xCF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x0C, 0x36, 0x6E, 0x8F, 0xE8, 0xE8, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xD3, 0x7C, 0xC7, 0x8D, 0x3F, 0x5C, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x64, 0x6A, 0x73, 0x10, 0x79, 0xB8, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xF9, 0xEF, 0xA5, 0x20, 0x4A, 0x5C, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xF3, 0xF4, 0x49, 0x5B, 0x73, 0xAA, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xF2, 0xEA, 0x0F, 0x00, 0xAD, 0x53, 0xAB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xB8, 0x66, 0xED, 0xC4, 0x2B, 0x4C, 0x35),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x2F, 0xC1, 0x9A, 0x37, 0xD2, 0x7F, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA7, 0x81, 0x38, 0x64, 0xC9, 0x37, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x3B, 0x6C, 0x9F, 0x5B, 0xD9, 0x8B, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x14, 0xD9, 0x08, 0xD8, 0xD2, 0x7E, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x71, 0xE6, 0x3D, 0xD1, 0xB0, 0xE7, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x81, 0x23, 0xEC, 0x2D, 0x42, 0x45, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x5B, 0x44, 0x6B, 0x89, 0x03, 0x67, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x27, 0xAE, 0x80, 0x5A, 0x33, 0xBE, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB6, 0x64, 0x1A, 0xDF, 0xD3, 0x85, 0x91),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x8C, 0x22, 0xBA, 0xD0, 0xBD, 0xCC, 0xA0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x3C, 0x01, 0x3A, 0xFF, 0x9D, 0xC7, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC7, 0x64, 0xB4, 0x59, 0x4E, 0x9F, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x34, 0x0A, 0x41, 0x94, 0xA8, 0xF2, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD4, 0xE4, 0xF0, 0x97, 0x45, 0x6D, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x1F, 0x4D, 0x6D, 0xFE, 0xA0, 0xC4, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x28, 0x5C, 0x40, 0xBB, 0x65, 0xD4, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xA8, 0x87, 0x35, 0x20, 0x3A, 0x89, 0x44),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFD, 0x4F, 0xAB, 0x2D, 0xD1, 0xD0, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE8, 0x00, 0xFC, 0x69, 0x52, 0xF8, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x9A, 0x99, 0xE1, 0xDC, 0x9C, 0x3F, 0xD9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x08, 0x98, 0xD9, 0xCA, 0x73, 0xD5, 0xA9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x2C, 0xE0, 0xA7, 0x3E, 0x91, 0xD7, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x04, 0xB0, 0x54, 0x09, 0xF4, 0x72, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xEE, 0x28, 0xCC, 0xE8, 0x50, 0x78, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x91, 0x03, 0x76, 0xDB, 0x68, 0x24, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xE0, 0x56, 0xB2, 0x5D, 0x12, 0xD3, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x42, 0x59, 0x8B, 0xDF, 0x67, 0xB5, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xCC, 0xE5, 0x31, 0x53, 0x7A, 0x46, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_16_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8D, 0x59, 0xB5, 0x1B, 0x0F, 0xF4, 0xAF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x2F, 0xD1, 0x2C, 0xE0, 0xD8, 0x04, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0xD7, 0xBA, 0xB0, 0xA3, 0x7E, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x08, 0x51, 0x56, 0xA6, 0x76, 0x67, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x17, 0x63, 0xFE, 0x56, 0xD0, 0xD9, 0x71),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xF6, 0xC3, 0x14, 0x47, 0xC5, 0xA7, 0x31),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x4C, 0x80, 0xF6, 0xA2, 0x57, 0xA7, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xB3, 0x7B, 0xF8, 0x2F, 0xE1, 0x3E, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_16_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xF4, 0xF9, 0x6B, 0x7B, 0x90, 0xDF, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x82, 0xEF, 0x62, 0xA1, 0x4C, 0x53, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x99, 0x76, 0x01, 0xBA, 0x8D, 0x0F, 0x54),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xF4, 0x58, 0x73, 0x56, 0xFE, 0xDD, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xCE, 0xF9, 0xE8, 0xA1, 0x34, 0xC3, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x5F, 0xDC, 0x6A, 0x3D, 0xD8, 0x7F, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xF4, 0x51, 0xB8, 0xB8, 0xC1, 0xD7, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x7D, 0x58, 0xD1, 0xD4, 0x1B, 0x4D, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_17_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x95, 0xDF, 0x00, 0xD8, 0x21, 0xDE, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x47, 0x3C, 0xC3, 0xB2, 0x01, 0x53, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x17, 0x43, 0x23, 0xBD, 0xCA, 0x71, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xBA, 0x0F, 0x4F, 0xDC, 0x41, 0x54, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x39, 0x26, 0x70, 0x53, 0x32, 0x18, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x46, 0x07, 0x97, 0x3A, 0x57, 0xE0, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x92, 0x4F, 0xCE, 0xDF, 0x25, 0x80, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x6F, 0x9A, 0x03, 0x05, 0x4B, 0xD1, 0x47),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_17_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x01, 0x72, 0x30, 0x90, 0x17, 0x51, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xFB, 0x41, 0x65, 0x5C, 0xB4, 0x2D, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xCD, 0xCD, 0xAA, 0x41, 0xCC, 0xBB, 0x07),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xCE, 0x08, 0x0A, 0x63, 0xE9, 0xA2, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA8, 0x21, 0x7F, 0x7A, 0x5B, 0x9B, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x6B, 0x89, 0x44, 0x0A, 0x7F, 0x85, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xDE, 0x7C, 0x19, 0x5C, 0x65, 0x26, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xAC, 0x62, 0x29, 0x4A, 0xF1, 0xD0, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_18_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x00, 0x40, 0x87, 0xEB, 0xA9, 0x58, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x51, 0x0B, 0xFF, 0x56, 0x35, 0x51, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xAC, 0x08, 0x94, 0x71, 0xDA, 0xEC, 0x99),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x4D, 0xC5, 0x7B, 0x31, 0x8B, 0x8D, 0x5E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x05, 0xF1, 0x3E, 0x9E, 0x8F, 0x17, 0x8F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x9C, 0x4B, 0x62, 0x94, 0xAD, 0x49, 0xFC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC9, 0xC6, 0x8F, 0xFD, 0x33, 0x44, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x96, 0x17, 0x7F, 0x42, 0xBE, 0xF7, 0x0D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_18_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x29, 0x39, 0x13, 0x08, 0x8D, 0x91, 0x47),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x79, 0xF9, 0x2F, 0xA9, 0x0A, 0xCF, 0xD6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x87, 0x7A, 0xA3, 0x19, 0xAB, 0x55, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x0B, 0x01, 0xC5, 0x56, 0x19, 0x9D, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xDE, 0x82, 0x3B, 0xEA, 0xD3, 0x0B, 0x8C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x6B, 0xC7, 0xF3, 0x0F, 0x82, 0x87, 0x6C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x2E, 0x23, 0xF2, 0x39, 0x9D, 0x49, 0x70),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xDE, 0xAF, 0x7A, 0xEE, 0xB0, 0xDA, 0x70),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_19_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x4E, 0x2A, 0x50, 0xFD, 0x8E, 0xC0, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x0F, 0x7C, 0x76, 0x63, 0xD8, 0x89, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x2D, 0xB9, 0x4E, 0xF4, 0xEE, 0x85, 0xCF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x95, 0x5C, 0x96, 0x5D, 0xAA, 0x59, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xDB, 0xD2, 0x68, 0x8E, 0x5A, 0x94, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x02, 0xBF, 0x77, 0x9F, 0xB9, 0x4C, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xDC, 0xC0, 0xCF, 0x81, 0x1E, 0xC4, 0x6C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xCC, 0x37, 0x86, 0xDC, 0xE2, 0x64, 0x72),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_19_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x30, 0xB1, 0x59, 0x20, 0x9D, 0x98, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x0C, 0x9D, 0xF8, 0x20, 0xDC, 0x90, 0xBA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xA0, 0xF4, 0xE7, 0x3E, 0x9C, 0x9E, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x25, 0xA2, 0xB0, 0x54, 0xCD, 0x2E, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD9, 0x42, 0xB0, 0x80, 0xB0, 0xA3, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xFE, 0x9D, 0x8D, 0x40, 0xFF, 0x27, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9D, 0xA6, 0x88, 0x3A, 0x8B, 0x6F, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x39, 0xEE, 0x1F, 0x3F, 0xB1, 0x4F, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_20_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD7, 0x9E, 0xFF, 0xD2, 0x35, 0x67, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x4F, 0x15, 0x5D, 0xE3, 0xE8, 0x53, 0x86),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF7, 0x24, 0x98, 0xA2, 0xCB, 0x11, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x2E, 0x25, 0xE1, 0x94, 0xC5, 0xA3, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x82, 0x6E, 0xBA, 0xE7, 0x43, 0x25, 0xB0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x65, 0xB4, 0x49, 0x73, 0x18, 0x35, 0x54),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x5B, 0xBC, 0x62, 0x86, 0x4C, 0xC1, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xF2, 0x95, 0xA2, 0xBB, 0xA2, 0x35, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_20_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x59, 0x62, 0xB0, 0x4B, 0x1E, 0xB4, 0xD8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x55, 0xCE, 0xB0, 0x69, 0xBA, 0x63, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x69, 0x86, 0xDB, 0x34, 0x7D, 0x68, 0x64),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x06, 0xCA, 0x55, 0x44, 0x36, 0x2B, 0xBA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xD4, 0xC4, 0x3D, 0xCD, 0x9E, 0x69, 0xA4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x44, 0xE4, 0xBF, 0x31, 0xE6, 0x40, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x4F, 0xFA, 0x75, 0xE3, 0xFB, 0x97, 0x0E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xC0, 0xBD, 0x1C, 0x48, 0xB0, 0x26, 0xD0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_21_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x7B, 0x32, 0xFA, 0xF2, 0x6D, 0x84, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x21, 0x03, 0x1D, 0x0D, 0x22, 0x55, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xF9, 0x42, 0x03, 0x9C, 0xC2, 0xCB, 0xBA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xA1, 0x96, 0xD9, 0x9D, 0x11, 0x6F, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x40, 0x57, 0xEB, 0x40, 0x2D, 0xC0, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x96, 0xBB, 0x4F, 0x2F, 0x23, 0xA8, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x29, 0x85, 0x21, 0xA5, 0x50, 0x62, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x7D, 0x92, 0xCF, 0x87, 0x0C, 0x22, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_21_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x0E, 0xA5, 0x32, 0x5B, 0xDF, 0x9C, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x96, 0x37, 0x2C, 0x88, 0x35, 0x30, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xB4, 0x69, 0xFF, 0xEB, 0xC6, 0x94, 0x08),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x55, 0x60, 0xAD, 0xAA, 0x58, 0x14, 0x88),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xFF, 0xF2, 0xB2, 0xD5, 0xA7, 0xD9, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xAE, 0x54, 0xD2, 0x60, 0x31, 0xF3, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x92, 0x83, 0xE3, 0xF1, 0x42, 0x83, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD2, 0xC8, 0xB7, 0x76, 0x45, 0x7F, 0x7D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_22_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x11, 0xA4, 0xFB, 0x7A, 0x01, 0xBC, 0xC8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x27, 0x73, 0x8D, 0x02, 0x91, 0x27, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x62, 0xF6, 0xDD, 0x6B, 0xFA, 0x5B, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCA, 0xA2, 0x44, 0x2C, 0xF0, 0x28, 0xD8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xF1, 0x7A, 0xA2, 0x42, 0x4C, 0x50, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x83, 0x3E, 0x50, 0xAB, 0x9C, 0xF7, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xED, 0x78, 0xCB, 0x76, 0x69, 0xDA, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x1E, 0x43, 0x27, 0x47, 0x6E, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_22_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x4F, 0x54, 0xB9, 0x3E, 0xBD, 0xD5, 0x44),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x40, 0x69, 0x7F, 0x74, 0x9D, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x06, 0x6F, 0x67, 0x68, 0x2B, 0x4D, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x65, 0x41, 0xFC, 0x7C, 0x1E, 0xE8, 0xC8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x79, 0x37, 0xAF, 0xFD, 0xD2, 0xDA, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xA8, 0x69, 0x56, 0x62, 0xA4, 0xE4, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x71, 0x73, 0x21, 0x8A, 0x17, 0x81, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x55, 0x8F, 0x7B, 0xB8, 0xAF, 0xF7, 0x86),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_23_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xD1, 0xBD, 0xBE, 0x8C, 0xBC, 0x60, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA6, 0x57, 0x8C, 0xAE, 0x5C, 0x19, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x43, 0xE4, 0xD9, 0xD8, 0x7B, 0xE7, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xB9, 0xE4, 0x85, 0x7C, 0x2E, 0xFC, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2E, 0x01, 0x2A, 0x6D, 0x56, 0xBE, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x0C, 0x25, 0x9B, 0xAE, 0x86, 0x37, 0x43),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x22, 0xB3, 0xCB, 0x99, 0x66, 0xB7, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xF7, 0x90, 0xF0, 0x1B, 0x09, 0x27, 0xF7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_23_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x16, 0x08, 0xEF, 0x39, 0x64, 0x49, 0x31),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA0, 0xE3, 0x97, 0xA9, 0x07, 0x54, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xFF, 0xE2, 0x00, 0x07, 0x21, 0x88, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFD, 0x59, 0x53, 0x05, 0x6C, 0x42, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xF7, 0x39, 0x5C, 0x82, 0x36, 0xE8, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x83, 0xA8, 0xE2, 0xA8, 0x43, 0x07, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xAF, 0x2B, 0x79, 0xED, 0xD8, 0x39, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x20, 0x91, 0x7A, 0xC4, 0x07, 0xEF, 0x6C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_24_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x2F, 0xAA, 0x0C, 0x94, 0x0E, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x81, 0x87, 0x41, 0x23, 0xEB, 0x55, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x53, 0xCC, 0x79, 0xB6, 0xEB, 0x6C, 0xCC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x77, 0x73, 0x9D, 0xFC, 0x64, 0x6F, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x40, 0xE3, 0x6D, 0x1C, 0x16, 0x71, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xF4, 0x1B, 0xFF, 0x1C, 0x2F, 0xA5, 0xD7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x0E, 0x0B, 0x11, 0xF4, 0x8D, 0x93, 0xAF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC5, 0x64, 0x6F, 0x24, 0x19, 0xF2, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_24_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xB3, 0xAF, 0xA5, 0x0E, 0x4F, 0x5E, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x77, 0xCA, 0xF2, 0x6D, 0xC5, 0xF6, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x18, 0x8E, 0x33, 0x68, 0x6C, 0xE8, 0xE0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x8B, 0x80, 0x90, 0x19, 0x7F, 0x90, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x80, 0x6B, 0x68, 0xE2, 0x7D, 0xD4, 0xD0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC1, 0x67, 0xB3, 0x72, 0xCB, 0xBF, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xD5, 0xD3, 0x1D, 0x14, 0x58, 0x0A, 0x80),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x7A, 0x65, 0x98, 0xB3, 0x07, 0x4B, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_25_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x87, 0x0F, 0x5F, 0xCF, 0xA2, 0x01, 0x08),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC9, 0xC8, 0x6E, 0x35, 0x87, 0xA5, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x3E, 0x91, 0xA0, 0xAB, 0x24, 0x1E, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBC, 0x02, 0x35, 0x70, 0xC1, 0x5F, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x59, 0xA0, 0x50, 0x04, 0x80, 0x52, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x56, 0x6E, 0x42, 0x8F, 0x8C, 0x91, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xA2, 0xCB, 0xA5, 0xDE, 0x14, 0x24, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xCB, 0x74, 0x28, 0xE6, 0xA7, 0xE7, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_25_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x73, 0xA8, 0x8F, 0x9E, 0x0E, 0x63, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x1B, 0x77, 0xC7, 0xC1, 0x38, 0xF9, 0xDC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x3C, 0xCF, 0xA8, 0x7A, 0xD7, 0xF3, 0xC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x5F, 0x9A, 0xC9, 0xAD, 0xE9, 0x1A, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0x2B, 0x5E, 0xD5, 0x81, 0x95, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x88, 0x75, 0x29, 0x1F, 0xC7, 0xC7, 0xD0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA9, 0x5A, 0x4D, 0x63, 0x95, 0xF9, 0x4E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xCD, 0x04, 0x8F, 0xCD, 0x91, 0xDE, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_26_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xD4, 0xFD, 0x25, 0x11, 0x99, 0x6E, 0xEA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x83, 0x01, 0x3D, 0xFB, 0x56, 0xA5, 0x4E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x3A, 0xDC, 0x74, 0xC2, 0xD7, 0xCF, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xBD, 0xF1, 0xDD, 0xA3, 0x07, 0x03, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xBE, 0xE9, 0x2E, 0x58, 0x84, 0x66, 0xFC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x20, 0x78, 0x37, 0x79, 0x0B, 0xA6, 0x64),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xF2, 0xAC, 0x65, 0xC8, 0xC9, 0x2F, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x93, 0xE5, 0x0D, 0x0C, 0xC6, 0xB8, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_26_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAD, 0x5C, 0x19, 0x12, 0x61, 0x0E, 0x25),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x4F, 0x0B, 0x1F, 0x49, 0x7E, 0xCD, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2E, 0x30, 0x61, 0xDB, 0x08, 0x68, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x78, 0xAF, 0xB3, 0x08, 0xC1, 0x69, 0xE5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x5F, 0x5D, 0xC1, 0x57, 0x6F, 0xD8, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xD3, 0x6A, 0xF7, 0xFD, 0x86, 0xE5, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x63, 0xBD, 0x70, 0x7B, 0x47, 0xE8, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x62, 0xC8, 0x7E, 0x9D, 0x11, 0x2B, 0xA5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_27_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x84, 0xFD, 0xD5, 0x9A, 0x56, 0x7F, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBB, 0xA4, 0x6F, 0x12, 0x6E, 0x4D, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x08, 0xA1, 0x82, 0x9C, 0x62, 0x74, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x22, 0x05, 0x1D, 0x15, 0x35, 0x79),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x88, 0xCF, 0x5C, 0x05, 0x78, 0xFB, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x6B, 0x2F, 0x79, 0x09, 0x73, 0x67, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA0, 0x80, 0xD8, 0xE8, 0xEC, 0xFB, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0B, 0xB7, 0x81, 0x48, 0x7B, 0xD9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_27_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x53, 0xA9, 0xED, 0x61, 0x92, 0xD7, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x49, 0xD9, 0x5D, 0x9B, 0x4E, 0x89, 0x35),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x12, 0xEB, 0x9A, 0xC9, 0xCB, 0xC1, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xDC, 0x95, 0x16, 0xFE, 0x29, 0x70, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x33, 0xB1, 0xD6, 0x78, 0xB9, 0xE2, 0x36),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xCE, 0x88, 0xC3, 0xFD, 0x7A, 0x6B, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x1E, 0x50, 0x1E, 0xAF, 0xB1, 0x25, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xE7, 0xD7, 0xD5, 0xBD, 0x7A, 0x12, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_28_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xAA, 0xA2, 0x80, 0x5D, 0x8F, 0xCD, 0xC8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x39, 0x79, 0x64, 0xA1, 0x67, 0x3C, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xC7, 0x49, 0xFF, 0x7F, 0xAC, 0xAB, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x54, 0x3E, 0x83, 0xF0, 0x3D, 0xBC, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x92, 0x4A, 0x38, 0x42, 0x8A, 0xAB, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x0B, 0x4F, 0xEE, 0x9E, 0x92, 0xA5, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xDD, 0x19, 0x96, 0xF2, 0xF0, 0x6B, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xFC, 0xDD, 0xB2, 0x8A, 0xE5, 0x4C, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_28_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x06, 0x49, 0xAC, 0x99, 0x7E, 0xF8, 0x12),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xC8, 0x01, 0x51, 0xEA, 0xF6, 0x52, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x89, 0x66, 0x2B, 0x1F, 0x9B, 0x2A, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x0F, 0x95, 0x07, 0x2B, 0x6C, 0x6E, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC3, 0xB4, 0xBB, 0x91, 0x1F, 0xA3, 0x72),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x6E, 0x54, 0x28, 0x7B, 0x9C, 0x79, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x45, 0xFF, 0xA6, 0xDA, 0xA2, 0x83, 0x71),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xDE, 0x8F, 0x17, 0x37, 0x82, 0xCB, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_29_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x94, 0x3F, 0x26, 0xC9, 0x1D, 0xD9, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x28, 0x20, 0xCD, 0xC1, 0xF3, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC9, 0xB5, 0x60, 0x9B, 0x1E, 0xDC, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xB9, 0x5B, 0x7D, 0xA0, 0xB2, 0x8C, 0xF0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xD1, 0x42, 0xE6, 0x39, 0x33, 0x6D, 0xBB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xC0, 0xFC, 0xD2, 0x14, 0x5D, 0x3E, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x4A, 0x3E, 0x40, 0x16, 0x93, 0x15, 0xCF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x24, 0xC1, 0x27, 0x27, 0xE5, 0x4B, 0xD8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_29_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x50, 0xD8, 0xBC, 0xC1, 0x46, 0x22, 0xBB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x0E, 0x60, 0xA1, 0xB3, 0x50, 0xD4, 0x86),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xB1, 0x26, 0xB6, 0x6D, 0x47, 0x5A, 0x6F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0xAC, 0x11, 0x35, 0x3E, 0xB9, 0xF4, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x97, 0xFA, 0xBB, 0x6B, 0x39, 0x13, 0xD8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x34, 0x12, 0x75, 0x8E, 0x9B, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x9E, 0xCD, 0x29, 0xB6, 0xEF, 0x8D, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xAC, 0xE9, 0x25, 0x27, 0xBB, 0x78, 0x47),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_30_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x7A, 0xA8, 0xD3, 0xE3, 0x66, 0xE5, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x4C, 0xC4, 0x2C, 0x76, 0x81, 0x50, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x71, 0x08, 0xB8, 0x52, 0x7C, 0xAF, 0xDC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x59, 0x24, 0xDD, 0xFB, 0x2F, 0xD0, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCD, 0x56, 0xE9, 0xAC, 0x91, 0xE6, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x64, 0x20, 0xC6, 0x9F, 0xE4, 0xEF, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x2C, 0x8F, 0x8C, 0x97, 0xF6, 0x22, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0x88, 0xAA, 0xA8, 0xD7, 0xA5, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_30_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x6C, 0xAE, 0x83, 0xB1, 0x55, 0x55, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x67, 0x84, 0x47, 0x7C, 0x83, 0x5C, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x10, 0x4D, 0xDD, 0x30, 0x60, 0xB0, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xA7, 0x36, 0x76, 0x24, 0x32, 0x9F, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x42, 0x81, 0xFB, 0xA4, 0x2E, 0x13, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x94, 0x91, 0xFF, 0x99, 0xA0, 0x09, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x83, 0xA1, 0x76, 0xAF, 0x37, 0x5C, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA8, 0x04, 0x86, 0xC4, 0xA9, 0x79, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_31_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8C, 0xC2, 0x34, 0xFB, 0x83, 0x28, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x03, 0x7D, 0x5E, 0x9E, 0x0E, 0xB0, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x02, 0x46, 0x7F, 0xB9, 0xAC, 0xBB, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xED, 0x48, 0xC2, 0x96, 0x4D, 0x56, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xC5, 0xD1, 0xE6, 0x1C, 0x7E, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x2E, 0x18, 0x71, 0x2D, 0x7B, 0xD7, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x46, 0x9D, 0xDE, 0xAA, 0x78, 0x8E, 0xB1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD7, 0x69, 0x2E, 0xE1, 0xD9, 0x48, 0xDE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_31_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFF, 0x9E, 0x09, 0x22, 0x22, 0xE6, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x14, 0x28, 0x13, 0x1B, 0x62, 0x12, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x7F, 0x67, 0x03, 0xB0, 0xC0, 0xF3, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xC3, 0x0F, 0xFB, 0x25, 0x48, 0x3E, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x6E, 0x53, 0x98, 0x36, 0xB3, 0xD3, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x81, 0x54, 0x22, 0xA4, 0xCC, 0xC1, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xBA, 0xFC, 0xA9, 0xDF, 0x68, 0x86, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x92, 0x0E, 0xC3, 0xF2, 0x58, 0xE8, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_ecp_point secp521r1_T[32] = {
+    ECP_POINT_INIT_XY_Z1(secp521r1_T_0_X, secp521r1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_1_X, secp521r1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_2_X, secp521r1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_3_X, secp521r1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_4_X, secp521r1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_5_X, secp521r1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_6_X, secp521r1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_7_X, secp521r1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_8_X, secp521r1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_9_X, secp521r1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_10_X, secp521r1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_11_X, secp521r1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_12_X, secp521r1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_13_X, secp521r1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_14_X, secp521r1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_15_X, secp521r1_T_15_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_16_X, secp521r1_T_16_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_17_X, secp521r1_T_17_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_18_X, secp521r1_T_18_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_19_X, secp521r1_T_19_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_20_X, secp521r1_T_20_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_21_X, secp521r1_T_21_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_22_X, secp521r1_T_22_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_23_X, secp521r1_T_23_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_24_X, secp521r1_T_24_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_25_X, secp521r1_T_25_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_26_X, secp521r1_T_26_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_27_X, secp521r1_T_27_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_28_X, secp521r1_T_28_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_29_X, secp521r1_T_29_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_30_X, secp521r1_T_30_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_31_X, secp521r1_T_31_Y),
+};
+#else
+#define secp521r1_T NULL
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
+static const mbedtls_mpi_uint secp192k1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+static const mbedtls_mpi_uint secp192k1_a[] = {
+    MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp192k1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_2(0x03, 0x00),
+};
+static const mbedtls_mpi_uint secp192k1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB),
+};
+static const mbedtls_mpi_uint secp192k1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B),
+};
+static const mbedtls_mpi_uint secp192k1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint secp192k1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB),
+};
+static const mbedtls_mpi_uint secp192k1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B),
+};
+static const mbedtls_mpi_uint secp192k1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x77, 0x3D, 0x0D, 0x85, 0x48, 0xA8, 0xA9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x07, 0xDF, 0x1D, 0xB3, 0xB3, 0x01, 0x54),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x86, 0xF6, 0xAF, 0x19, 0x2A, 0x88, 0x2E),
+};
+static const mbedtls_mpi_uint secp192k1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x90, 0xB6, 0x2F, 0x48, 0x36, 0x4C, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x11, 0x14, 0xA6, 0xCB, 0xBA, 0x15, 0xD9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB0, 0xF2, 0xD4, 0xC9, 0xDA, 0xBA, 0xD7),
+};
+static const mbedtls_mpi_uint secp192k1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xC1, 0x9C, 0xE6, 0xBB, 0xFB, 0xCF, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x19, 0xAC, 0x5A, 0xC9, 0x8A, 0x1C, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xF6, 0x76, 0x86, 0x89, 0x27, 0x8D, 0x28),
+};
+static const mbedtls_mpi_uint secp192k1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xE0, 0x6F, 0x34, 0xBA, 0x5E, 0xD3, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xDC, 0xA6, 0x87, 0xC9, 0x9D, 0xC0, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x11, 0x7E, 0xD6, 0xF7, 0x33, 0xFC, 0xE4),
+};
+static const mbedtls_mpi_uint secp192k1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x37, 0x3E, 0xC0, 0x7F, 0x62, 0xE7, 0x54),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3B, 0x69, 0x9D, 0x44, 0xBC, 0x82, 0x99),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x84, 0xB3, 0x5F, 0x2B, 0xA5, 0x9E, 0x2C),
+};
+static const mbedtls_mpi_uint secp192k1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x95, 0xEB, 0x4C, 0x04, 0xB4, 0xF4, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAD, 0x4B, 0xD5, 0x9A, 0xEB, 0xC4, 0x4E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xB1, 0xC5, 0x59, 0xE3, 0xD5, 0x16, 0x2A),
+};
+static const mbedtls_mpi_uint secp192k1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x2A, 0xCC, 0xAC, 0xD0, 0xEE, 0x50, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x83, 0xE0, 0x5B, 0x14, 0x44, 0x52, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x15, 0x2D, 0x78, 0xF6, 0x51, 0x32, 0xCF),
+};
+static const mbedtls_mpi_uint secp192k1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x36, 0x9B, 0xDD, 0xF8, 0xDD, 0xEF, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xB1, 0x6A, 0x2B, 0xAF, 0xEB, 0x2B, 0xB1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x87, 0x7A, 0x66, 0x5D, 0x5B, 0xDF, 0x8F),
+};
+static const mbedtls_mpi_uint secp192k1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x45, 0xE5, 0x81, 0x9B, 0xEB, 0x37, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x29, 0xE2, 0x20, 0x64, 0x23, 0x6B, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1D, 0x41, 0xE1, 0x9B, 0x61, 0x7B, 0xD9),
+};
+static const mbedtls_mpi_uint secp192k1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x57, 0xA3, 0x0A, 0x13, 0xE4, 0x59, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x6E, 0x4A, 0x48, 0x84, 0x90, 0xAC, 0xC7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB8, 0xF5, 0xF3, 0xDE, 0xA0, 0xA1, 0x1D),
+};
+static const mbedtls_mpi_uint secp192k1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x32, 0x81, 0xA9, 0x91, 0x5A, 0x4E, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xA8, 0x90, 0xBE, 0x0F, 0xEC, 0xC0, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x30, 0xD7, 0x08, 0xAE, 0xC4, 0x3A, 0xA5),
+};
+static const mbedtls_mpi_uint secp192k1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x55, 0xE3, 0x76, 0xB3, 0x64, 0x74, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x75, 0xD4, 0xDB, 0x98, 0xD7, 0x39, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xEB, 0x8A, 0xAB, 0x16, 0xD9, 0xD4, 0x0B),
+};
+static const mbedtls_mpi_uint secp192k1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xBE, 0xF9, 0xC7, 0xC7, 0xBA, 0xF3, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x85, 0x59, 0xF3, 0x60, 0x41, 0x02, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x1C, 0x4A, 0xA4, 0xC7, 0xED, 0x66, 0xBC),
+};
+static const mbedtls_mpi_uint secp192k1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x2E, 0x46, 0x52, 0x18, 0x87, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x35, 0x5A, 0x75, 0xAC, 0x4D, 0x75, 0x91),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x2F, 0xAC, 0xFC, 0xBC, 0xE6, 0x93, 0x5E),
+};
+static const mbedtls_mpi_uint secp192k1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x4D, 0xC9, 0x18, 0xE9, 0x00, 0xEB, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x69, 0x72, 0x07, 0x5A, 0x59, 0xA8, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x65, 0x83, 0x20, 0x10, 0xF9, 0x69, 0x82),
+};
+static const mbedtls_mpi_uint secp192k1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x56, 0x7F, 0x9F, 0xBF, 0x46, 0x0C, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0xF0, 0xDC, 0xDF, 0x2D, 0xE6, 0xE5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xF0, 0x72, 0x3A, 0x7A, 0x03, 0xE5, 0x22),
+};
+static const mbedtls_mpi_uint secp192k1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xAA, 0x57, 0x13, 0x37, 0xA7, 0x2C, 0xD4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xAC, 0xA2, 0x23, 0xF9, 0x84, 0x60, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xEB, 0x51, 0x70, 0x64, 0x78, 0xCA, 0x05),
+};
+static const mbedtls_mpi_uint secp192k1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xCC, 0x30, 0x62, 0x93, 0x46, 0x13, 0xE9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x26, 0xCC, 0x6C, 0x3D, 0x5C, 0xDA, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xAA, 0xB8, 0x03, 0xA4, 0x1A, 0x00, 0x96),
+};
+static const mbedtls_mpi_uint secp192k1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x9D, 0xE6, 0xCC, 0x4E, 0x2E, 0xC2, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xC3, 0x8A, 0xAE, 0x6F, 0x40, 0x05, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x8F, 0x4A, 0x4D, 0x35, 0xD3, 0x50, 0x9D),
+};
+static const mbedtls_mpi_uint secp192k1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xFD, 0x98, 0xAB, 0xC7, 0x03, 0xB4, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x40, 0xD2, 0x9F, 0xCA, 0xD0, 0x53, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x84, 0x00, 0x6F, 0xC8, 0xAD, 0xED, 0x8D),
+};
+static const mbedtls_mpi_uint secp192k1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xD3, 0x57, 0xD7, 0xC3, 0x07, 0xBD, 0xD7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xBA, 0x47, 0x1D, 0x3D, 0xEF, 0x98, 0x6C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC0, 0x6C, 0x7F, 0x12, 0xEE, 0x9F, 0x67),
+};
+static const mbedtls_mpi_uint secp192k1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x02, 0xDA, 0x79, 0xAA, 0xC9, 0x27, 0xC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x79, 0xC7, 0x71, 0x84, 0xCB, 0xE5, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x37, 0x06, 0xBA, 0xB5, 0xD5, 0x18, 0x4C),
+};
+static const mbedtls_mpi_uint secp192k1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x65, 0x72, 0x6C, 0xF2, 0x63, 0x27, 0x6A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xBC, 0x71, 0xDF, 0x75, 0xF8, 0x98, 0x4D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x70, 0x9B, 0xDC, 0xE7, 0x18, 0x71, 0xFF),
+};
+static const mbedtls_mpi_uint secp192k1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x5B, 0x9F, 0x00, 0x5A, 0xB6, 0x80, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE0, 0xBB, 0xFC, 0x5E, 0x78, 0x9C, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x03, 0x68, 0x83, 0x3D, 0x2E, 0x4C, 0xDD),
+};
+static const mbedtls_mpi_uint secp192k1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x49, 0x23, 0xA8, 0xCB, 0x3B, 0x1A, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x3D, 0xA7, 0x46, 0xCF, 0x75, 0xB6, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xFD, 0x30, 0x01, 0xB6, 0xEF, 0xF9, 0xE8),
+};
+static const mbedtls_mpi_uint secp192k1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xFA, 0xDA, 0xB8, 0x29, 0x42, 0xC9, 0xC7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xD7, 0xA0, 0xE6, 0x6B, 0x86, 0x61, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xE9, 0xD3, 0x37, 0xD8, 0xE7, 0x35, 0xA9),
+};
+static const mbedtls_mpi_uint secp192k1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC8, 0x8E, 0xB1, 0xCB, 0xB1, 0xB5, 0x4D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xD7, 0x46, 0x7D, 0xAF, 0xE2, 0xDC, 0xBB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x46, 0xE7, 0xD8, 0x76, 0x31, 0x90, 0x76),
+};
+static const mbedtls_mpi_uint secp192k1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD3, 0xF4, 0x74, 0xE1, 0x67, 0xD8, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x70, 0x3C, 0xC8, 0xAF, 0x5F, 0xF4, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x4E, 0xED, 0x5C, 0x43, 0xB3, 0x16, 0x35),
+};
+static const mbedtls_mpi_uint secp192k1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAE, 0xD1, 0xDD, 0x31, 0x14, 0xD3, 0xF0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x14, 0x06, 0x13, 0x12, 0x1C, 0x81, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xF9, 0x0C, 0x91, 0xF7, 0x67, 0x59, 0x63),
+};
+static const mbedtls_mpi_uint secp192k1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x91, 0xE2, 0xF4, 0x9D, 0xEB, 0x88, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x82, 0x30, 0x9C, 0xAE, 0x18, 0x4D, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x79, 0xCF, 0x17, 0xA5, 0x1E, 0xE8, 0xC8),
+};
+static const mbedtls_ecp_point secp192k1_T[16] = {
+    ECP_POINT_INIT_XY_Z1(secp192k1_T_0_X, secp192k1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_1_X, secp192k1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_2_X, secp192k1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_3_X, secp192k1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_4_X, secp192k1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_5_X, secp192k1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_6_X, secp192k1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_7_X, secp192k1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_8_X, secp192k1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_9_X, secp192k1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_10_X, secp192k1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_11_X, secp192k1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_12_X, secp192k1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_13_X, secp192k1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_14_X, secp192k1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_15_X, secp192k1_T_15_Y),
+};
+#else
+#define secp192k1_T NULL
+#endif
+
+#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
+static const mbedtls_mpi_uint secp224k1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF),
+};
+static const mbedtls_mpi_uint secp224k1_a[] = {
+    MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_2(0x05, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D),
+    MBEDTLS_BYTES_TO_T_UINT_4(0x33, 0x5B, 0x45, 0xA1),
+};
+static const mbedtls_mpi_uint secp224k1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_4(0xED, 0x9F, 0x08, 0x7E),
+};
+static const mbedtls_mpi_uint secp224k1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
+};
+
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint secp224k1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x5B, 0x45, 0xA1, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x9F, 0x08, 0x7E, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x6C, 0x22, 0x22, 0x40, 0x89, 0xAE, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x92, 0xE1, 0x87, 0x56, 0x35, 0xAF, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xAF, 0x08, 0x35, 0x27, 0xEA, 0x04, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x53, 0xFD, 0xCF, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xD0, 0x9F, 0x8D, 0xF3, 0x63, 0x54, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xDB, 0x0F, 0x61, 0x54, 0x26, 0xD1, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x21, 0xF7, 0x1B, 0xB5, 0x1D, 0xF6, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x05, 0xDA, 0x8F, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x26, 0x73, 0xBC, 0xE4, 0x29, 0x62, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x95, 0x17, 0x8B, 0xC3, 0x9B, 0xAC, 0xCC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xDB, 0x77, 0xDF, 0xDD, 0x13, 0x04, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xFC, 0x22, 0x93, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0xF1, 0x5A, 0x37, 0xEF, 0x79, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x37, 0xAC, 0x9A, 0x5B, 0x51, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x75, 0x13, 0xA9, 0x4A, 0xAD, 0xFE, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x82, 0x6F, 0x66, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x5E, 0xF0, 0x40, 0xC3, 0xA6, 0xE2, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x9A, 0x6F, 0xCF, 0x11, 0x26, 0x66, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x73, 0xA8, 0xCF, 0x2B, 0x12, 0x36, 0x37),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xB3, 0x0A, 0x58, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x79, 0x00, 0x55, 0x04, 0x34, 0x90, 0x1A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x54, 0x1C, 0xC2, 0x45, 0x0C, 0x1B, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x19, 0xAB, 0xA8, 0xFC, 0x73, 0xDC, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xFB, 0x93, 0xCE, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x75, 0xD0, 0x66, 0x95, 0x86, 0xCA, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xEA, 0x29, 0x16, 0x6A, 0x38, 0xDF, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA2, 0x36, 0x2F, 0xDC, 0xBB, 0x5E, 0xF7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x89, 0x59, 0x49, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xA3, 0x99, 0x9D, 0xB8, 0x77, 0x9D, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x93, 0x43, 0x47, 0xC6, 0x5C, 0xF9, 0xFD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x00, 0x79, 0x42, 0x64, 0xB8, 0x25, 0x3E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x54, 0xB4, 0x33, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x0C, 0x42, 0x90, 0x83, 0x0B, 0x31, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2E, 0xAE, 0xC8, 0xC7, 0x5F, 0xD2, 0x70),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xBC, 0xAD, 0x41, 0xE7, 0x32, 0x3A, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x97, 0x52, 0x83, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x13, 0x7A, 0xBD, 0xAE, 0x94, 0x60, 0xFD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x9B, 0x95, 0xB4, 0x6E, 0x68, 0xB2, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x49, 0xBE, 0x51, 0xFE, 0x66, 0x15, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x37, 0xE4, 0xFE, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x9B, 0xEE, 0x64, 0xC9, 0x1B, 0xBD, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x5F, 0x34, 0xA9, 0x0B, 0xB7, 0x25, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x13, 0xB1, 0x38, 0xFB, 0x9D, 0x78, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xE7, 0x1B, 0xFA, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xB3, 0xB7, 0x44, 0x92, 0x6B, 0x00, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x82, 0x44, 0x3E, 0x18, 0x1A, 0x58, 0x6A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF8, 0xC0, 0xE4, 0xEE, 0xC1, 0xBF, 0x44),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x32, 0x27, 0xB2, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x9A, 0x42, 0x62, 0x8B, 0x26, 0x54, 0x21),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x85, 0x74, 0xA0, 0x79, 0xA8, 0xEE, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0x60, 0xB3, 0x28, 0x4D, 0x55, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x27, 0x82, 0x29, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xFC, 0x73, 0x77, 0xAF, 0x5C, 0xAC, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xED, 0xE5, 0xF6, 0x1D, 0xA8, 0x67, 0x43),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xDE, 0x33, 0x1C, 0xF1, 0x80, 0x73, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE2, 0xDE, 0x3C, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x3E, 0x6B, 0xFE, 0xF0, 0x04, 0x28, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xB2, 0x14, 0x9D, 0x18, 0x11, 0x7D, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC4, 0xD6, 0x2E, 0x6E, 0x57, 0x4D, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x55, 0x1B, 0xDE, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xF7, 0x17, 0xBC, 0x45, 0xAB, 0x16, 0xAB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xB0, 0xEF, 0x61, 0xE3, 0x20, 0x7C, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x85, 0x41, 0x4D, 0xF1, 0x7E, 0x4D, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC2, 0x9B, 0x5E, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x2E, 0x49, 0x3D, 0x3E, 0x4B, 0xD3, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x2B, 0x9D, 0xD5, 0x27, 0xFA, 0xCA, 0xE0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xB3, 0x6A, 0xE0, 0x79, 0x14, 0x28, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x1E, 0xDC, 0xF5, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x44, 0x56, 0xCD, 0xFC, 0x9F, 0x09, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x8C, 0x59, 0xA4, 0x64, 0x2A, 0x3A, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xA0, 0xB5, 0x86, 0x4E, 0x69, 0xDA, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x8B, 0x11, 0x38, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x17, 0x16, 0x12, 0x17, 0xDC, 0x00, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x76, 0x24, 0x6C, 0x97, 0x2C, 0xB5, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x71, 0xE3, 0xB0, 0xBB, 0x4E, 0x50, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x48, 0x26, 0xD5, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x5F, 0x28, 0xF6, 0x01, 0x5A, 0x60, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x95, 0xFE, 0xD0, 0xAD, 0x15, 0xD4, 0xD9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0x7A, 0xFD, 0x80, 0xF7, 0x9F, 0x64),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xBC, 0x1B, 0xDF, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xE6, 0xDF, 0x14, 0x29, 0xF4, 0xD4, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x12, 0xDD, 0xEC, 0x5B, 0x8A, 0x59, 0xE5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x92, 0x3E, 0x35, 0x08, 0xE9, 0xCF, 0x0E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x35, 0x29, 0x97, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xDB, 0xD6, 0x6A, 0xC5, 0x43, 0xA4, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x33, 0x50, 0x61, 0x70, 0xA1, 0xE9, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x15, 0x6E, 0x5F, 0x01, 0x0C, 0x8C, 0xFA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xA1, 0x9A, 0x9D, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xC6, 0xF7, 0xE2, 0x4A, 0xCD, 0x9B, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x4D, 0x5A, 0xB8, 0xE2, 0x6D, 0xA6, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3F, 0xB6, 0x17, 0xE3, 0x2C, 0x6F, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA4, 0x59, 0x51, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x4F, 0x7C, 0x49, 0xCD, 0x6E, 0xEB, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xC9, 0x1F, 0xB7, 0x4D, 0x98, 0xC7, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xFD, 0x98, 0x20, 0x95, 0xBB, 0x20, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF2, 0x73, 0x92, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xEF, 0xFB, 0x30, 0xFA, 0x12, 0x1A, 0xB0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x4C, 0x24, 0xB4, 0x5B, 0xC9, 0x4C, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xDD, 0x5E, 0x84, 0x95, 0x4D, 0x26, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xFA, 0xF9, 0x3A, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xA3, 0x2E, 0x7A, 0xDC, 0xA7, 0x53, 0xA9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x9F, 0x81, 0x84, 0xB2, 0x0D, 0xFE, 0x31),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x89, 0x1B, 0x77, 0x0C, 0x89, 0x71, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0x7F, 0xB2, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xE9, 0x2C, 0x79, 0xA6, 0x3C, 0xAD, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE0, 0x23, 0x02, 0x86, 0x0F, 0x77, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x93, 0x6D, 0xE9, 0xF9, 0x3C, 0xBE, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xE7, 0x24, 0x92, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x3C, 0x5B, 0x4B, 0x1B, 0x25, 0x37, 0xD6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xE8, 0x38, 0x1B, 0xA1, 0x5A, 0x2E, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x19, 0xFD, 0xF4, 0x78, 0x01, 0x6B, 0x44),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x69, 0x37, 0x4F, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xE2, 0xBF, 0xD3, 0xEC, 0x95, 0x9C, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x7B, 0xFC, 0xD5, 0xD3, 0x25, 0x5E, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x55, 0x09, 0xA2, 0x58, 0x6A, 0xC9, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xCC, 0x3B, 0xD9, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x08, 0x65, 0x5E, 0xCB, 0xAB, 0x48, 0xC8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x79, 0x8B, 0xC0, 0x11, 0xC0, 0x69, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xE8, 0x8C, 0x4C, 0xC5, 0x28, 0xE4, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x1F, 0x34, 0x5C, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_ecp_point secp224k1_T[16] = {
+    ECP_POINT_INIT_XY_Z1(secp224k1_T_0_X, secp224k1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_1_X, secp224k1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_2_X, secp224k1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_3_X, secp224k1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_4_X, secp224k1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_5_X, secp224k1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_6_X, secp224k1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_7_X, secp224k1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_8_X, secp224k1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_9_X, secp224k1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_10_X, secp224k1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_11_X, secp224k1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_12_X, secp224k1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_13_X, secp224k1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_14_X, secp224k1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_15_X, secp224k1_T_15_Y),
+};
+#else
+#define secp224k1_T NULL
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+static const mbedtls_mpi_uint secp256k1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+static const mbedtls_mpi_uint secp256k1_a[] = {
+    MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp256k1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_2(0x07, 0x00),
+};
+static const mbedtls_mpi_uint secp256k1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79),
+};
+static const mbedtls_mpi_uint secp256k1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48),
+};
+static const mbedtls_mpi_uint secp256k1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint secp256k1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79),
+};
+static const mbedtls_mpi_uint secp256k1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48),
+};
+static const mbedtls_mpi_uint secp256k1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xEE, 0xD7, 0x1E, 0x67, 0x86, 0x32, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0xB1, 0xA9, 0xD5, 0xCC, 0x27, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0E, 0x11, 0x01, 0x71, 0xFE, 0x92, 0x73),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x28, 0x63, 0x6D, 0x72, 0x09, 0xA6, 0xC0),
+};
+static const mbedtls_mpi_uint secp256k1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0x69, 0xDC, 0x3E, 0x2C, 0x75, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xB7, 0x3F, 0x30, 0x26, 0x3C, 0xDF, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBE, 0xB9, 0x5D, 0x0E, 0xE8, 0x5E, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xC3, 0x05, 0xD6, 0xB7, 0xD5, 0x24, 0xFC),
+};
+static const mbedtls_mpi_uint secp256k1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCF, 0x7B, 0xDC, 0xCD, 0xC3, 0x39, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xDA, 0xB9, 0xE5, 0x64, 0xA7, 0x47, 0x91),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x46, 0xA8, 0x61, 0xF6, 0x23, 0xEB, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xC1, 0xFF, 0xE4, 0x55, 0xD5, 0xC2, 0xBF),
+};
+static const mbedtls_mpi_uint secp256k1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xBE, 0xB9, 0x59, 0x24, 0x13, 0x4A, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x45, 0x12, 0xDE, 0xBA, 0x4F, 0xEF, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x08, 0xBF, 0xC1, 0x66, 0xAA, 0x0A, 0xBC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xFE, 0x30, 0x55, 0x31, 0x86, 0xA7, 0xB4),
+};
+static const mbedtls_mpi_uint secp256k1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBF, 0x18, 0x81, 0x67, 0x27, 0x42, 0xBD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x05, 0x83, 0xA4, 0xDD, 0x57, 0xD3, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x63, 0xAB, 0xE4, 0x90, 0x70, 0xD0, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x5D, 0xFD, 0xA0, 0xEF, 0xCF, 0x1C, 0x54),
+};
+static const mbedtls_mpi_uint secp256k1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x80, 0xE4, 0xF6, 0x09, 0xBC, 0x57, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x9F, 0x6E, 0x88, 0x54, 0x6E, 0x51, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x5F, 0x85, 0xFB, 0x84, 0x3E, 0x4A, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x19, 0xF5, 0x55, 0xC9, 0x07, 0xD8, 0xCE),
+};
+static const mbedtls_mpi_uint secp256k1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xB4, 0xC3, 0xD9, 0x5C, 0xA0, 0xD4, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x30, 0xAF, 0x59, 0x9B, 0xF8, 0x04, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xA6, 0xFD, 0x66, 0x7B, 0xC3, 0x39, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xBF, 0xF0, 0xC2, 0xE9, 0x71, 0xA4, 0x9E),
+};
+static const mbedtls_mpi_uint secp256k1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x2D, 0xB9, 0x88, 0x28, 0xF1, 0xBE, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF3, 0x1A, 0x0E, 0xB9, 0x01, 0x66, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0xA4, 0xF4, 0x05, 0xD0, 0xAA, 0x53),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x39, 0x1E, 0x47, 0xE5, 0x68, 0xC8, 0xC0),
+};
+static const mbedtls_mpi_uint secp256k1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xB9, 0xFC, 0xE0, 0x33, 0x8A, 0x7D, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x93, 0xA5, 0x53, 0x55, 0x16, 0xB4, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x5F, 0xEA, 0x9B, 0x29, 0x52, 0x71, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xF0, 0x24, 0xB8, 0x7D, 0xB7, 0xA0, 0x9B),
+};
+static const mbedtls_mpi_uint secp256k1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x00, 0x27, 0xB2, 0xDF, 0x73, 0xA2, 0xE0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x2E, 0x4D, 0x7C, 0xDE, 0x7A, 0x23, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0x60, 0xC7, 0x97, 0x1E, 0xA4, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x13, 0x5B, 0x77, 0x59, 0xCB, 0x36, 0xE1),
+};
+static const mbedtls_mpi_uint secp256k1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xBC, 0x9F, 0x9E, 0x2D, 0x53, 0x2A, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x5F, 0x64, 0x9F, 0x1A, 0x19, 0xE6, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x7B, 0x39, 0xD2, 0xDB, 0x85, 0x84, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xC7, 0x0D, 0x58, 0x6E, 0x3F, 0x52, 0x15),
+};
+static const mbedtls_mpi_uint secp256k1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x68, 0x19, 0x0B, 0x68, 0xC9, 0x1E, 0xFB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x4E, 0x21, 0x49, 0x3D, 0x55, 0xCC, 0x25),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF9, 0x25, 0x45, 0x54, 0x45, 0xB1, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xF7, 0xCD, 0x80, 0xA4, 0x04, 0x05),
+};
+static const mbedtls_mpi_uint secp256k1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x1E, 0x88, 0xC4, 0xAA, 0x18, 0x7E, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xAC, 0xD9, 0xB2, 0xA1, 0xC0, 0x71, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xA2, 0xF1, 0x15, 0xA6, 0x5F, 0x6C, 0x86),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x5B, 0x05, 0xBC, 0xB7, 0xC6, 0x4E, 0x72),
+};
+static const mbedtls_mpi_uint secp256k1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x80, 0xF8, 0x5C, 0x20, 0x2A, 0xE1, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x48, 0x2E, 0x68, 0x82, 0x7F, 0xEB, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x3B, 0x25, 0xDB, 0x32, 0x4D, 0x88, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x6E, 0xA6, 0xB6, 0x6D, 0x62, 0x78, 0x22),
+};
+static const mbedtls_mpi_uint secp256k1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4D, 0x3E, 0x86, 0x58, 0xC3, 0xEB, 0xBA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x89, 0x33, 0x18, 0x21, 0x1D, 0x9B, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x9D, 0xFF, 0xC3, 0x79, 0xC1, 0x88, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xD4, 0x48, 0x53, 0xE8, 0xAD, 0x21, 0x16),
+};
+static const mbedtls_mpi_uint secp256k1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x7B, 0xDE, 0xCB, 0xD8, 0x39, 0x17, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xF3, 0x03, 0xF2, 0x5C, 0xBC, 0xC8, 0x8A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xAE, 0x4C, 0xB0, 0x16, 0xA4, 0x93, 0x86),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8B, 0x6B, 0xDC, 0xD7, 0x9A, 0x3E, 0x7E),
+};
+static const mbedtls_mpi_uint secp256k1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x2D, 0x7A, 0xD2, 0x59, 0x05, 0xA2, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x56, 0x09, 0x32, 0xF1, 0xE8, 0xE3, 0x72),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xCA, 0xE5, 0x2E, 0xF0, 0xFB, 0x18, 0x19),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x85, 0xA9, 0x23, 0x15, 0x31, 0x1F, 0x0E),
+};
+static const mbedtls_mpi_uint secp256k1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xE5, 0xB1, 0x86, 0xB9, 0x6E, 0x8D, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x77, 0xFC, 0xC9, 0xA3, 0x3F, 0x89, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x6A, 0xDC, 0x25, 0xB0, 0xC7, 0x41, 0x54),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x11, 0x6B, 0xA6, 0x11, 0x62, 0xD4, 0x2D),
+};
+static const mbedtls_mpi_uint secp256k1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7D, 0x34, 0xB3, 0x20, 0x7F, 0x37, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xD4, 0x45, 0xE8, 0xC2, 0xE9, 0xC5, 0xEA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x32, 0x3B, 0x25, 0x7E, 0x79, 0xAF, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xE4, 0x54, 0x71, 0xBE, 0x35, 0x4E, 0xD0),
+};
+static const mbedtls_mpi_uint secp256k1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x94, 0xDD, 0x8F, 0xB5, 0xC2, 0xDD, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x49, 0xE9, 0x1C, 0x2F, 0x08, 0x49, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xB6, 0x03, 0x88, 0x6F, 0xB8, 0x15, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xD3, 0x1C, 0xF3, 0xA5, 0xEB, 0x79, 0x01),
+};
+static const mbedtls_mpi_uint secp256k1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF9, 0x43, 0x88, 0x89, 0x0D, 0x06, 0xEA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2D, 0xF5, 0x98, 0x32, 0xF6, 0xB1, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0x8F, 0x2B, 0x50, 0x27, 0x0A, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE3, 0xBD, 0x16, 0x05, 0xC8, 0x93, 0x12),
+};
+static const mbedtls_mpi_uint secp256k1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x6A, 0xF7, 0xE3, 0x3D, 0xDE, 0x5F, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA3, 0x9C, 0x22, 0x3C, 0x33, 0x36, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x24, 0x4C, 0x69, 0x45, 0x78, 0x14, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xF8, 0xD4, 0xBF, 0xB8, 0xC0, 0xA1, 0x25),
+};
+static const mbedtls_mpi_uint secp256k1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x88, 0xE1, 0x91, 0x03, 0xEB, 0xB3, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x11, 0xA1, 0xEF, 0x14, 0x0D, 0xC4, 0x7D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xD4, 0x0D, 0x1D, 0x96, 0x33, 0x5C, 0x19),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x45, 0x2A, 0x1A, 0xE6, 0x57, 0x04, 0x9B),
+};
+static const mbedtls_mpi_uint secp256k1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xB5, 0xA7, 0x80, 0xE9, 0x93, 0x97, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xB9, 0x7C, 0xA0, 0xC9, 0x57, 0x26, 0x43),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xEF, 0x56, 0xDA, 0x66, 0xF6, 0x1B, 0x9A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x89, 0x6B, 0x91, 0xE0, 0xA9, 0x65, 0x2B),
+};
+static const mbedtls_mpi_uint secp256k1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x98, 0x96, 0x9B, 0x06, 0x7D, 0x5E, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xFA, 0xC1, 0x5F, 0x19, 0x37, 0x94, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xBE, 0x6B, 0x1A, 0x05, 0xE4, 0xBF, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xCD, 0x5D, 0x35, 0xB4, 0x51, 0xF7, 0x64),
+};
+static const mbedtls_mpi_uint secp256k1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xEF, 0x96, 0xDB, 0xF2, 0x61, 0x63, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x04, 0x88, 0xC9, 0x9F, 0x1B, 0x94, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x30, 0x79, 0x7E, 0x24, 0xE7, 0x5F, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xB8, 0x90, 0xB7, 0x94, 0x25, 0xBB, 0x0F),
+};
+static const mbedtls_mpi_uint secp256k1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x79, 0xEA, 0xAD, 0xC0, 0x6D, 0x18, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xA4, 0x58, 0x2A, 0x8D, 0x95, 0xB3, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC4, 0xC2, 0x12, 0x0D, 0x79, 0xE2, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6F, 0xBE, 0x97, 0x4D, 0xA4, 0x20, 0x07),
+};
+static const mbedtls_mpi_uint secp256k1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x31, 0x71, 0xC6, 0xA6, 0x91, 0xEB, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x9B, 0xA8, 0x4A, 0xE7, 0x77, 0xE1, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x06, 0xD3, 0x3D, 0x94, 0x30, 0xEF, 0x8C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xDF, 0xCA, 0xFA, 0xF5, 0x28, 0xF8, 0xC9),
+};
+static const mbedtls_mpi_uint secp256k1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xE1, 0x32, 0xFD, 0x3E, 0x81, 0xF8, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xF2, 0x4B, 0x1D, 0x19, 0xC9, 0x0F, 0xCC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB1, 0x8A, 0x22, 0x8B, 0x05, 0x6B, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x21, 0xEF, 0x30, 0xEC, 0x09, 0x2A, 0x89),
+};
+static const mbedtls_mpi_uint secp256k1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x84, 0x4A, 0x46, 0x07, 0x6C, 0x3C, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x18, 0x3A, 0xF4, 0xCC, 0xF5, 0xB2, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x8F, 0xCD, 0x0A, 0x9C, 0xF4, 0xBD, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x89, 0x7F, 0x8A, 0xB1, 0x52, 0x3A, 0xAB),
+};
+static const mbedtls_ecp_point secp256k1_T[16] = {
+    ECP_POINT_INIT_XY_Z1(secp256k1_T_0_X, secp256k1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_1_X, secp256k1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_2_X, secp256k1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_3_X, secp256k1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_4_X, secp256k1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_5_X, secp256k1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_6_X, secp256k1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_7_X, secp256k1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_8_X, secp256k1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_9_X, secp256k1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_10_X, secp256k1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_11_X, secp256k1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_12_X, secp256k1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_13_X, secp256k1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_14_X, secp256k1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_15_X, secp256k1_T_15_Y),
+};
+#else
+#define secp256k1_T NULL
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
+
+/*
+ * Domain parameters for brainpoolP256r1 (RFC 5639 3.4)
+ */
+#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
+static const mbedtls_mpi_uint brainpoolP256r1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_a[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9),
+};
+
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint brainpoolP256r1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xA2, 0xED, 0x52, 0xC9, 0x8C, 0xE3, 0xA5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xC9, 0xC4, 0x87, 0x3F, 0x93, 0x7A, 0xD1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x12, 0x53, 0x61, 0x3E, 0x76, 0x08, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x8C, 0x74, 0xF4, 0x08, 0xC3, 0x76, 0x80),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xDD, 0x09, 0xA6, 0xED, 0xEE, 0xC4, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xD9, 0xBE, 0x4B, 0xA5, 0xB7, 0x2B, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x20, 0x12, 0xCA, 0x0A, 0x38, 0x24, 0xAB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x72, 0x71, 0x90, 0x7A, 0x2E, 0xB7, 0x23),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0xA1, 0x93, 0x10, 0x2A, 0x51, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x10, 0x11, 0x12, 0xBC, 0xB0, 0xB6, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x58, 0xD7, 0x0A, 0x84, 0x05, 0xA3, 0x9C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x8E, 0x95, 0x61, 0xD3, 0x0B, 0xDF, 0x36),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x92, 0x12, 0x0F, 0x5E, 0x87, 0x70, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xE9, 0x9B, 0xEB, 0x3A, 0xFB, 0xCF, 0xC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0x92, 0xB9, 0xF7, 0x45, 0xD3, 0x06, 0xB6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x28, 0x65, 0xE1, 0xC5, 0x6C, 0x57, 0x18),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x0E, 0x77, 0x01, 0x81, 0x9E, 0x38, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xF0, 0xD5, 0xA5, 0x91, 0x2B, 0xDF, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xEE, 0xB6, 0x25, 0xD6, 0x98, 0xDE, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0x55, 0x63, 0x39, 0xEB, 0xB5, 0x47),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD6, 0xB8, 0xE3, 0x13, 0xED, 0x7F, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xE8, 0xAE, 0x36, 0xB8, 0xCD, 0x19, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x82, 0x83, 0x7A, 0x7B, 0x46, 0x56, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x60, 0x46, 0x15, 0x5A, 0xAC, 0x99, 0x30),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x61, 0x50, 0xC6, 0xFF, 0x10, 0x7D, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x51, 0xDF, 0xA9, 0x7D, 0x78, 0x26, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x15, 0x9A, 0xF7, 0x01, 0xC1, 0xBB, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x0F, 0xE6, 0x2A, 0xBD, 0x4A, 0x9E, 0x87),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF8, 0xD1, 0x77, 0xD2, 0x49, 0xB3, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x86, 0xFB, 0x9E, 0x1F, 0x5A, 0x60, 0x47),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xC4, 0x8D, 0xCD, 0x86, 0x61, 0x2F, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xF6, 0xB9, 0xAC, 0x37, 0x9D, 0xE9, 0x28),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x77, 0xAA, 0x97, 0x9C, 0x0B, 0x04, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xA6, 0x60, 0x81, 0xCE, 0x25, 0x13, 0x3E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x00, 0xF3, 0xBB, 0x82, 0x99, 0x95, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0xCE, 0x90, 0x71, 0x38, 0x2F, 0x10),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x1A, 0xC0, 0x84, 0x27, 0xD6, 0x9D, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x37, 0x52, 0x16, 0x13, 0x0E, 0xCE, 0x92),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBF, 0x5A, 0xDB, 0xDB, 0x6E, 0x1E, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB7, 0x5E, 0xF9, 0x86, 0xDD, 0x8A, 0x5C),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xAB, 0x5C, 0x8D, 0x1D, 0xF2, 0x2D, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC5, 0xF8, 0xF7, 0x1D, 0x96, 0x0B, 0x4D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x4C, 0xA7, 0x45, 0x20, 0x6A, 0x1E, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x5D, 0xEF, 0xDE, 0xEE, 0x39, 0x44, 0x19),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x2F, 0x6D, 0x52, 0xC9, 0x58, 0x60, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xC9, 0x62, 0xCB, 0x38, 0x3C, 0x55, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xA5, 0x09, 0x10, 0x88, 0xDB, 0xE3, 0xBD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xE0, 0x3C, 0xCE, 0x06, 0x0B, 0x4B, 0x5D),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x1D, 0xB4, 0x10, 0x76, 0x8F, 0xBA, 0x09),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x70, 0x5A, 0x07, 0xF5, 0x1A, 0x74, 0xC7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xE9, 0x94, 0xA8, 0xC0, 0xD5, 0x4A, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x6D, 0xD4, 0xE8, 0x9B, 0xE9, 0x6D, 0x0E),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x00, 0x32, 0x41, 0x57, 0x84, 0x89, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC7, 0x14, 0xEC, 0xE9, 0x27, 0xFF, 0xF3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x67, 0x9E, 0xFB, 0xB6, 0xB8, 0x96, 0xF3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x4A, 0xE3, 0x97, 0x4B, 0x58, 0xDE, 0x30),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x1E, 0x5C, 0xF5, 0x7F, 0xD5, 0xD4, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x08, 0x7A, 0xF1, 0xBD, 0x89, 0xC7, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xF9, 0x11, 0x1B, 0xF5, 0x3C, 0x6D, 0x8C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x50, 0xE5, 0x69, 0x1D, 0x59, 0xFC, 0x0C),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x2F, 0xF8, 0x3F, 0xEC, 0x55, 0x99, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xA7, 0x29, 0x90, 0x43, 0x81, 0x31, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x18, 0x44, 0x50, 0x5D, 0x76, 0xCB, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xC5, 0x5B, 0x9A, 0x03, 0xE6, 0x17, 0x39),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x89, 0xFC, 0x55, 0x94, 0x91, 0x6A, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x46, 0x35, 0xF2, 0x3A, 0x42, 0x08, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xD2, 0x76, 0x49, 0x42, 0x87, 0xD3, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xEA, 0xA0, 0x52, 0xF1, 0x6A, 0x30, 0x57),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xB2, 0x57, 0xA3, 0x8A, 0x4D, 0x1B, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xA3, 0x99, 0x94, 0xB5, 0x3D, 0x64, 0x09),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC3, 0xD7, 0x53, 0xF6, 0x49, 0x1C, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x23, 0x41, 0x4D, 0xFB, 0x7A, 0x5C, 0x53),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xB8, 0x15, 0x65, 0x5C, 0x85, 0x94, 0xD7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x37, 0xC7, 0xF8, 0x7E, 0xAE, 0x6C, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xD8, 0x11, 0x54, 0x98, 0x44, 0xE3, 0xF1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x4D, 0xA6, 0x4B, 0x28, 0xF2, 0x57, 0x9E),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD0, 0xEB, 0x1E, 0xAA, 0x30, 0xD3, 0x6A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x9B, 0x4D, 0xA7, 0x73, 0x6E, 0xB6, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x47, 0xF6, 0xED, 0x37, 0xEF, 0x71, 0x4D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xB5, 0x49, 0x61, 0x5E, 0x45, 0xF6, 0x4A),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x0E, 0xB3, 0x84, 0x3A, 0x63, 0x72, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x53, 0x5C, 0xA7, 0xC6, 0x2E, 0xAB, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x0F, 0x8F, 0x87, 0x50, 0x28, 0xB4, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x98, 0x4A, 0x98, 0x31, 0x86, 0xCA, 0x51),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC9, 0xE2, 0xFD, 0x5D, 0x1F, 0xE8, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x90, 0x91, 0xC4, 0x84, 0xF0, 0xBA, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5A, 0xB3, 0x4E, 0xFB, 0xE0, 0x57, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x0B, 0x90, 0xA6, 0xFD, 0x9D, 0x8E, 0x02),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x41, 0x8F, 0x31, 0xFA, 0x5A, 0xF6, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xE9, 0xE3, 0xF6, 0xE0, 0x4A, 0xE7, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x4E, 0xCD, 0xA2, 0x22, 0x14, 0xD4, 0x12),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xED, 0x21, 0xB7, 0x0F, 0x53, 0x10, 0x17),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x06, 0x24, 0x2C, 0x4E, 0xD1, 0x1E, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x3F, 0xC1, 0x9F, 0xAB, 0xF0, 0x37, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x5E, 0x12, 0xCE, 0x83, 0x1B, 0x2A, 0x18),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x65, 0xCF, 0xE8, 0x5C, 0xA5, 0xA2, 0x70),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x86, 0x76, 0x3A, 0x94, 0xF6, 0x1D, 0xC1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xDA, 0xC9, 0xA6, 0x29, 0x93, 0x15, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x61, 0x6A, 0x7D, 0xC7, 0xA9, 0xF3, 0x76),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x03, 0x71, 0xA2, 0x15, 0xCE, 0x50, 0x72),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD0, 0xA8, 0x1E, 0x91, 0xC4, 0x4F, 0x24),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x4B, 0x7E, 0xD7, 0x71, 0x58, 0x7E, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x45, 0xAF, 0x2A, 0x18, 0x93, 0x95, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x8F, 0xC7, 0xFA, 0x4C, 0x7A, 0x86, 0x54),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xAF, 0x68, 0x3A, 0x23, 0xC1, 0x2E, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x50, 0x11, 0x67, 0x39, 0xB9, 0xAF, 0x48),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x86, 0xAA, 0x1E, 0x88, 0x21, 0x29, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x28, 0xA4, 0x9D, 0x89, 0xA9, 0x9A, 0x10),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBA, 0x04, 0x67, 0xB7, 0x01, 0x40, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xE9, 0x09, 0xA3, 0xCA, 0xA6, 0x37, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x97, 0xA8, 0xB6, 0x3C, 0xEE, 0x90, 0x3D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xED, 0xC4, 0xF7, 0xC3, 0x95, 0xEC, 0x85),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x84, 0xBD, 0xEB, 0xD5, 0x64, 0xBB, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x9B, 0xE2, 0x28, 0x50, 0xC2, 0x72, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xF2, 0x74, 0xD1, 0x26, 0xBF, 0x32, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xCB, 0xAF, 0x72, 0xDB, 0x6D, 0x30, 0x98),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x50, 0x85, 0xF4, 0x2B, 0x48, 0xC1, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x28, 0xBB, 0x11, 0xBA, 0x5B, 0x22, 0x6C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA1, 0xE5, 0x5C, 0xC9, 0x1D, 0x44, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xE8, 0xE6, 0x6F, 0xBB, 0xC1, 0x81, 0x7F),
+};
+static const mbedtls_ecp_point brainpoolP256r1_T[16] = {
+    ECP_POINT_INIT_XY_Z1(brainpoolP256r1_T_0_X, brainpoolP256r1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_1_X, brainpoolP256r1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_2_X, brainpoolP256r1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_3_X, brainpoolP256r1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_4_X, brainpoolP256r1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_5_X, brainpoolP256r1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_6_X, brainpoolP256r1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_7_X, brainpoolP256r1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_8_X, brainpoolP256r1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_9_X, brainpoolP256r1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_10_X, brainpoolP256r1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_11_X, brainpoolP256r1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_12_X, brainpoolP256r1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_13_X, brainpoolP256r1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_14_X, brainpoolP256r1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_15_X, brainpoolP256r1_T_15_Y),
+};
+#else
+#define brainpoolP256r1_T NULL
+#endif
+
+#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */
+
+/*
+ * Domain parameters for brainpoolP384r1 (RFC 5639 3.6)
+ */
+#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
+static const mbedtls_mpi_uint brainpoolP384r1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_a[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C),
+};
+
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint brainpoolP384r1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xD8, 0x8A, 0x54, 0x41, 0xD6, 0x6B, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x3B, 0xF1, 0x22, 0xFD, 0x2D, 0x4B, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x55, 0xE3, 0x33, 0xF0, 0x73, 0x52, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x3F, 0x30, 0x26, 0xCA, 0x7F, 0x52, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x6E, 0x17, 0x9B, 0xD5, 0x2A, 0x4A, 0x31),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xDA, 0x6B, 0xE5, 0x03, 0x07, 0x1D, 0x2E),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x7A, 0xAF, 0x98, 0xE3, 0xA4, 0xF6, 0x19),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x7D, 0xFE, 0x51, 0x40, 0x3B, 0x47, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x88, 0xEC, 0xC4, 0xE2, 0x8F, 0xCB, 0xA4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xE2, 0x88, 0x2D, 0x4E, 0x50, 0xEB, 0x9A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x54, 0x94, 0x5E, 0xF4, 0x7F, 0x3A, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x07, 0x1C, 0xE1, 0xBD, 0x0F, 0xF8, 0x63),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x92, 0x28, 0x2E, 0x32, 0x04, 0xB1, 0x4D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x82, 0x44, 0x43, 0x76, 0x0D, 0x55, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xE3, 0xFF, 0x89, 0x46, 0xDE, 0x4E, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x22, 0xBB, 0x67, 0x1A, 0x81, 0xEE, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x54, 0xE2, 0x7A, 0xAE, 0xDA, 0x2C, 0xD0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x9A, 0x90, 0xAA, 0x6E, 0x8B, 0xCC, 0x5F),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x40, 0xAC, 0xED, 0x7D, 0x37, 0x87, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xF8, 0xB1, 0x80, 0x4C, 0x8C, 0x04, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x98, 0x2C, 0xAD, 0x30, 0x69, 0x35, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x2E, 0x00, 0x2F, 0x44, 0x8C, 0xF0, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x58, 0x07, 0xD7, 0xCD, 0x60, 0xA1, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFB, 0x7B, 0x03, 0x05, 0x5E, 0x79, 0x73),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x17, 0xCE, 0x38, 0x4B, 0x5E, 0x5B, 0xC8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x0E, 0x0A, 0x61, 0x9D, 0x7C, 0x62, 0x08),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF0, 0x98, 0x71, 0x7F, 0x17, 0x26, 0xD7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xD3, 0xFA, 0x3C, 0xF0, 0x70, 0x07, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x47, 0x5C, 0x09, 0x43, 0xB7, 0x65, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xA7, 0x3E, 0xFA, 0xF3, 0xEC, 0x22),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x78, 0x22, 0x2B, 0x58, 0x71, 0xFA, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x30, 0xCE, 0x6A, 0xB3, 0xB0, 0x4F, 0x83),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x95, 0x20, 0xA9, 0x23, 0xC2, 0x65, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xCF, 0x03, 0x5B, 0x8A, 0x80, 0x44, 0xBB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xF8, 0x91, 0xF7, 0xD5, 0xED, 0xEA, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x5B, 0x16, 0x10, 0x25, 0xAC, 0x2A, 0x17),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEC, 0xDC, 0xC4, 0x7B, 0x8C, 0x6B, 0xE9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBB, 0x1C, 0xD3, 0x5A, 0xEE, 0xD9, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5D, 0x30, 0x5E, 0xF7, 0xB2, 0x41, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xCE, 0x0F, 0x1A, 0xC6, 0x41, 0x64, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x18, 0xE1, 0xE3, 0x82, 0x15, 0x66, 0x4B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xE2, 0x24, 0x04, 0x72, 0x39, 0xA0, 0x7C),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x51, 0xA2, 0x58, 0x88, 0x62, 0xE1, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xD2, 0x65, 0x14, 0xE9, 0x4C, 0x82, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE1, 0xAC, 0x87, 0xAE, 0x31, 0x1A, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4F, 0x96, 0x1E, 0x85, 0x7A, 0xC3, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x86, 0xBB, 0xF0, 0xC0, 0x9D, 0x08, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x53, 0x03, 0x09, 0x80, 0x91, 0xEF, 0x68),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xD7, 0xAF, 0x6F, 0x69, 0x7B, 0x88, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x13, 0xE4, 0x30, 0xA2, 0x47, 0xB5, 0xC1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD2, 0xC0, 0xDD, 0x8A, 0x1C, 0x3C, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x8C, 0xB3, 0x4C, 0xBA, 0x8B, 0x6D, 0xCF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xC7, 0xA1, 0xA8, 0x6E, 0x3C, 0x4F, 0xF1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x4A, 0x97, 0xC8, 0x03, 0x6F, 0x01, 0x82),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x18, 0x12, 0xA9, 0x39, 0xD5, 0x22, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA7, 0xC0, 0xBD, 0x9D, 0x8D, 0x78, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xD0, 0x7F, 0xDF, 0xD0, 0x30, 0xDE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x73, 0x96, 0xEC, 0xA8, 0x1D, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xD1, 0x65, 0x66, 0xDC, 0xD9, 0xCF, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xED, 0x7B, 0x37, 0xAD, 0xE2, 0xBE, 0x2D),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x79, 0x42, 0x6A, 0x07, 0x66, 0xB1, 0xBD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x53, 0x62, 0x65, 0x92, 0x09, 0x4C, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xAF, 0xC3, 0x03, 0xF6, 0xF4, 0x2D, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xCA, 0x41, 0xD9, 0xA2, 0x69, 0x9B, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xB2, 0xA6, 0x8D, 0xE1, 0xAA, 0x61, 0x76),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xBA, 0x4D, 0x12, 0xB6, 0xBE, 0xF3, 0x7E),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x92, 0x22, 0x07, 0xCE, 0xC9, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA1, 0x7C, 0x91, 0xDB, 0x32, 0xF7, 0xE5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x49, 0x4B, 0x6D, 0xFB, 0xD9, 0x70, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xFB, 0x4E, 0x4C, 0x5E, 0x66, 0x81, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xB3, 0xE1, 0x00, 0xB7, 0xD9, 0xCC, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x36, 0x8B, 0xC4, 0x39, 0x20, 0xFD, 0x30),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x1F, 0x60, 0x03, 0xBB, 0xD7, 0x60, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x3C, 0x62, 0xDD, 0x71, 0x95, 0xE9, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x5B, 0x7A, 0x5F, 0x68, 0x81, 0xC5, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xB5, 0xB9, 0x98, 0x42, 0x28, 0xA5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x29, 0x8E, 0x11, 0x49, 0xB4, 0xD7, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x3E, 0xD2, 0x30, 0xA1, 0xBA, 0xCA, 0x03),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x37, 0x64, 0x44, 0x2F, 0x03, 0xE5, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x42, 0xBC, 0xFF, 0xA2, 0x1A, 0x5F, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x04, 0xAB, 0x04, 0xE0, 0x24, 0xAD, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x45, 0x17, 0x67, 0x1F, 0x3E, 0x53, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x0F, 0xB3, 0x1B, 0x57, 0x54, 0xC2, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0xF8, 0xC4, 0x1B, 0x9B, 0xFA, 0x30),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x90, 0xFD, 0xFB, 0xCA, 0x49, 0x38, 0x4E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xCF, 0xC6, 0xDD, 0xF0, 0xFF, 0x8C, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x69, 0x9D, 0xBD, 0x5F, 0x33, 0xE9, 0xB4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x19, 0x82, 0x3D, 0xAC, 0x1C, 0x40, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC7, 0x02, 0x46, 0x14, 0x77, 0x00, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x05, 0xF2, 0x77, 0x3A, 0x66, 0x5C, 0x39),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xE6, 0x17, 0xDE, 0xB2, 0xA1, 0xE5, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x71, 0xEC, 0x9D, 0xD8, 0xF5, 0xD4, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xC6, 0x42, 0x5E, 0xE7, 0x18, 0xBA, 0xD0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x21, 0x68, 0x5A, 0x26, 0xFB, 0xD7, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x00, 0x5C, 0xBA, 0x8A, 0x34, 0xEC, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x3C, 0xAF, 0x53, 0xE8, 0x65, 0x35),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xEF, 0x28, 0xDC, 0x67, 0x05, 0xC8, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x78, 0xC3, 0x85, 0x49, 0xA0, 0xBC, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x3E, 0x2D, 0xA0, 0xCF, 0xD4, 0x7A, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x93, 0xFE, 0x60, 0xB3, 0x6E, 0x99, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xAD, 0x04, 0xE7, 0x49, 0xAF, 0x5E, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x7A, 0xED, 0xA6, 0x9E, 0x18, 0x09, 0x31),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x05, 0x94, 0x44, 0xDC, 0xB8, 0x85, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xB7, 0x37, 0xC2, 0x50, 0x75, 0x15, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xC6, 0x0F, 0xB2, 0xA9, 0x91, 0x3E, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x81, 0xAD, 0x25, 0xA1, 0x26, 0x73, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xF1, 0xD1, 0x61, 0x7C, 0x76, 0x8F, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xDB, 0x4A, 0xFF, 0x14, 0xA7, 0x48, 0x0B),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x73, 0xC6, 0xC2, 0xCC, 0xF1, 0x57, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xED, 0x73, 0x27, 0x70, 0x82, 0xB6, 0x5E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xBA, 0xAC, 0x3A, 0xCF, 0xF4, 0xEA, 0xA6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xD6, 0xB1, 0x8F, 0x0E, 0x08, 0x2C, 0x5E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE3, 0x8F, 0x2F, 0x0E, 0xA1, 0xF3, 0x07),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xF5, 0x7C, 0x9B, 0x29, 0x0A, 0xF6, 0x28),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xEE, 0x17, 0x47, 0x34, 0x15, 0xA3, 0xAF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBE, 0x88, 0x48, 0xE7, 0xA2, 0xBB, 0xDE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xAD, 0xDC, 0x65, 0x61, 0x37, 0x0F, 0xC1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x67, 0xAD, 0xA2, 0x3A, 0x1C, 0x91, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x07, 0x0C, 0x3A, 0x41, 0x6E, 0x13, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBD, 0x7E, 0xED, 0xAA, 0x14, 0xDD, 0x61),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xDC, 0x20, 0x01, 0x72, 0x11, 0x48, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xC4, 0x7B, 0xF8, 0x62, 0x3D, 0xF0, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xC2, 0x3D, 0x2E, 0x52, 0xA3, 0x4A, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE2, 0x53, 0x46, 0x5E, 0x21, 0xF8, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xC7, 0x8F, 0xA9, 0x26, 0x42, 0x32, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xA6, 0xA0, 0x8D, 0x4B, 0x9A, 0x19, 0x03),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xAB, 0x6D, 0x1E, 0xFB, 0xEE, 0x60, 0x0C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x56, 0x3C, 0xC5, 0x5D, 0x10, 0x79, 0x1C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xBC, 0x41, 0x9F, 0x71, 0xEF, 0x02, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x36, 0xC4, 0xD0, 0x88, 0x9B, 0x32, 0xFC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xD4, 0x5D, 0x17, 0x39, 0xE6, 0x22, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x26, 0x01, 0xCE, 0xBE, 0x4A, 0x9C, 0x27),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x6D, 0x11, 0xCA, 0x6C, 0x5A, 0x93, 0x0C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x96, 0x26, 0xAF, 0x2F, 0xE4, 0x30, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC1, 0x4C, 0xC6, 0x30, 0x1F, 0x5C, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB3, 0xE8, 0xFC, 0x35, 0xEB, 0x63, 0x6C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x1D, 0xCA, 0xFC, 0x50, 0x36, 0x4B, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0E, 0x23, 0x5B, 0xAF, 0xEB, 0x2D, 0x31),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x88, 0xB6, 0xD7, 0x74, 0x4A, 0x23, 0xB6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x66, 0xE2, 0xBB, 0x29, 0xA6, 0x4F, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x6F, 0x7E, 0x68, 0x6E, 0xA0, 0x14, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x73, 0xD4, 0xE8, 0xAB, 0x5B, 0xF6, 0x0D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xE0, 0x3C, 0x24, 0x00, 0x95, 0xE9, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x0D, 0x4F, 0x81, 0xD0, 0xF2, 0x3F, 0x00),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x1D, 0xCD, 0x78, 0x39, 0xC4, 0x6B, 0xD9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x45, 0xC7, 0xB8, 0x2F, 0xAA, 0x5D, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x8C, 0x6E, 0xA3, 0x24, 0xB2, 0xDB, 0x4B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x2D, 0xD9, 0xF1, 0xC7, 0x9B, 0x8A, 0xAF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xE1, 0x2C, 0xB9, 0x40, 0x37, 0x91, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2C, 0xB5, 0x23, 0x03, 0x2B, 0xAF, 0x2F),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x9D, 0x5A, 0x20, 0x10, 0xA9, 0x84, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x30, 0x89, 0x20, 0x13, 0xE9, 0xB2, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x52, 0xEB, 0x03, 0x18, 0x1F, 0xA6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x9E, 0x1C, 0x35, 0x87, 0x92, 0x69, 0xC7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xC9, 0x88, 0xAF, 0xC6, 0x6C, 0x83, 0x72),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD5, 0x7A, 0x54, 0x34, 0x99, 0xB6, 0x6F),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xAD, 0x45, 0x9B, 0x4B, 0x41, 0x4D, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x5D, 0xAB, 0x7F, 0x35, 0x34, 0xE9, 0x29),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBE, 0x78, 0x34, 0x44, 0xF3, 0x4A, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xDE, 0xE3, 0xC4, 0xEE, 0x0B, 0xF9, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x86, 0x16, 0x48, 0x32, 0xB8, 0x74, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEE, 0x7C, 0xBA, 0xBD, 0x81, 0xE3, 0x55),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x6A, 0xFA, 0x84, 0xDA, 0xB8, 0xD5, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x9F, 0x8A, 0xD5, 0x1B, 0x2E, 0x1A, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0C, 0x61, 0xE2, 0xFF, 0x5B, 0xE6, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x62, 0xC1, 0x87, 0x53, 0x1B, 0x92, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x90, 0x00, 0xD1, 0x6A, 0x0C, 0x0E, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x2E, 0xB5, 0x3B, 0x44, 0xB5, 0xA0, 0x78),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5D, 0x02, 0x58, 0xB5, 0xBE, 0x45, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xEF, 0x8E, 0x90, 0x4D, 0x2A, 0x32, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x75, 0x5C, 0x0A, 0x33, 0x8F, 0x36),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x6C, 0x95, 0xD4, 0x1F, 0xF3, 0xEB, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xE4, 0x4C, 0x91, 0x20, 0xF3, 0x25, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x95, 0xEB, 0x29, 0x6F, 0x20, 0x34, 0x81),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x15, 0xE5, 0x13, 0x7E, 0x64, 0x8B, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xBC, 0x0D, 0x18, 0x7E, 0x37, 0x9E, 0xFA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x82, 0x20, 0xF7, 0x2D, 0x7A, 0x77, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x29, 0xA2, 0xDB, 0x7A, 0xE6, 0x6F, 0xA5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xC6, 0x50, 0x5C, 0xBC, 0xE6, 0x4F, 0xBD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x9F, 0xD5, 0xE8, 0xC5, 0x3D, 0xB7, 0x30),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_16_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x03, 0x55, 0x10, 0xDB, 0xA6, 0x8B, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x17, 0xAE, 0x78, 0xC9, 0x1D, 0x43, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x35, 0x49, 0xD4, 0x47, 0x84, 0x8D, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x95, 0x2F, 0xEA, 0xBC, 0xB4, 0x18, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x48, 0xAE, 0x89, 0xF5, 0x65, 0x3D, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xF2, 0x2B, 0x20, 0xD1, 0x75, 0x50, 0x63),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_16_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xE6, 0x5C, 0x2C, 0xE0, 0x7D, 0xDF, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x07, 0x3E, 0xCE, 0x9F, 0x18, 0xB6, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xF8, 0xF0, 0xD5, 0xFA, 0x42, 0x1D, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x6C, 0x1D, 0x03, 0xC9, 0x0E, 0x2B, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x52, 0xA5, 0xB4, 0x63, 0xE1, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0xD9, 0xC4, 0xFD, 0x16, 0x60, 0x54),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_17_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x7D, 0xDE, 0xDF, 0x4B, 0x4A, 0xB0, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x4E, 0x8C, 0x94, 0xC1, 0xE2, 0x85, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xF0, 0xEA, 0xB5, 0x9B, 0x70, 0xEF, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xC2, 0x39, 0x5D, 0xF3, 0x2C, 0xD9, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x1C, 0x2E, 0xCC, 0x2F, 0x54, 0x87, 0x80),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x72, 0xC7, 0xB5, 0x50, 0xA3, 0x84, 0x77),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_17_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xD1, 0xAF, 0xA9, 0xB4, 0x8B, 0x5D, 0xFA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xF6, 0x52, 0x8A, 0xC3, 0x56, 0xA5, 0x5E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x52, 0xFF, 0xEA, 0x05, 0x42, 0x77, 0x83),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x08, 0x90, 0x72, 0x86, 0xC4, 0xC3, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x15, 0xF8, 0xF1, 0x16, 0x67, 0xC6, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x87, 0xAC, 0x8F, 0x71, 0xEC, 0x83, 0x81),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_18_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xE1, 0xE6, 0x2D, 0x0E, 0x11, 0xA1, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xE2, 0xA8, 0x32, 0xE6, 0xE3, 0x83, 0xD1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x56, 0xE5, 0xCD, 0xB7, 0x2B, 0x67, 0x6F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xED, 0xC9, 0x65, 0x6D, 0x87, 0xE1, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xFD, 0x9A, 0x53, 0x0E, 0xFA, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x4C, 0x4A, 0xE2, 0x23, 0x84, 0xFA, 0x01),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_18_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFE, 0x49, 0x81, 0xD1, 0x3E, 0xF4, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x72, 0xE0, 0xEF, 0x0D, 0xB8, 0x3E, 0x6F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x00, 0x0F, 0x5F, 0xCE, 0x60, 0x72, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCC, 0xD8, 0x03, 0x07, 0x6E, 0x5A, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x3A, 0x35, 0x50, 0x4E, 0x1F, 0xCA, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xEA, 0x88, 0x55, 0xBD, 0x6E, 0x05, 0x7F),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_19_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x6D, 0xF1, 0x97, 0xA6, 0x69, 0x39, 0x24),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x41, 0x99, 0xFF, 0x3B, 0xA1, 0x26, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x2F, 0x95, 0x80, 0x12, 0x4A, 0x1B, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xBF, 0x51, 0xAA, 0xAE, 0x2D, 0xDA, 0xCF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1C, 0xB3, 0x52, 0x36, 0x49, 0xD4, 0x86),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC1, 0x1F, 0x3A, 0xD3, 0x3E, 0x5C, 0x1A),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_19_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x51, 0xF7, 0x2B, 0xC8, 0xA9, 0xA7, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x4E, 0x7F, 0x98, 0x41, 0x66, 0xB0, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x1D, 0xC0, 0x42, 0xCD, 0xF8, 0xC3, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x41, 0x91, 0x7D, 0xCC, 0x8B, 0xCC, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xAE, 0x76, 0xED, 0x56, 0x18, 0xC5, 0xAB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x6A, 0x06, 0xA3, 0x7F, 0x65, 0x10, 0x1F),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_20_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xEC, 0x3C, 0x05, 0x05, 0xCA, 0xF6, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0xCD, 0x02, 0x51, 0x12, 0x16, 0x3C, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xEB, 0xB3, 0x43, 0x7B, 0xDD, 0xB2, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x90, 0x41, 0xDB, 0xE4, 0xF5, 0x91),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0E, 0x18, 0x2A, 0x5A, 0x83, 0x7C, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x37, 0xA1, 0x0D, 0xF1, 0x2F, 0x63, 0x79),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_20_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC0, 0xFA, 0x6F, 0x1F, 0x67, 0xCF, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x34, 0x45, 0xBB, 0xF4, 0xF9, 0x9B, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x69, 0xFE, 0x67, 0x1D, 0x64, 0x8F, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x39, 0xBF, 0xD8, 0xB3, 0xC7, 0xAD, 0x8A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x93, 0xFF, 0xF3, 0x28, 0xFA, 0x39, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF9, 0xC3, 0x85, 0x26, 0x7A, 0x88, 0x89),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_21_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD5, 0x79, 0xD8, 0x11, 0xDE, 0xEB, 0x4E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x46, 0xA4, 0x6A, 0xDA, 0x74, 0x34, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBD, 0xD3, 0xF5, 0x14, 0xEE, 0xFE, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4C, 0xA3, 0x71, 0x43, 0x65, 0xF8, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x6C, 0x35, 0xFA, 0x90, 0x25, 0xD8, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x34, 0x84, 0x96, 0xA1, 0x43, 0x03, 0x4D),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_21_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x3B, 0x3B, 0x2F, 0xCA, 0x59, 0xF2, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x48, 0x24, 0x74, 0xD8, 0x72, 0x90, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x42, 0x74, 0x8C, 0x6F, 0x52, 0x19, 0x3D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9E, 0x41, 0x63, 0x68, 0x78, 0x4C, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x94, 0xB6, 0x6B, 0x38, 0x52, 0xA8, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x30, 0x25, 0x93, 0xA1, 0x6F, 0x6E, 0x68),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_22_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2F, 0x4B, 0x64, 0x79, 0x50, 0xFF, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x36, 0xED, 0x57, 0x39, 0x3B, 0xE7, 0xF3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x85, 0xEA, 0x35, 0xD6, 0xC0, 0xA0, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x89, 0x3A, 0xCC, 0x22, 0x1C, 0x46, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x7A, 0xB0, 0xA1, 0x1B, 0x69, 0x62, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xB8, 0x8A, 0x6C, 0x18, 0x85, 0x0D, 0x88),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_22_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB6, 0x50, 0xE9, 0x4E, 0x7F, 0xE8, 0x07),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5B, 0x5C, 0xD1, 0x4B, 0x11, 0x9A, 0xD8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x25, 0x56, 0x74, 0x51, 0x9C, 0xEC, 0x9C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x7F, 0xB6, 0x8A, 0xCB, 0x3A, 0x10, 0x6A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x33, 0x07, 0x01, 0xE9, 0x49, 0x59, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xA5, 0x2E, 0xF2, 0xBA, 0x32, 0x63, 0x44),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_23_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x06, 0x0B, 0xA5, 0x44, 0x27, 0x7F, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x74, 0xAC, 0x0F, 0xCC, 0x4F, 0x13, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB1, 0xBF, 0x97, 0x49, 0xA5, 0x1C, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x64, 0x68, 0x7B, 0x0F, 0xCC, 0x77, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x39, 0xF9, 0x4E, 0x84, 0x9C, 0xF6, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xCF, 0x6D, 0xE2, 0xA1, 0x2D, 0xF9, 0x2B),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_23_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC4, 0x90, 0x57, 0x31, 0x01, 0x05, 0x5E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x1E, 0xBB, 0xBF, 0x98, 0xA4, 0x7C, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xE3, 0xA0, 0xB2, 0xCD, 0x39, 0x9A, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x34, 0x60, 0x7A, 0x89, 0x98, 0xB5, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x20, 0x3D, 0x3A, 0x04, 0x8F, 0x5A, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x26, 0xB6, 0x49, 0x09, 0x9C, 0x0F, 0x59),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_24_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x66, 0xD2, 0x38, 0x2A, 0x62, 0x81, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xC8, 0x20, 0x5E, 0x28, 0xA3, 0x81, 0xA7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x31, 0xA4, 0xF1, 0xEA, 0x7D, 0x87, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x2C, 0x99, 0x09, 0x6F, 0x63, 0xEB, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x76, 0xDA, 0x1A, 0x06, 0xBE, 0xDE, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x09, 0x2E, 0x75, 0x39, 0x30, 0x2D, 0x42),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_24_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x9B, 0xC1, 0x5A, 0x17, 0xC3, 0x8C, 0x31),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x8D, 0x94, 0x4D, 0x3D, 0xAB, 0x60, 0xD4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFD, 0x1E, 0x0F, 0x43, 0xAE, 0x9D, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF2, 0xF3, 0x20, 0x1B, 0xAA, 0xB7, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x5B, 0xA4, 0xF4, 0x90, 0x3B, 0xE3, 0x71),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x78, 0x72, 0xBD, 0x65, 0x09, 0x0B, 0x01),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_25_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x37, 0x2A, 0x6C, 0x16, 0x4F, 0x64, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xCE, 0xA3, 0x90, 0xB4, 0x9A, 0xBC, 0xF7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x55, 0x63, 0x1D, 0x3A, 0x6E, 0x18),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xB4, 0xAA, 0x99, 0x22, 0x45, 0x89, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x7C, 0x8C, 0xA6, 0x3D, 0xA7, 0x3E, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x06, 0x42, 0xDC, 0xA6, 0xE3, 0xC6, 0x12),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_25_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8C, 0x3D, 0x5D, 0x47, 0x31, 0x7C, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x85, 0xEE, 0x46, 0x7E, 0x13, 0x04, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x3C, 0x8B, 0x43, 0x2E, 0x74, 0xF5, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x88, 0x8E, 0x07, 0x29, 0x08, 0x03, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x9B, 0x89, 0xEB, 0x08, 0xE8, 0x43, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x07, 0x67, 0xFD, 0xD9, 0x73, 0x6F, 0x18),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_26_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xEB, 0x21, 0x8D, 0x98, 0x43, 0x74, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xCC, 0x14, 0xD8, 0x08, 0xBB, 0xA6, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x98, 0xF2, 0x6A, 0x18, 0xC3, 0xDD, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x38, 0x91, 0xA0, 0x03, 0xF2, 0x04, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xAF, 0xE8, 0xFD, 0xFB, 0x13, 0x70, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x93, 0x87, 0x98, 0x4A, 0xE0, 0x00, 0x12),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_26_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x2E, 0x69, 0x9C, 0xA2, 0x2D, 0x03, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFE, 0xF3, 0xB9, 0xC1, 0x85, 0x2A, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xFD, 0x86, 0xB1, 0xCD, 0xBF, 0x41, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xD8, 0x9A, 0x21, 0xF3, 0xFE, 0xCB, 0xF1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x78, 0x04, 0x60, 0xB7, 0xA9, 0xA2, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1E, 0x66, 0x2A, 0x54, 0x51, 0xBD, 0x8B),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_27_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x16, 0x36, 0xEF, 0x61, 0x2D, 0xEE, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x5F, 0x88, 0xA0, 0x13, 0x12, 0xF7, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xC6, 0xAD, 0x4A, 0x4A, 0x07, 0x01, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x74, 0xB1, 0x4F, 0xEB, 0xBD, 0xD5, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF9, 0x71, 0xA2, 0x06, 0x4F, 0xD7, 0xBC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x8B, 0x4D, 0x48, 0xE0, 0x98, 0xFB, 0x6A),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_27_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xBA, 0x10, 0xA3, 0x0D, 0x52, 0xAC, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xD0, 0xE0, 0x36, 0xE6, 0x07, 0x3A, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x80, 0xF0, 0xAA, 0x49, 0x22, 0x4B, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC7, 0xAB, 0x1C, 0x89, 0xCD, 0x24, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x2A, 0xFC, 0xB3, 0x6D, 0x45, 0x96, 0x49),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xE4, 0xDB, 0x52, 0x3F, 0xC4, 0xB4, 0x19),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_28_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xCC, 0xC8, 0x7F, 0xBB, 0x6B, 0x87, 0x47),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x21, 0x3C, 0x69, 0x7D, 0x38, 0x57, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x4C, 0x18, 0x3C, 0x53, 0xA5, 0x48, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC3, 0x64, 0x45, 0xDB, 0xC4, 0x6D, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCC, 0xD1, 0xBB, 0x17, 0xB8, 0x34, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x69, 0x71, 0xFA, 0xA0, 0x28, 0x4A, 0x3D),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_28_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xE8, 0x9E, 0x39, 0xEA, 0x8D, 0x38, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x9C, 0xBB, 0xCD, 0x80, 0x1A, 0xEE, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA0, 0x45, 0xBF, 0xD9, 0x22, 0x11, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7C, 0x5C, 0xD9, 0xC0, 0x9F, 0x69, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x8A, 0xA6, 0x79, 0x4E, 0x35, 0xB9, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8B, 0x9A, 0x3E, 0xA1, 0xB8, 0x28, 0x10),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_29_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x2F, 0xEF, 0xBB, 0xA9, 0x72, 0x7F, 0xEA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x34, 0xB7, 0x12, 0xB9, 0xE7, 0xC3, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x1D, 0xD9, 0x42, 0x77, 0x0C, 0x71, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x01, 0x59, 0xA7, 0x56, 0x03, 0x91, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x91, 0x99, 0x33, 0x30, 0x3E, 0xEF, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xC9, 0x5A, 0x9A, 0x54, 0x66, 0xF1, 0x70),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_29_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x2C, 0xB7, 0x6E, 0x71, 0x7D, 0x35, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x0D, 0xEF, 0xD1, 0x2D, 0x99, 0x63, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x31, 0xAF, 0x2D, 0xC9, 0xC6, 0xC2, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xC0, 0xDF, 0x80, 0x54, 0xC4, 0xAC, 0xF3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x6B, 0xA0, 0x84, 0x96, 0xF7, 0x31, 0xC8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xE2, 0x7C, 0x7A, 0x41, 0x45, 0x75, 0x6A),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_30_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xEE, 0x58, 0x31, 0xE8, 0x68, 0xD6, 0x76),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x2E, 0x48, 0xB7, 0x09, 0x9F, 0xD4, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA9, 0x5C, 0xE7, 0x64, 0x43, 0x5D, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x9F, 0x50, 0xAB, 0x68, 0xFF, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x88, 0x2D, 0xBA, 0x12, 0xBF, 0x8D, 0x7D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xDF, 0x6F, 0xB3, 0x75, 0xA4, 0x55, 0x73),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_30_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x17, 0x92, 0x39, 0xB7, 0x13, 0x37, 0x6F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x43, 0x71, 0xA7, 0xCA, 0x17, 0x1B, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xB9, 0xB0, 0x78, 0xEF, 0xA0, 0xDA, 0x83),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0xF2, 0x0F, 0x85, 0xA2, 0xB6, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x65, 0x2E, 0x6E, 0x45, 0xB9, 0x4C, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x6A, 0x8C, 0x2B, 0x77, 0x96, 0x36, 0x22),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_31_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x7A, 0x13, 0x4A, 0x97, 0x63, 0x02, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x1E, 0x06, 0x03, 0x8F, 0xB9, 0xEE, 0x64),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0xEE, 0x8B, 0x89, 0xA9, 0x70, 0xDB, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x81, 0xC9, 0x70, 0x8D, 0x62, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xDA, 0x46, 0xF8, 0xF9, 0x3A, 0xBE, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x9C, 0x7A, 0x97, 0x62, 0xEB, 0xFA, 0x0F),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_31_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x03, 0x3D, 0x3C, 0x46, 0x27, 0x9E, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x08, 0x1C, 0xD5, 0x25, 0xAF, 0xE9, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x69, 0xDC, 0x59, 0xF4, 0x8A, 0x7C, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x9A, 0x7A, 0x99, 0x21, 0x0C, 0x4E, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xCE, 0x85, 0x5F, 0xAC, 0xAA, 0x82, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x57, 0x69, 0x90, 0x76, 0xF3, 0x53, 0x3F),
+};
+static const mbedtls_ecp_point brainpoolP384r1_T[32] = {
+    ECP_POINT_INIT_XY_Z1(brainpoolP384r1_T_0_X, brainpoolP384r1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_1_X, brainpoolP384r1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_2_X, brainpoolP384r1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_3_X, brainpoolP384r1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_4_X, brainpoolP384r1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_5_X, brainpoolP384r1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_6_X, brainpoolP384r1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_7_X, brainpoolP384r1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_8_X, brainpoolP384r1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_9_X, brainpoolP384r1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_10_X, brainpoolP384r1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_11_X, brainpoolP384r1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_12_X, brainpoolP384r1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_13_X, brainpoolP384r1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_14_X, brainpoolP384r1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_15_X, brainpoolP384r1_T_15_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_16_X, brainpoolP384r1_T_16_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_17_X, brainpoolP384r1_T_17_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_18_X, brainpoolP384r1_T_18_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_19_X, brainpoolP384r1_T_19_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_20_X, brainpoolP384r1_T_20_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_21_X, brainpoolP384r1_T_21_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_22_X, brainpoolP384r1_T_22_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_23_X, brainpoolP384r1_T_23_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_24_X, brainpoolP384r1_T_24_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_25_X, brainpoolP384r1_T_25_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_26_X, brainpoolP384r1_T_26_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_27_X, brainpoolP384r1_T_27_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_28_X, brainpoolP384r1_T_28_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_29_X, brainpoolP384r1_T_29_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_30_X, brainpoolP384r1_T_30_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_31_X, brainpoolP384r1_T_31_Y),
+};
+#else
+#define brainpoolP384r1_T NULL
+#endif
+
+#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */
+
+/*
+ * Domain parameters for brainpoolP512r1 (RFC 5639 3.7)
+ */
+#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
+static const mbedtls_mpi_uint brainpoolP512r1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_a[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA),
+};
+
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint brainpoolP512r1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xE9, 0x6B, 0x8C, 0x6F, 0x9D, 0x88, 0x43),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x4F, 0x86, 0x96, 0xA7, 0x56, 0xD1, 0x37),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xAB, 0xFA, 0xEE, 0xA7, 0xF5, 0x0E, 0xA6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x40, 0xEF, 0x9E, 0x6D, 0xD6, 0x32, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xED, 0x56, 0x14, 0x57, 0x1A, 0x8D, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xED, 0x4D, 0x3A, 0xFA, 0x71, 0x75, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xC5, 0x76, 0x1C, 0x14, 0xBE, 0xB5, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x5A, 0xCB, 0xE7, 0x36, 0x1D, 0x52, 0x1C),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8D, 0x7A, 0xEB, 0xA3, 0x8B, 0xD5, 0xB0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xA3, 0x41, 0xF8, 0xAC, 0x9E, 0xAB, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xE3, 0x65, 0x0D, 0x1C, 0xFE, 0x09, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xCA, 0x13, 0x3F, 0xC5, 0xF9, 0x7E, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x5D, 0x63, 0x28, 0xA6, 0x89, 0xD3, 0x91),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x95, 0x3F, 0x7A, 0x82, 0xD4, 0x77, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xBB, 0x92, 0x32, 0x00, 0xF4, 0x66, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x58, 0x31, 0xD1, 0x17, 0x9F, 0x2A, 0x22),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x36, 0xA9, 0xCD, 0x80, 0xA5, 0x2D, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x44, 0xAB, 0xCE, 0x71, 0xFF, 0x0C, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x24, 0x58, 0x35, 0x5A, 0x21, 0x32, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xA6, 0x28, 0xF8, 0x7A, 0x97, 0xAE, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xE7, 0x08, 0xFA, 0x47, 0xC9, 0x55, 0x09),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xAC, 0x2E, 0x84, 0xA4, 0xF5, 0x52, 0xC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x58, 0x05, 0x9D, 0xA7, 0xC8, 0x71, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x92, 0xB4, 0x92, 0xC1, 0x92, 0xEC, 0x6B),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x48, 0x2D, 0x79, 0x5E, 0x58, 0xE5, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x85, 0x26, 0xEC, 0xE9, 0x6E, 0xD4, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x68, 0x26, 0x87, 0x38, 0xA2, 0xD2, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x17, 0x60, 0xCE, 0x75, 0xF8, 0xA5, 0x6F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x51, 0xDB, 0xA9, 0xAE, 0x87, 0xF1, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x49, 0x92, 0x3B, 0x19, 0x96, 0xF5, 0xB0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xD5, 0x52, 0x52, 0x8C, 0xCE, 0xFD, 0xFA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x18, 0x0A, 0xE6, 0xF6, 0xAE, 0x08, 0x41),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x2B, 0xD8, 0x54, 0xCE, 0xB0, 0x57, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xB0, 0xF8, 0x9E, 0x03, 0x03, 0x3C, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x0E, 0x29, 0x29, 0x00, 0xF3, 0x70, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x33, 0x99, 0x0E, 0x00, 0x5D, 0xFE, 0x4B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2D, 0xF2, 0x59, 0x32, 0xCF, 0x03, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xC9, 0x72, 0xAE, 0x0C, 0xEF, 0xD1, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x5A, 0x27, 0xBF, 0x2F, 0x45, 0xF9, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xBE, 0xE5, 0x2C, 0xFF, 0x5B, 0x1E, 0x88),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xAC, 0xBB, 0xD8, 0x83, 0xC2, 0x46, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xDC, 0xCE, 0x15, 0xB4, 0xEF, 0xCF, 0x46),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xDB, 0x5E, 0x94, 0x31, 0x0B, 0xB2, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xB9, 0xE3, 0xE3, 0x11, 0x71, 0x41, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xE3, 0x01, 0xB7, 0x7D, 0xBC, 0x65, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x07, 0x65, 0x87, 0xA7, 0xE8, 0x48, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x48, 0x8F, 0xD4, 0x30, 0x8E, 0xB4, 0x6C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE0, 0x73, 0xBE, 0x1E, 0xBF, 0x56, 0x36),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x0E, 0x5E, 0x87, 0xC5, 0xAB, 0x0E, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xF9, 0x5F, 0x80, 0x24, 0x4C, 0x2A, 0xF1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x15, 0x21, 0x54, 0x92, 0x84, 0x8D, 0x6A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x8A, 0x47, 0x74, 0xDC, 0x42, 0xB1, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xF7, 0x30, 0xFD, 0xC1, 0x9B, 0x0C, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x6C, 0xCC, 0xDF, 0xC5, 0xE3, 0xA9, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x67, 0x59, 0x10, 0x5C, 0x51, 0x54, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x37, 0xFB, 0x6E, 0xB0, 0x78, 0x63, 0x8E),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEF, 0xC4, 0x39, 0x20, 0xF1, 0x46, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x62, 0xAE, 0xFF, 0x10, 0xE4, 0xE2, 0xE9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x5C, 0xF5, 0x2E, 0x22, 0x89, 0xE5, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x0C, 0x29, 0xA8, 0x62, 0xAE, 0xDB, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x9E, 0x0F, 0xCA, 0x87, 0x2A, 0x6F, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xDC, 0x9B, 0x9F, 0x65, 0xD4, 0xAD, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xC3, 0x08, 0x0F, 0xCF, 0x67, 0xE9, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5C, 0xD7, 0xFF, 0x41, 0x9C, 0xCB, 0x26),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x05, 0x12, 0xAD, 0x73, 0x63, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x99, 0x07, 0x86, 0x57, 0xE7, 0x94, 0xB1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x4B, 0xA5, 0xBF, 0x18, 0xA9, 0xEF, 0x6A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x4C, 0xC4, 0x09, 0xF2, 0x2F, 0x0C, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x3A, 0x04, 0xEA, 0x89, 0x6C, 0x91, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0x3A, 0xE7, 0xA3, 0xEC, 0x24, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xA1, 0x26, 0x21, 0x04, 0xE3, 0xB9, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x71, 0x4B, 0x7B, 0xC2, 0x89, 0xCD, 0xA2),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xB9, 0xA8, 0x9D, 0xFD, 0x00, 0x3A, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x41, 0x6C, 0xBB, 0x5A, 0xCA, 0x1F, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xD7, 0xE2, 0x6C, 0x6B, 0xA7, 0x48, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x19, 0xAD, 0xA7, 0xC1, 0x7E, 0x4F, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF7, 0x19, 0x3C, 0x06, 0x74, 0x2C, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x23, 0x4F, 0x0C, 0x09, 0xB0, 0x80, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x74, 0x34, 0x08, 0x44, 0x7E, 0xA3, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xCC, 0x8D, 0x12, 0x6E, 0xE1, 0x3D, 0x0B),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x18, 0xB1, 0x71, 0x02, 0x93, 0xC2, 0xA4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x89, 0x40, 0xE2, 0x1F, 0xE7, 0x5E, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xAE, 0x89, 0x01, 0xD4, 0x0C, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xDA, 0x58, 0x70, 0x24, 0xF2, 0xE4, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xC7, 0x1D, 0xD6, 0x4A, 0x6F, 0x66, 0x4F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x1D, 0x7E, 0x4A, 0x2C, 0xCA, 0xEC, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x7F, 0xA8, 0x99, 0xE4, 0xD3, 0x4E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x1D, 0x5A, 0xDF, 0x5E, 0x58, 0x36, 0x49),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB9, 0x32, 0x69, 0x1F, 0x72, 0x2A, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x73, 0xE2, 0x03, 0x39, 0x35, 0xAA, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x5E, 0x5D, 0x48, 0xEF, 0xAE, 0x30, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x7F, 0x60, 0x19, 0xAF, 0xEC, 0x9D, 0xFC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x19, 0xE4, 0x1B, 0x56, 0x15, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xD7, 0x33, 0x59, 0x1F, 0x43, 0x59, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xCE, 0xEE, 0xCA, 0xA4, 0x7F, 0x63, 0xD4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x40, 0xC0, 0xF6, 0x19, 0x89, 0x43, 0x20),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x92, 0xEA, 0x07, 0x65, 0x79, 0x86, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xB7, 0x13, 0x75, 0xD3, 0xC5, 0x0A, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x9E, 0xFA, 0xE1, 0x1F, 0x0C, 0xF9, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x8C, 0xED, 0x5C, 0x21, 0xE9, 0x09, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x4D, 0xD8, 0x18, 0xC4, 0xF6, 0x36, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xC9, 0xAC, 0x5C, 0xFA, 0x69, 0xA4, 0xA0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8C, 0x94, 0x1C, 0x7B, 0x71, 0x36, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBD, 0x46, 0xCE, 0xB7, 0x1D, 0x9C, 0x5E),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD6, 0x96, 0x4B, 0xA6, 0x47, 0xEB, 0xE5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xF1, 0x5F, 0x15, 0xDE, 0x99, 0x6F, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xBD, 0xE5, 0x04, 0xB8, 0xE6, 0xC0, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD3, 0xF0, 0x04, 0x00, 0xE4, 0x05, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xF3, 0x06, 0xA3, 0x1A, 0xFF, 0xEA, 0x73),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x32, 0xAA, 0x99, 0x33, 0x09, 0xB6, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xEF, 0xFC, 0x61, 0x10, 0x42, 0x31, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF1, 0xF4, 0x33, 0xCF, 0x28, 0x90, 0x9C),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xDE, 0xF9, 0x88, 0x87, 0x7B, 0xEB, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xB8, 0xDA, 0xFA, 0xDA, 0x3D, 0xA6, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF0, 0x62, 0x82, 0x53, 0x32, 0x55, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA5, 0x32, 0x4A, 0x19, 0x11, 0x9C, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xB3, 0x27, 0xE9, 0x75, 0x90, 0x05, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x1C, 0x90, 0x48, 0x77, 0x01, 0x85, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD6, 0x9B, 0x84, 0xA8, 0xD7, 0xC5, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x7A, 0xCB, 0xB3, 0x11, 0x46, 0xD7, 0x99),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x23, 0xBF, 0x75, 0x75, 0xA1, 0x95, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x66, 0x5D, 0x34, 0x13, 0xA9, 0x03, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x80, 0x9D, 0x5F, 0xD2, 0x44, 0xE1, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x5D, 0xBD, 0xA8, 0xBF, 0xB4, 0x25, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x99, 0x1F, 0x53, 0xF1, 0x57, 0xDB, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x7C, 0xE5, 0xC5, 0x51, 0x0B, 0x4C, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xB0, 0x1A, 0x9C, 0x16, 0xB0, 0x32, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xE3, 0xCF, 0xDD, 0x48, 0xB4, 0x7B, 0x33),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xDD, 0x9E, 0x3C, 0x98, 0x0E, 0x77, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xAB, 0x01, 0xD3, 0x87, 0x74, 0x25, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xA3, 0xE3, 0x76, 0x43, 0x87, 0x12, 0xBD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0xB1, 0x3B, 0x60, 0x66, 0xEB, 0x98, 0x54),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x78, 0xC8, 0xD7, 0x4E, 0x75, 0xCA, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xDF, 0x71, 0x19, 0xE7, 0x07, 0x36, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC9, 0xA8, 0x5F, 0x91, 0xBF, 0x47, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x96, 0x58, 0x96, 0x18, 0xB6, 0xFA, 0x01),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x2D, 0xA9, 0x9B, 0x86, 0xDB, 0x0C, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0B, 0x2D, 0x56, 0x4A, 0xD3, 0x93, 0x8A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x15, 0xE2, 0x65, 0x12, 0x86, 0x0E, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x41, 0x4D, 0xC1, 0xCB, 0xE4, 0xC3, 0xD7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x53, 0x10, 0xCA, 0xA3, 0xAC, 0x83, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x01, 0x22, 0x96, 0x10, 0xAD, 0x69, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x46, 0x4E, 0xD8, 0xEA, 0xD6, 0x9D, 0xF3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x2F, 0x7F, 0x62, 0x62, 0x80, 0xD0, 0x14),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xDA, 0x00, 0x63, 0x09, 0xBD, 0x6A, 0x83),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD4, 0x6E, 0x48, 0x05, 0xB7, 0xF7, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x4D, 0xD7, 0x00, 0x4A, 0x15, 0x27, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x15, 0xAA, 0x37, 0x27, 0x34, 0x18, 0x24),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x20, 0x2C, 0x84, 0x1B, 0x88, 0xBA, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x09, 0xD6, 0x04, 0xA2, 0x60, 0x84, 0x72),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x04, 0x94, 0x08, 0xD4, 0xED, 0x47, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xF3, 0xE4, 0x3E, 0xB9, 0x5B, 0x35, 0x42),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xD8, 0xB6, 0x80, 0xD6, 0xF1, 0x30, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x14, 0xA6, 0x85, 0xEE, 0xA7, 0xD8, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x49, 0x2A, 0x1E, 0x7C, 0xE9, 0x2D, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x87, 0x56, 0x91, 0x03, 0x77, 0x4D, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x52, 0xD4, 0xAA, 0xF7, 0xFA, 0xB0, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x11, 0x39, 0xB1, 0xE7, 0x76, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x13, 0xBC, 0x37, 0x5D, 0x74, 0xCD, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x48, 0x14, 0x23, 0x30, 0xF8, 0x46, 0x37),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x27, 0xB0, 0xD9, 0xB2, 0x74, 0xB4, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xA6, 0xB9, 0x6F, 0x9F, 0x64, 0x36, 0x92),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x2B, 0x78, 0x40, 0x05, 0x2B, 0x7B, 0xA9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x68, 0x3A, 0xB6, 0x4A, 0xE2, 0xDB, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x33, 0xD7, 0x34, 0x8B, 0x25, 0x45, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xCE, 0xA8, 0xC9, 0x01, 0xFB, 0x0E, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF9, 0x51, 0x4C, 0x12, 0x9F, 0x60, 0xE4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x85, 0xBD, 0x30, 0x37, 0x84, 0x39, 0x44),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x33, 0xAF, 0x2E, 0xB8, 0x2E, 0xCC, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xB1, 0x73, 0x59, 0x4E, 0x0C, 0x09, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x24, 0x89, 0x81, 0x12, 0xFF, 0xBB, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0x1A, 0x66, 0xEE, 0xED, 0xB6, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xBD, 0x04, 0x20, 0x5D, 0xFB, 0xBF, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF8, 0x34, 0xA3, 0xFF, 0x45, 0xDE, 0x92),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x18, 0x73, 0xF1, 0x32, 0x25, 0x58, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xC1, 0x14, 0xE3, 0x9E, 0x40, 0x0F, 0x12),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0x9D, 0x9C, 0x00, 0xF7, 0x56, 0x19),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBA, 0x87, 0xF9, 0x15, 0x0C, 0x66, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x1F, 0xC1, 0x28, 0xB0, 0x47, 0x0D, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xCA, 0x27, 0xEE, 0x4B, 0x23, 0x2B, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB5, 0x68, 0xC8, 0x17, 0x5D, 0xC3, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x02, 0x08, 0xEE, 0x20, 0x9D, 0xEA, 0x64),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x14, 0x50, 0xD4, 0x7D, 0x5F, 0xCF, 0xA0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFA, 0xF8, 0xA7, 0xC6, 0xDC, 0x14, 0x8C),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xBD, 0x0A, 0x1A, 0x18, 0x98, 0xDC, 0xB0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x63, 0x02, 0xB7, 0xD5, 0x5B, 0x5A, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB1, 0xD7, 0x4B, 0x15, 0x39, 0x61, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x32, 0xE1, 0x9E, 0x70, 0x1B, 0xCE, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD8, 0x18, 0x83, 0x52, 0x9B, 0x6D, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x55, 0x56, 0x19, 0x34, 0xA4, 0xEA, 0xFC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA9, 0x55, 0x80, 0xE3, 0x15, 0x36, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x06, 0xC8, 0x1D, 0x17, 0x0D, 0xAD, 0x16),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xD6, 0xF0, 0xCC, 0xF3, 0x63, 0x53, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x5A, 0xDC, 0x46, 0xBD, 0x0D, 0xAD, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x2F, 0x11, 0x60, 0x15, 0x51, 0x4A, 0xEA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE3, 0x93, 0x38, 0xD5, 0x83, 0xAA, 0x0D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA6, 0xCC, 0xB1, 0xFD, 0xBB, 0x1A, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x54, 0xC8, 0x54, 0x6F, 0x79, 0x1A, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4A, 0xDA, 0x28, 0x92, 0x97, 0x9D, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x4B, 0xDB, 0xC7, 0x52, 0xC5, 0x66, 0x34),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7E, 0x92, 0x53, 0x30, 0x93, 0xFD, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0x6A, 0xB1, 0x91, 0x0A, 0xB4, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x9D, 0x40, 0x3F, 0xE3, 0xF1, 0x01, 0x46),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x0E, 0xD8, 0xED, 0x11, 0x8E, 0x4C, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x4A, 0x1B, 0x88, 0xDF, 0x8D, 0x29, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x23, 0x21, 0x11, 0xAB, 0x77, 0x81, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xAF, 0x11, 0xFA, 0xBA, 0x40, 0x63, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x6F, 0x8D, 0x80, 0xDF, 0x67, 0xF5, 0x44),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x8B, 0xB7, 0x08, 0xF4, 0xD7, 0x2D, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x2B, 0x30, 0x02, 0x45, 0x71, 0x08, 0x49),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x3A, 0xCA, 0x50, 0xF6, 0xC2, 0x19, 0x8C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xB9, 0x9B, 0x3E, 0x73, 0x95, 0x1D, 0x49),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x60, 0x59, 0x48, 0xCB, 0xD8, 0xD6, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x6C, 0x89, 0xAB, 0x99, 0xA8, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xA1, 0x8B, 0x4E, 0x06, 0x19, 0xEC, 0x99),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x95, 0x04, 0xCF, 0xD5, 0x94, 0xB3, 0x02),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x35, 0x93, 0x7C, 0xB3, 0xB8, 0x9E, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x45, 0x5C, 0x7E, 0xBF, 0x75, 0x81, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE8, 0x24, 0xDF, 0xEC, 0x2F, 0x7D, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x8B, 0xD5, 0x6A, 0x9B, 0xA0, 0xE0, 0x4F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE3, 0x27, 0x82, 0xDE, 0xDD, 0xCA, 0x4B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x57, 0x56, 0x46, 0x05, 0x06, 0x01, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x35, 0xA7, 0x47, 0xE2, 0x6B, 0x2C, 0x4F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x9D, 0x4C, 0xEC, 0x1F, 0x11, 0x75, 0x2B),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xAA, 0x41, 0xC1, 0xE9, 0x0E, 0xE9, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xCF, 0x9C, 0x4B, 0xE8, 0xED, 0x0A, 0x49),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x73, 0xCA, 0x0C, 0x46, 0x0A, 0x9C, 0xE4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE1, 0x9E, 0xBC, 0xFE, 0x44, 0x63, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x43, 0x71, 0xEE, 0xF8, 0xC1, 0x8C, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x4B, 0xF0, 0x69, 0x25, 0xBD, 0x71, 0x1A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x9A, 0xFE, 0x82, 0xE7, 0xC1, 0xC1, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x5A, 0x6E, 0x5E, 0x97, 0x6A, 0x35, 0x8D),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x18, 0x6C, 0x7E, 0xB8, 0x9E, 0x57, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xB9, 0xC1, 0xD0, 0xFE, 0x78, 0xFB, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x08, 0xAE, 0x46, 0x34, 0xEA, 0x7A, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1C, 0x56, 0xA9, 0x18, 0x37, 0xD4, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x63, 0xE9, 0x0A, 0xB6, 0x38, 0x3C, 0xC1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x4F, 0xA4, 0x6E, 0x85, 0x31, 0x23, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xAD, 0xC4, 0xC3, 0xB1, 0x4B, 0x1C, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x56, 0x4A, 0x38, 0xB3, 0x6B, 0x6F, 0x2C),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_16_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xC7, 0x19, 0xDE, 0x21, 0xED, 0x89, 0xD0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xBE, 0xA6, 0xAE, 0xEB, 0x9D, 0xA7, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x0E, 0x13, 0x1E, 0x86, 0x57, 0xC3, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4B, 0x30, 0x46, 0x52, 0xC1, 0xEC, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xD5, 0x44, 0x31, 0x96, 0x3B, 0x26, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x68, 0xA8, 0x67, 0x78, 0x39, 0xE8, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x78, 0xB7, 0xDD, 0xF2, 0x58, 0xB6, 0x3D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x3C, 0xB3, 0x26, 0xC4, 0x2C, 0x8C, 0xA5),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_16_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x24, 0xE5, 0x73, 0xEE, 0x9A, 0x02, 0xA9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x6A, 0x65, 0x60, 0xF3, 0x62, 0xE3, 0xE9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x07, 0x84, 0xE6, 0x3B, 0x46, 0x65, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x8F, 0x0C, 0xB0, 0xE1, 0x04, 0x82, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x13, 0xBF, 0x3D, 0xA0, 0x48, 0xA2, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x26, 0x76, 0x74, 0xAB, 0x0B, 0x29, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x6E, 0x5F, 0x03, 0x34, 0x7C, 0x38, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x72, 0xF9, 0x3B, 0x3C, 0xA4, 0xBC, 0x7C),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_17_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xCE, 0x18, 0x80, 0xB8, 0x24, 0x45, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x09, 0x03, 0xB8, 0x06, 0x64, 0xF7, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x26, 0xB1, 0x10, 0x6D, 0x71, 0x12, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x12, 0xC6, 0x6E, 0x1E, 0x6A, 0xC3, 0x80),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xD3, 0x0A, 0xDE, 0xD8, 0x6B, 0x04, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x87, 0x5B, 0xAE, 0xDB, 0x3C, 0xC0, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF5, 0xF9, 0xC1, 0x9A, 0x89, 0xBB, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x69, 0x72, 0x8B, 0xAE, 0x32, 0x13, 0x11),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_17_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x16, 0x07, 0x50, 0xFA, 0x4C, 0xCF, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x50, 0x21, 0xE9, 0xDE, 0xEC, 0x7E, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x2F, 0xE8, 0x83, 0x30, 0x0B, 0x65, 0x0E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x0B, 0x99, 0xAC, 0xC9, 0xBA, 0x6C, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x59, 0x5A, 0x0D, 0x7B, 0x9E, 0x08, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x91, 0xB2, 0xDC, 0x90, 0xCE, 0x67, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x93, 0x60, 0x0C, 0xD7, 0x1F, 0x2F, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7F, 0x9D, 0x40, 0xF8, 0x78, 0x7A, 0x54),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_18_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x22, 0x95, 0xE8, 0xEF, 0x31, 0x57, 0x35),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x88, 0x53, 0xFE, 0xAF, 0x7C, 0x47, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xCE, 0xCC, 0x79, 0xE8, 0x9F, 0x8C, 0xC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x16, 0xDD, 0x77, 0x6E, 0x8A, 0x73, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x07, 0x97, 0x21, 0x3B, 0xF8, 0x5F, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xB5, 0xD2, 0x81, 0x84, 0xF0, 0xE7, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x8F, 0x75, 0x09, 0x6A, 0x0E, 0x53, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x4F, 0x70, 0x97, 0xC7, 0xAC, 0x7D, 0x3F),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_18_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x3C, 0x6A, 0xB4, 0x10, 0xA9, 0xC8, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC5, 0xD6, 0x69, 0x16, 0xB8, 0xAC, 0x25),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x44, 0xDC, 0xEB, 0x48, 0x54, 0x5D, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x48, 0x9B, 0xD7, 0x72, 0x69, 0xA4, 0x8A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x0D, 0x36, 0x9A, 0x66, 0x0B, 0xEC, 0x24),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC6, 0xD4, 0xB6, 0x60, 0xE5, 0xC3, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x29, 0x42, 0xE0, 0x9D, 0xFD, 0x7C, 0x3E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x10, 0xBA, 0x55, 0xBC, 0x3B, 0x38, 0x5D),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_19_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x66, 0xFA, 0x05, 0x73, 0x03, 0x1B, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xA4, 0x66, 0x12, 0x96, 0x7B, 0x02, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xDE, 0x6D, 0x98, 0xD1, 0xD5, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF5, 0x44, 0xB8, 0x8E, 0xF6, 0x8C, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x15, 0x2B, 0x72, 0xBC, 0x49, 0xE5, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x44, 0xD7, 0xDF, 0x8F, 0xEB, 0x8D, 0x80),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x64, 0x88, 0xAA, 0xB7, 0xE4, 0x70, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x14, 0xBB, 0xE9, 0x9B, 0xB9, 0x65, 0x5D),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_19_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x8E, 0x88, 0xF5, 0xF1, 0xC1, 0x89, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x30, 0x53, 0xE6, 0xFB, 0x2D, 0x82, 0xB4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE4, 0xFF, 0xBA, 0x31, 0x79, 0xAB, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x09, 0xF7, 0xB7, 0x09, 0x78, 0x4C, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xAE, 0xC2, 0x44, 0xDC, 0x17, 0x78, 0x47),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD4, 0x17, 0x43, 0x19, 0x74, 0x9E, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x64, 0x3B, 0x73, 0xA2, 0x99, 0x27, 0x76),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0x36, 0x5F, 0xD3, 0x14, 0xB1, 0x31),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_20_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x07, 0xAB, 0xFD, 0x9B, 0x03, 0xC5, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xBE, 0xB0, 0x1D, 0xF2, 0x0C, 0x73, 0x73),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE7, 0x7B, 0x87, 0xD3, 0x34, 0xFD, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x25, 0x3D, 0xC7, 0x36, 0x83, 0x53, 0xDC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x7C, 0xCF, 0x63, 0x55, 0x12, 0x11, 0xB0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x34, 0x4D, 0x27, 0x92, 0xAC, 0x18, 0x16),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x42, 0x61, 0x9D, 0x2E, 0xFF, 0x13, 0x16),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xDE, 0x92, 0x65, 0x57, 0x0D, 0xBC, 0x0A),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_20_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x7B, 0x6E, 0xC6, 0x2A, 0x21, 0x74, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xA7, 0x53, 0x4D, 0x29, 0x36, 0xEF, 0xE5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xD6, 0x41, 0xC7, 0x99, 0xAD, 0x50, 0x53),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xAC, 0x41, 0x9F, 0xFB, 0x4C, 0x86, 0xF1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xBB, 0xE6, 0x25, 0x28, 0xAA, 0xEB, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x04, 0xA2, 0xC3, 0xAA, 0x08, 0x8A, 0xCC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x2B, 0x5B, 0xE2, 0x8D, 0x76, 0xEA, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x33, 0xD2, 0x21, 0x4D, 0x62, 0xE3, 0x8E),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_21_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x06, 0x8B, 0x2B, 0xC2, 0xC4, 0xB1, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF5, 0xA1, 0xC0, 0x03, 0x6A, 0x29, 0x12),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA9, 0xEF, 0x55, 0xB6, 0x1A, 0x9F, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x54, 0x32, 0xBE, 0x06, 0x43, 0xB5, 0xFD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xD6, 0xD9, 0x20, 0x89, 0xBE, 0xD4, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x26, 0x95, 0x10, 0xCE, 0xB4, 0x88, 0x79),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xA6, 0x27, 0xAC, 0x32, 0xBA, 0xBD, 0xC7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xA6, 0xAE, 0x9C, 0x7B, 0xBE, 0xA1, 0x63),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_21_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xCD, 0x4D, 0x3D, 0xDF, 0x96, 0xBB, 0x7D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0x11, 0x06, 0xCC, 0x0E, 0x31, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xE4, 0xF4, 0xAD, 0x7B, 0x5F, 0xF1, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x54, 0xBE, 0xF4, 0x8A, 0x03, 0x47, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x53, 0x00, 0x7F, 0xB0, 0x8A, 0x68, 0xA6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0xB1, 0x73, 0x6F, 0x5B, 0x0E, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x32, 0xE3, 0x43, 0x64, 0x75, 0xFB, 0xFB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x18, 0x55, 0x8A, 0x4E, 0x6E, 0x35, 0x54),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_22_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x97, 0x15, 0x1E, 0xCB, 0xF2, 0x9C, 0xA5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xD1, 0xBB, 0xF3, 0x70, 0xAD, 0x13, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x96, 0xA4, 0xC5, 0x5E, 0xDA, 0xD5, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x81, 0xE9, 0x65, 0x66, 0x76, 0x47, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x87, 0x06, 0x73, 0xCF, 0x34, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x81, 0x15, 0x42, 0xA2, 0x79, 0x5B, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA2, 0x7D, 0x09, 0x14, 0x64, 0xC6, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x6D, 0xC4, 0xED, 0xF1, 0xD6, 0xE9, 0x24),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_22_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xD5, 0xBB, 0x25, 0xA3, 0xDD, 0xA3, 0x88),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xF2, 0x68, 0x67, 0x39, 0x8F, 0x73, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x76, 0x28, 0x89, 0xAD, 0x32, 0xE0, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x90, 0xCC, 0x57, 0x58, 0xAA, 0xC9, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD7, 0x43, 0xD2, 0xCE, 0x5E, 0xA0, 0x08),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xB0, 0xB8, 0xA4, 0x9E, 0x96, 0x26, 0x86),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x61, 0x1D, 0xF3, 0x65, 0x5E, 0x60, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x1E, 0x65, 0xED, 0xCF, 0x07, 0x60, 0x20),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_23_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x30, 0x17, 0x8A, 0x91, 0x88, 0x0A, 0xA4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7D, 0x18, 0xA4, 0xAC, 0x59, 0xFC, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x31, 0x8B, 0x25, 0x65, 0x39, 0x9A, 0xDC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x16, 0x4B, 0x68, 0xBA, 0x59, 0x13, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xD3, 0xC5, 0x56, 0xC9, 0x8C, 0x5E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC6, 0x9F, 0xF4, 0xE6, 0xF7, 0xB4, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x7C, 0x03, 0x00, 0x26, 0x9F, 0xD8, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x1D, 0x6E, 0x00, 0xB9, 0x00, 0x6E, 0x93),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_23_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x63, 0xDA, 0x03, 0x2B, 0xD5, 0x0B, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xFC, 0xE2, 0xC8, 0x47, 0xF0, 0xAE, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x4C, 0xF7, 0x50, 0x0C, 0x48, 0x06, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2B, 0x32, 0x98, 0x0E, 0x7E, 0x61, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x02, 0x27, 0xFE, 0x75, 0x86, 0xDF, 0x24),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x30, 0xB1, 0x22, 0x32, 0x1B, 0xFE, 0x24),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x27, 0xF7, 0x78, 0x6F, 0xD7, 0xFD, 0xE4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x78, 0xCC, 0xEA, 0xC0, 0x50, 0x24, 0x44),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_24_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x2B, 0x4F, 0x7F, 0x58, 0xE6, 0xC2, 0x70),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x43, 0xD5, 0xA7, 0x35, 0x3C, 0x80, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x6D, 0x4B, 0x12, 0x00, 0x7B, 0xE6, 0xA6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x15, 0xBD, 0xD0, 0x9B, 0xCA, 0xAA, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xCE, 0x9C, 0xE3, 0x8B, 0x60, 0x7A, 0x53),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xDA, 0x4B, 0x03, 0xA7, 0x8D, 0x43, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAF, 0x00, 0x2B, 0x32, 0xF0, 0x22, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xD9, 0x99, 0x99, 0xBE, 0x43, 0x99, 0x3E),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_24_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x71, 0x41, 0xF4, 0xB5, 0xFD, 0xDD, 0x36),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xE2, 0x20, 0x4C, 0xD1, 0x2E, 0x1F, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x43, 0x48, 0x76, 0x8A, 0x49, 0xAC, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1A, 0x55, 0xA8, 0xA3, 0xD4, 0x57, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xA6, 0x84, 0x39, 0xC9, 0x13, 0xBB, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xFA, 0xA9, 0x70, 0xDE, 0x83, 0xDD, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xC9, 0xD9, 0x3E, 0x44, 0x91, 0x68, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x9F, 0x85, 0x6D, 0xF7, 0x54, 0x36, 0x82),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_25_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x6B, 0xA6, 0xA3, 0xE5, 0xD4, 0x46, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x3E, 0xDC, 0x84, 0x7C, 0x7B, 0x24, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xED, 0x7F, 0x86, 0x07, 0x6C, 0x57, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x06, 0xFE, 0x52, 0x12, 0x79, 0x69, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xD1, 0x44, 0x5F, 0x21, 0x3A, 0xC3, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD9, 0x4A, 0xC0, 0x75, 0xAB, 0x17, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x81, 0x94, 0xB6, 0x80, 0x6B, 0x6F, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBE, 0x8E, 0xA5, 0xAA, 0xBC, 0x1E, 0x3E),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_25_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xC7, 0x85, 0xA6, 0x59, 0x9B, 0xB1, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xCE, 0x40, 0xD1, 0xFB, 0xDF, 0x94, 0xF7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xB8, 0x5E, 0xBF, 0x45, 0xA8, 0x2D, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9C, 0x06, 0x1B, 0xA9, 0x57, 0xB9, 0x79),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xE9, 0xCE, 0xA2, 0xD3, 0x74, 0xA1, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x5F, 0x34, 0x78, 0xDB, 0xAE, 0x3A, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x32, 0x84, 0x3E, 0x68, 0x6A, 0x43, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xBC, 0x39, 0x36, 0xA4, 0xC5, 0xBB, 0x11),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_26_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x07, 0xA2, 0xB5, 0xC9, 0x0F, 0x4D, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0x67, 0xE6, 0xF1, 0x46, 0xEB, 0x71),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x41, 0x23, 0x95, 0xE7, 0xE0, 0x10, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x69, 0xFE, 0x68, 0x8C, 0xC6, 0x5F, 0xB6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB9, 0x2B, 0x3D, 0xD2, 0x4F, 0xD8, 0x1A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x09, 0xF5, 0x5F, 0xCF, 0xF6, 0x91, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x15, 0x42, 0x6B, 0x6D, 0xB5, 0xF3, 0xB6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x56, 0x9D, 0xC5, 0xFF, 0xCA, 0x13, 0x9B),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_26_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x38, 0xE6, 0x23, 0x63, 0x48, 0x3C, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x68, 0x3C, 0xD1, 0x3B, 0xE9, 0x3B, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x08, 0x54, 0x49, 0xD1, 0x46, 0x45, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x70, 0x52, 0x6E, 0x79, 0xC4, 0x5E, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xDF, 0xE8, 0x5A, 0x32, 0x81, 0xDA, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x2D, 0x94, 0x5B, 0xB5, 0x35, 0x9F, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x12, 0x8D, 0xC3, 0x36, 0x36, 0xB2, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x2F, 0x22, 0x38, 0x5B, 0x18, 0x4C, 0x35),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_27_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC1, 0x22, 0x0E, 0xF0, 0x73, 0x11, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xAE, 0xA4, 0x56, 0x18, 0x61, 0x66, 0x12),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFB, 0x72, 0x08, 0x84, 0x38, 0x51, 0xB0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x86, 0xA8, 0xB9, 0x31, 0x99, 0x29, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xFB, 0xC3, 0x42, 0xB3, 0xC7, 0x6F, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xF8, 0xE1, 0x09, 0xBE, 0x75, 0xB0, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x7D, 0xFF, 0xF4, 0x99, 0xFC, 0x13, 0xAB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x1B, 0x84, 0x81, 0x42, 0x22, 0xC6, 0x3D),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_27_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE0, 0x37, 0xA4, 0xA0, 0x2F, 0x38, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x3D, 0xB7, 0x40, 0x2F, 0x39, 0x3C, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x3B, 0x8A, 0x51, 0xAE, 0x40, 0x49, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x20, 0x9F, 0xDD, 0xA9, 0xD0, 0x77, 0xC7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x1D, 0x64, 0xDA, 0xA0, 0x53, 0xC7, 0x7D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x7B, 0x66, 0x55, 0x94, 0xD1, 0x51, 0x44),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xB5, 0x5B, 0x38, 0x35, 0x40, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0x0F, 0xF0, 0x73, 0x79, 0x43, 0x61),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_28_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x47, 0x45, 0x69, 0x80, 0x72, 0x72, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x11, 0x99, 0x59, 0xDB, 0x48, 0x80, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x6E, 0x3D, 0xFC, 0x37, 0x15, 0xF4, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xBB, 0x5B, 0xA6, 0x35, 0x8D, 0x28, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x1A, 0x3B, 0x2C, 0x8F, 0xD3, 0xAA, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x1C, 0x1A, 0xF8, 0x02, 0xD9, 0x7B, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x69, 0xAC, 0xF8, 0x54, 0x31, 0x14, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x8A, 0xE6, 0xDE, 0x58, 0xB9, 0xC4, 0x7A),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_28_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x83, 0x52, 0xFE, 0xF9, 0x7B, 0xE9, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xA2, 0x55, 0x46, 0x15, 0x49, 0xC1, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBC, 0x5C, 0x91, 0xBD, 0xB9, 0x9C, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xFD, 0xB1, 0x4E, 0x5F, 0x74, 0xEE, 0x53),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x8B, 0xD8, 0x8B, 0x17, 0x73, 0x1B, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x92, 0xD7, 0x67, 0x06, 0xAD, 0x25, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0x80, 0x24, 0xE2, 0x27, 0x5F, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x1C, 0xCE, 0xD0, 0x67, 0xCA, 0xD4, 0x0B),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_29_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xF1, 0xDD, 0x33, 0x66, 0xF9, 0x05, 0xD6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xE5, 0x6B, 0x79, 0xBD, 0x48, 0x42, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x14, 0x52, 0xE3, 0x53, 0xB4, 0x50, 0xD4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x84, 0x6C, 0xCF, 0xDA, 0xB2, 0x20, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xD6, 0x1A, 0xE5, 0xE2, 0x29, 0x70, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x61, 0xFE, 0xBB, 0x21, 0x82, 0xD1, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0xF0, 0x9C, 0x8B, 0x1A, 0x42, 0x30, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xD6, 0x49, 0x81, 0x92, 0xF1, 0xD0, 0x90),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_29_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x91, 0x93, 0x6A, 0xA6, 0x22, 0xE9, 0xD6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xDC, 0xC3, 0x69, 0x11, 0x95, 0x7D, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xA3, 0x9D, 0x87, 0x5E, 0x64, 0x41, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x87, 0x5A, 0x15, 0xBD, 0x6E, 0x3C, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x8D, 0x50, 0xCC, 0xCF, 0xB7, 0x8F, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x65, 0xCD, 0x31, 0x30, 0xF1, 0x68, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x5C, 0x66, 0x67, 0x92, 0x30, 0x57, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x9B, 0x01, 0x3D, 0x20, 0x8B, 0xD1, 0x0D),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_30_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC0, 0xE6, 0x4F, 0xDE, 0x62, 0xAB, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x48, 0xB3, 0x1C, 0x0F, 0x16, 0x93, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x63, 0xBD, 0x1F, 0x16, 0x50, 0x56, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x06, 0xBC, 0xE9, 0x27, 0x1C, 0x9A, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xFE, 0x21, 0xC5, 0x39, 0x55, 0xE1, 0xFD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA8, 0xD0, 0x96, 0x0E, 0xB5, 0xB2, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xE7, 0x4B, 0xF3, 0x11, 0x0C, 0xC9, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x3A, 0xC4, 0x87, 0x71, 0xEE, 0xFA, 0x18),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_30_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x77, 0xEE, 0x81, 0x5E, 0x96, 0xEA, 0x4B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xDF, 0xA9, 0xF4, 0x4F, 0x7C, 0xB2, 0x43),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD4, 0xDF, 0x35, 0x63, 0x47, 0x25, 0x8A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3D, 0xFF, 0xA4, 0x02, 0xC3, 0x95, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x10, 0x78, 0xD1, 0x2B, 0xB7, 0xBE, 0x0E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE9, 0x57, 0xF9, 0xE0, 0xD8, 0xFC, 0xBC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xC4, 0x01, 0xD6, 0xB4, 0xE7, 0x78, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6C, 0xB9, 0x13, 0xA4, 0xE8, 0x6D, 0x6F),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_31_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xB0, 0xC9, 0xCD, 0xBF, 0xA2, 0x1E, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x4F, 0x86, 0x22, 0x9B, 0xEA, 0xE8, 0xBB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x46, 0xDF, 0x43, 0xB9, 0x82, 0x2D, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x32, 0xF1, 0x4E, 0x95, 0x41, 0xAE, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x93, 0x26, 0xFC, 0xD3, 0x90, 0xDC, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x05, 0x45, 0xCA, 0xF9, 0x5A, 0x89, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x82, 0x63, 0x4E, 0x55, 0x1D, 0x3A, 0x08),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x69, 0x52, 0x49, 0xE9, 0xED, 0x57, 0x34),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_31_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x64, 0xE9, 0xAC, 0x4C, 0x4A, 0xEA, 0x25),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xE9, 0x0B, 0x99, 0xE7, 0xF9, 0xA9, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x0C, 0xC1, 0xF4, 0x8D, 0x07, 0xB6, 0xB1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x68, 0xFA, 0x35, 0xE4, 0x9E, 0xAE, 0xD9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2D, 0x1A, 0x13, 0x8E, 0x02, 0xE2, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x28, 0x86, 0x46, 0x7B, 0x3A, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4C, 0x64, 0x59, 0x0A, 0xF9, 0x02, 0xC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x4F, 0x23, 0xA2, 0xC3, 0xD5, 0xEF, 0x42),
+};
+static const mbedtls_ecp_point brainpoolP512r1_T[32] = {
+    ECP_POINT_INIT_XY_Z1(brainpoolP512r1_T_0_X, brainpoolP512r1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_1_X, brainpoolP512r1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_2_X, brainpoolP512r1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_3_X, brainpoolP512r1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_4_X, brainpoolP512r1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_5_X, brainpoolP512r1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_6_X, brainpoolP512r1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_7_X, brainpoolP512r1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_8_X, brainpoolP512r1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_9_X, brainpoolP512r1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_10_X, brainpoolP512r1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_11_X, brainpoolP512r1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_12_X, brainpoolP512r1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_13_X, brainpoolP512r1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_14_X, brainpoolP512r1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_15_X, brainpoolP512r1_T_15_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_16_X, brainpoolP512r1_T_16_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_17_X, brainpoolP512r1_T_17_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_18_X, brainpoolP512r1_T_18_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_19_X, brainpoolP512r1_T_19_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_20_X, brainpoolP512r1_T_20_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_21_X, brainpoolP512r1_T_21_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_22_X, brainpoolP512r1_T_22_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_23_X, brainpoolP512r1_T_23_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_24_X, brainpoolP512r1_T_24_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_25_X, brainpoolP512r1_T_25_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_26_X, brainpoolP512r1_T_26_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_27_X, brainpoolP512r1_T_27_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_28_X, brainpoolP512r1_T_28_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_29_X, brainpoolP512r1_T_29_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_30_X, brainpoolP512r1_T_30_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_31_X, brainpoolP512r1_T_31_Y),
+};
+#else
+#define brainpoolP512r1_T NULL
+#endif
+#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
+
+
+#if defined(ECP_LOAD_GROUP) || defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \
+    defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
 /*
  * Domain parameters for SM2 (GM/T 0003 Part 5)
  */
@@ -576,288 +4545,323 @@
     MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ),
     MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ),
 };
+#define sm2_T NULL
 #endif /* MBEDTLS_ECP_DP_SM2_ENABLED */
 /*
  * Create an MPI from embedded constants
- * (assumes len is an exact multiple of sizeof mbedtls_mpi_uint)
+ * (assumes len is an exact multiple of sizeof(mbedtls_mpi_uint))
  */
-static inline void ecp_mpi_load( mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len )
+static inline void ecp_mpi_load(mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len)
 {
     X->s = 1;
-    X->n = len / sizeof( mbedtls_mpi_uint );
+    X->n = len / sizeof(mbedtls_mpi_uint);
     X->p = (mbedtls_mpi_uint *) p;
 }
+#endif
 
+#if defined(ECP_LOAD_GROUP)
 /*
  * Set an MPI to static value 1
  */
-static inline void ecp_mpi_set1( mbedtls_mpi *X )
+static inline void ecp_mpi_set1(mbedtls_mpi *X)
 {
-    static mbedtls_mpi_uint one[] = { 1 };
     X->s = 1;
     X->n = 1;
-    X->p = one;
+    X->p = mpi_one;
 }
 
 /*
  * Make group available from embedded constants
  */
-static int ecp_group_load( mbedtls_ecp_group *grp,
-                           const mbedtls_mpi_uint *p,  size_t plen,
-                           const mbedtls_mpi_uint *a,  size_t alen,
-                           const mbedtls_mpi_uint *b,  size_t blen,
-                           const mbedtls_mpi_uint *gx, size_t gxlen,
-                           const mbedtls_mpi_uint *gy, size_t gylen,
-                           const mbedtls_mpi_uint *n,  size_t nlen)
+static int ecp_group_load(mbedtls_ecp_group *grp,
+                          const mbedtls_mpi_uint *p,  size_t plen,
+                          const mbedtls_mpi_uint *a,  size_t alen,
+                          const mbedtls_mpi_uint *b,  size_t blen,
+                          const mbedtls_mpi_uint *gx, size_t gxlen,
+                          const mbedtls_mpi_uint *gy, size_t gylen,
+                          const mbedtls_mpi_uint *n,  size_t nlen,
+                          const mbedtls_ecp_point *T)
 {
-    ecp_mpi_load( &grp->P, p, plen );
-    if( a != NULL )
-        ecp_mpi_load( &grp->A, a, alen );
-    ecp_mpi_load( &grp->B, b, blen );
-    ecp_mpi_load( &grp->N, n, nlen );
+    ecp_mpi_load(&grp->P, p, plen);
+    if (a != NULL) {
+        ecp_mpi_load(&grp->A, a, alen);
+    }
+    ecp_mpi_load(&grp->B, b, blen);
+    ecp_mpi_load(&grp->N, n, nlen);
 
-    ecp_mpi_load( &grp->G.X, gx, gxlen );
-    ecp_mpi_load( &grp->G.Y, gy, gylen );
-    ecp_mpi_set1( &grp->G.Z );
+    ecp_mpi_load(&grp->G.X, gx, gxlen);
+    ecp_mpi_load(&grp->G.Y, gy, gylen);
+    ecp_mpi_set1(&grp->G.Z);
 
-    grp->pbits = mbedtls_mpi_bitlen( &grp->P );
-    grp->nbits = mbedtls_mpi_bitlen( &grp->N );
+    grp->pbits = mbedtls_mpi_bitlen(&grp->P);
+    grp->nbits = mbedtls_mpi_bitlen(&grp->N);
 
     grp->h = 1;
 
-    return( 0 );
+    grp->T = (mbedtls_ecp_point *) T;
+    /*
+     * Set T_size to 0 to prevent T free by mbedtls_ecp_group_free.
+     */
+    grp->T_size = 0;
+
+    return 0;
 }
 #endif /* ECP_LOAD_GROUP */
 
 #if defined(MBEDTLS_ECP_NIST_OPTIM)
 /* Forward declarations */
 #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
-static int ecp_mod_p192( mbedtls_mpi * );
+static int ecp_mod_p192(mbedtls_mpi *);
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn);
 #endif
 #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
-static int ecp_mod_p224( mbedtls_mpi * );
+static int ecp_mod_p224(mbedtls_mpi *);
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs);
 #endif
 #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
-static int ecp_mod_p256( mbedtls_mpi * );
+static int ecp_mod_p256(mbedtls_mpi *);
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs);
 #endif
 #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
-static int ecp_mod_p384( mbedtls_mpi * );
+static int ecp_mod_p384(mbedtls_mpi *);
 #endif
 #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
-static int ecp_mod_p521( mbedtls_mpi * );
+static int ecp_mod_p521(mbedtls_mpi *);
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *N_p, size_t N_n);
 #endif
 
-#define NIST_MODP( P )      grp->modp = ecp_mod_ ## P;
+#define NIST_MODP(P)      grp->modp = ecp_mod_ ## P;
 #else
-#define NIST_MODP( P )
+#define NIST_MODP(P)
 #endif /* MBEDTLS_ECP_NIST_OPTIM */
 
 /* Additional forward declarations */
 #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
-static int ecp_mod_p255( mbedtls_mpi * );
+static int ecp_mod_p255(mbedtls_mpi *);
 #endif
 #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
-static int ecp_mod_p448( mbedtls_mpi * );
+static int ecp_mod_p448(mbedtls_mpi *);
 #endif
 #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
-static int ecp_mod_p192k1( mbedtls_mpi * );
+static int ecp_mod_p192k1(mbedtls_mpi *);
 #endif
 #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
-static int ecp_mod_p224k1( mbedtls_mpi * );
+static int ecp_mod_p224k1(mbedtls_mpi *);
 #endif
 #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
-static int ecp_mod_p256k1( mbedtls_mpi * );
+static int ecp_mod_p256k1(mbedtls_mpi *);
 #endif
 
 #if defined(ECP_LOAD_GROUP)
-#define LOAD_GROUP_A( G )   ecp_group_load( grp,            \
-                            G ## _p,  sizeof( G ## _p  ),   \
-                            G ## _a,  sizeof( G ## _a  ),   \
-                            G ## _b,  sizeof( G ## _b  ),   \
-                            G ## _gx, sizeof( G ## _gx ),   \
-                            G ## _gy, sizeof( G ## _gy ),   \
-                            G ## _n,  sizeof( G ## _n  ) )
+#define LOAD_GROUP_A(G)   ecp_group_load(grp,            \
+                                         G ## _p,  sizeof(G ## _p),   \
+                                         G ## _a,  sizeof(G ## _a),   \
+                                         G ## _b,  sizeof(G ## _b),   \
+                                         G ## _gx, sizeof(G ## _gx),   \
+                                         G ## _gy, sizeof(G ## _gy),   \
+                                         G ## _n,  sizeof(G ## _n),   \
+                                         G ## _T                         \
+                                         )
 
-#define LOAD_GROUP( G )     ecp_group_load( grp,            \
-                            G ## _p,  sizeof( G ## _p  ),   \
-                            NULL,     0,                    \
-                            G ## _b,  sizeof( G ## _b  ),   \
-                            G ## _gx, sizeof( G ## _gx ),   \
-                            G ## _gy, sizeof( G ## _gy ),   \
-                            G ## _n,  sizeof( G ## _n  ) )
+#define LOAD_GROUP(G)     ecp_group_load(grp,            \
+                                         G ## _p,  sizeof(G ## _p),   \
+                                         NULL,     0,                    \
+                                         G ## _b,  sizeof(G ## _b),   \
+                                         G ## _gx, sizeof(G ## _gx),   \
+                                         G ## _gy, sizeof(G ## _gy),   \
+                                         G ## _n,  sizeof(G ## _n),   \
+                                         G ## _T                         \
+                                         )
 #endif /* ECP_LOAD_GROUP */
 
 #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
 /* Constants used by ecp_use_curve25519() */
 static const mbedtls_mpi_sint curve25519_a24 = 0x01DB42;
-static const unsigned char curve25519_part_of_n[] = {
-    0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, 0x9C, 0xD6,
-    0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED,
+
+/* P = 2^255 - 19 */
+static const mbedtls_mpi_uint curve25519_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X7F)
+};
+
+/* N = 2^252 + 27742317777372353535851937790883648493 */
+static const mbedtls_mpi_uint curve25519_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0XED, 0XD3, 0XF5, 0X5C, 0X1A, 0X63, 0X12, 0X58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XD6, 0X9C, 0XF7, 0XA2, 0XDE, 0XF9, 0XDE, 0X14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0x00, 0x00, 0x00, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10)
 };
 
 /*
  * Specialized function for creating the Curve25519 group
  */
-static int ecp_use_curve25519( mbedtls_ecp_group *grp )
+static int ecp_use_curve25519(mbedtls_ecp_group *grp)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     /* Actually ( A + 2 ) / 4 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->A, curve25519_a24 ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve25519_a24));
 
-    /* P = 2^255 - 19 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 255 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 19 ) );
-    grp->pbits = mbedtls_mpi_bitlen( &grp->P );
+    ecp_mpi_load(&grp->P, curve25519_p, sizeof(curve25519_p));
 
-    /* N = 2^252 + 27742317777372353535851937790883648493 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &grp->N,
-                     curve25519_part_of_n, sizeof( curve25519_part_of_n ) ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 252, 1 ) );
+    grp->pbits = mbedtls_mpi_bitlen(&grp->P);
+
+    ecp_mpi_load(&grp->N, curve25519_n, sizeof(curve25519_n));
 
     /* Y intentionally not set, since we use x/z coordinates.
      * This is used as a marker to identify Montgomery curves! */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 9 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) );
-    mbedtls_mpi_free( &grp->G.Y );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 9));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1));
+    mbedtls_mpi_free(&grp->G.Y);
 
     /* Actually, the required msb for private keys */
     grp->nbits = 254;
 
 cleanup:
-    if( ret != 0 )
-        mbedtls_ecp_group_free( grp );
+    if (ret != 0) {
+        mbedtls_ecp_group_free(grp);
+    }
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
 /* Constants used by ecp_use_curve448() */
 static const mbedtls_mpi_sint curve448_a24 = 0x98AA;
-static const unsigned char curve448_part_of_n[] = {
-    0x83, 0x35, 0xDC, 0x16, 0x3B, 0xB1, 0x24,
-    0xB6, 0x51, 0x29, 0xC9, 0x6F, 0xDE, 0x93,
-    0x3D, 0x8D, 0x72, 0x3A, 0x70, 0xAA, 0xDC,
-    0x87, 0x3D, 0x6D, 0x54, 0xA7, 0xBB, 0x0D,
+
+/* P = 2^448 - 2^224 - 1 */
+static const mbedtls_mpi_uint curve448_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFE, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00)
+};
+
+/* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */
+static const mbedtls_mpi_uint curve448_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0XF3, 0X44, 0X58, 0XAB, 0X92, 0XC2, 0X78, 0X23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0X55, 0X8F, 0XC5, 0X8D, 0X72, 0XC2, 0X6C, 0X21),
+    MBEDTLS_BYTES_TO_T_UINT_8(0X90, 0X36, 0XD6, 0XAE, 0X49, 0XDB, 0X4E, 0XC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XE9, 0X23, 0XCA, 0X7C, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00)
 };
 
 /*
  * Specialized function for creating the Curve448 group
  */
-static int ecp_use_curve448( mbedtls_ecp_group *grp )
+static int ecp_use_curve448(mbedtls_ecp_group *grp)
 {
-    mbedtls_mpi Ns;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    mbedtls_mpi_init( &Ns );
-
     /* Actually ( A + 2 ) / 4 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->A, curve448_a24 ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve448_a24));
 
-    /* P = 2^448 - 2^224 - 1 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) );
-    grp->pbits = mbedtls_mpi_bitlen( &grp->P );
+    ecp_mpi_load(&grp->P, curve448_p, sizeof(curve448_p));
+    grp->pbits = mbedtls_mpi_bitlen(&grp->P);
 
     /* Y intentionally not set, since we use x/z coordinates.
      * This is used as a marker to identify Montgomery curves! */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 5 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) );
-    mbedtls_mpi_free( &grp->G.Y );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 5));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1));
+    mbedtls_mpi_free(&grp->G.Y);
 
-    /* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 446, 1 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &Ns,
-                        curve448_part_of_n, sizeof( curve448_part_of_n ) ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &grp->N, &grp->N, &Ns ) );
+    ecp_mpi_load(&grp->N, curve448_n, sizeof(curve448_n));
 
     /* Actually, the required msb for private keys */
     grp->nbits = 447;
 
 cleanup:
-    mbedtls_mpi_free( &Ns );
-    if( ret != 0 )
-        mbedtls_ecp_group_free( grp );
+    if (ret != 0) {
+        mbedtls_ecp_group_free(grp);
+    }
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */
 
 /*
  * Set a group using well-known domain parameters
  */
-int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id )
+int mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id)
 {
-    ECP_VALIDATE_RET( grp != NULL );
-    mbedtls_ecp_group_free( grp );
+    ECP_VALIDATE_RET(grp != NULL);
+    mbedtls_ecp_group_free(grp);
 
-    mbedtls_ecp_group_init( grp );
+    mbedtls_ecp_group_init(grp);
 
     grp->id = id;
 
-    switch( id )
-    {
+    switch (id) {
 #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
         case MBEDTLS_ECP_DP_SECP192R1:
-            NIST_MODP( p192 );
-            return( LOAD_GROUP( secp192r1 ) );
+            NIST_MODP(p192);
+            return LOAD_GROUP(secp192r1);
 #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
         case MBEDTLS_ECP_DP_SECP224R1:
-            NIST_MODP( p224 );
-            return( LOAD_GROUP( secp224r1 ) );
+            NIST_MODP(p224);
+            return LOAD_GROUP(secp224r1);
 #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
         case MBEDTLS_ECP_DP_SECP256R1:
-            NIST_MODP( p256 );
-            return( LOAD_GROUP( secp256r1 ) );
+            NIST_MODP(p256);
+            return LOAD_GROUP(secp256r1);
 #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
         case MBEDTLS_ECP_DP_SECP384R1:
-            NIST_MODP( p384 );
-            return( LOAD_GROUP( secp384r1 ) );
+            NIST_MODP(p384);
+            return LOAD_GROUP(secp384r1);
 #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
         case MBEDTLS_ECP_DP_SECP521R1:
-            NIST_MODP( p521 );
-            return( LOAD_GROUP( secp521r1 ) );
+            NIST_MODP(p521);
+            return LOAD_GROUP(secp521r1);
 #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
         case MBEDTLS_ECP_DP_SECP192K1:
             grp->modp = ecp_mod_p192k1;
-            return( LOAD_GROUP_A( secp192k1 ) );
+            return LOAD_GROUP_A(secp192k1);
 #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
         case MBEDTLS_ECP_DP_SECP224K1:
             grp->modp = ecp_mod_p224k1;
-            return( LOAD_GROUP_A( secp224k1 ) );
+            return LOAD_GROUP_A(secp224k1);
 #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
         case MBEDTLS_ECP_DP_SECP256K1:
             grp->modp = ecp_mod_p256k1;
-            return( LOAD_GROUP_A( secp256k1 ) );
+            return LOAD_GROUP_A(secp256k1);
 #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
         case MBEDTLS_ECP_DP_BP256R1:
-            return( LOAD_GROUP_A( brainpoolP256r1 ) );
+            return LOAD_GROUP_A(brainpoolP256r1);
 #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
         case MBEDTLS_ECP_DP_BP384R1:
-            return( LOAD_GROUP_A( brainpoolP384r1 ) );
+            return LOAD_GROUP_A(brainpoolP384r1);
 #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_SM2_ENABLED)
@@ -867,24 +4871,24 @@
 
 #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
         case MBEDTLS_ECP_DP_BP512R1:
-            return( LOAD_GROUP_A( brainpoolP512r1 ) );
+            return LOAD_GROUP_A(brainpoolP512r1);
 #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
         case MBEDTLS_ECP_DP_CURVE25519:
             grp->modp = ecp_mod_p255;
-            return( ecp_use_curve25519( grp ) );
+            return ecp_use_curve25519(grp);
 #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
         case MBEDTLS_ECP_DP_CURVE448:
             grp->modp = ecp_mod_p448;
-            return( ecp_use_curve448( grp ) );
+            return ecp_use_curve448(grp);
 #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */
 
         default:
             grp->id = MBEDTLS_ECP_DP_NONE;
-            return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+            return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
     }
 }
 
@@ -913,56 +4917,77 @@
  */
 
 /* Add 64-bit chunks (dst += src) and update carry */
-static inline void add64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry )
+static inline void add64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry)
 {
     unsigned char i;
     mbedtls_mpi_uint c = 0;
-    for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++, src++ )
-    {
-        *dst += c;      c  = ( *dst < c );
-        *dst += *src;   c += ( *dst < *src );
+    for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++, src++) {
+        *dst += c;      c  = (*dst < c);
+        *dst += *src;   c += (*dst < *src);
     }
     *carry += c;
 }
 
 /* Add carry to a 64-bit chunk and update carry */
-static inline void carry64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry )
+static inline void carry64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry)
 {
     unsigned char i;
-    for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++ )
-    {
+    for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++) {
         *dst += *carry;
-        *carry  = ( *dst < *carry );
+        *carry  = (*dst < *carry);
     }
 }
 
-#define WIDTH       8 / sizeof( mbedtls_mpi_uint )
-#define A( i )      N->p + (i) * WIDTH
-#define ADD( i )    add64( p, A( i ), &c )
-#define NEXT        p += WIDTH; carry64( p, &c )
-#define LAST        p += WIDTH; *p = c; while( ++p < end ) *p = 0
+#define WIDTH       8 / sizeof(mbedtls_mpi_uint)
+#define A(i)        Np + (i) * WIDTH
+#define ADD(i)      add64(p, A(i), &c)
+#define NEXT        p += WIDTH; carry64(p, &c)
+#define LAST        p += WIDTH; *p = c; while (++p < end) *p = 0
+#define RESET       last_carry[0] = c; c = 0; p = Np
+#define ADD_LAST    add64(p, last_carry, &c)
 
 /*
  * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1)
  */
-static int ecp_mod_p192( mbedtls_mpi *N )
+static int ecp_mod_p192(mbedtls_mpi *N)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_mpi_uint c = 0;
-    mbedtls_mpi_uint *p, *end;
-
-    /* Make sure we have enough blocks so that A(5) is legal */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, 6 * WIDTH ) );
-
-    p = N->p;
-    end = p + N->n;
-
-    ADD( 3 ); ADD( 5 );             NEXT; // A0 += A3 + A5
-    ADD( 3 ); ADD( 4 ); ADD( 5 );   NEXT; // A1 += A3 + A4 + A5
-    ADD( 4 ); ADD( 5 );             LAST; // A2 += A4 + A5
+    size_t expected_width = 2 * ((192 + biL - 1) / biL);
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
+    ret = mbedtls_ecp_mod_p192_raw(N->p, expected_width);
 
 cleanup:
-    return( ret );
+    return ret;
+}
+
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn)
+{
+    mbedtls_mpi_uint c = 0, last_carry[WIDTH] = { 0 };
+    mbedtls_mpi_uint *p, *end;
+
+    if (Nn != 2*((192 + biL - 1)/biL)) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    p = Np;
+    end = p + Nn;
+
+    ADD(3); ADD(5);         NEXT;   // A0 += A3 + A5
+    ADD(3); ADD(4); ADD(5); NEXT;   // A1 += A3 + A4 + A5
+    ADD(4); ADD(5);                 // A2 += A4 + A5
+
+    RESET;
+
+    /* Use the reduction for the carry as well:
+     * 2^192 * last_carry = 2^64 * last_carry + last_carry mod P192
+     */
+    ADD_LAST; NEXT;                 // A0 += last_carry
+    ADD_LAST; NEXT;                 // A1 += last_carry
+
+    LAST;                           // A2 += carry
+
+    return 0;
 }
 
 #undef WIDTH
@@ -970,11 +4995,14 @@
 #undef ADD
 #undef NEXT
 #undef LAST
+#undef RESET
+#undef ADD_LAST
 #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \
     defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \
     defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+
 /*
  * The reader is advised to first understand ecp_mod_p192() since the same
  * general structure is used here, but with additional complications:
@@ -991,21 +5019,267 @@
  *
  * While at it, also define the size of N in terms of 32-bit chunks.
  */
-#define LOAD32      cur = A( i );
+#define LOAD32      cur = A(i);
+
+#if defined(MBEDTLS_HAVE_INT32)  /* 32 bit */
+
+#define MAX32       X_limbs
+#define A(j)        X[j]
+#define STORE32     X[i] = (mbedtls_mpi_uint) cur;
+#define STORE0      X[i] = 0;
+
+#else /* 64 bit */
+
+#define MAX32   X_limbs * 2
+#define A(j)                                                \
+    (j) % 2 ?                                               \
+    (uint32_t) (X[(j) / 2] >> 32) :                         \
+    (uint32_t) (X[(j) / 2])
+#define STORE32                                             \
+    if (i % 2) {                                            \
+        X[i/2] &= 0x00000000FFFFFFFF;                       \
+        X[i/2] |= (uint64_t) (cur) << 32;                   \
+    } else {                                                \
+        X[i/2] &= 0xFFFFFFFF00000000;                       \
+        X[i/2] |= (uint32_t) cur;                           \
+    }
+
+#define STORE0                                              \
+    if (i % 2) {                                            \
+        X[i/2] &= 0x00000000FFFFFFFF;                       \
+    } else {                                                \
+        X[i/2] &= 0xFFFFFFFF00000000;                       \
+    }
+
+#endif
+
+static inline int8_t extract_carry(int64_t cur)
+{
+    return (int8_t) (cur >> 32);
+}
+
+#define ADD(j)    cur += A(j)
+#define SUB(j)    cur -= A(j)
+
+#define ADD_CARRY(cc) cur += (cc)
+#define SUB_CARRY(cc) cur -= (cc)
+
+#define ADD_LAST ADD_CARRY(last_c)
+#define SUB_LAST SUB_CARRY(last_c)
+
+/*
+ * Helpers for the main 'loop'
+ */
+#define INIT(b)                                         \
+    int8_t c = 0, last_c;                               \
+    int64_t cur;                                        \
+    size_t i = 0;                                       \
+    LOAD32;
+
+#define NEXT                                            \
+    c = extract_carry(cur);                             \
+    STORE32; i++; LOAD32;                               \
+    ADD_CARRY(c);
+
+#define RESET                                           \
+    c = extract_carry(cur);                             \
+    last_c = c;                                         \
+    STORE32; i = 0; LOAD32;                             \
+    c = 0;                                              \
+
+#define LAST                                            \
+    c = extract_carry(cur);                             \
+    STORE32; i++;                                       \
+    if (c != 0)                                         \
+    return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;              \
+    while (i < MAX32) { STORE0; i++; }
+
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+
+/*
+ * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
+ */
+static int ecp_mod_p224(mbedtls_mpi *N)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t expected_width =  2 * 224 / biL;
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
+    ret = mbedtls_ecp_mod_p224_raw(N->p, expected_width);
+cleanup:
+    return ret;
+}
+
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs)
+{
+    if (X_limbs != 2 * 224 / biL) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    INIT(224);
+
+    SUB(7);  SUB(11);           NEXT;   // A0 += -A7  - A11
+    SUB(8);  SUB(12);           NEXT;   // A1 += -A8  - A12
+    SUB(9);  SUB(13);           NEXT;   // A2 += -A9  - A13
+    SUB(10); ADD(7);  ADD(11);  NEXT;   // A3 += -A10 + A7 + A11
+    SUB(11); ADD(8);  ADD(12);  NEXT;   // A4 += -A11 + A8 + A12
+    SUB(12); ADD(9);  ADD(13);  NEXT;   // A5 += -A12 + A9 + A13
+    SUB(13); ADD(10);                   // A6 += -A13 + A10
+
+    RESET;
+
+    /* Use 2^224 = P + 2^96 - 1 to modulo reduce the final carry */
+    SUB_LAST; NEXT;                     // A0 -= last_c
+    ;         NEXT;                     // A1
+    ;         NEXT;                     // A2
+    ADD_LAST; NEXT;                     // A3 += last_c
+    ;         NEXT;                     // A4
+    ;         NEXT;                     // A5
+                                        // A6
+
+    /* The carry reduction cannot generate a carry
+     * (see commit 73e8553 for details)*/
+
+    LAST;
+
+    return 0;
+}
+
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+
+/*
+ * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)
+ */
+static int ecp_mod_p256(mbedtls_mpi *N)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t expected_width = 2 * 256 / biL;
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
+    ret = mbedtls_ecp_mod_p256_raw(N->p, expected_width);
+cleanup:
+    return ret;
+}
+
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs)
+{
+    if (X_limbs != 2 * 256 / biL) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    INIT(256);
+
+    ADD(8);  ADD(9);
+    SUB(11); SUB(12); SUB(13); SUB(14);                   NEXT; // A0
+
+    ADD(9);  ADD(10);
+    SUB(12); SUB(13); SUB(14); SUB(15);                   NEXT; // A1
+
+    ADD(10); ADD(11);
+    SUB(13); SUB(14); SUB(15);                            NEXT; // A2
+
+    ADD(11); ADD(11); ADD(12); ADD(12); ADD(13);
+    SUB(15); SUB(8);  SUB(9);                             NEXT; // A3
+
+    ADD(12); ADD(12); ADD(13); ADD(13); ADD(14);
+    SUB(9);  SUB(10);                                     NEXT; // A4
+
+    ADD(13); ADD(13); ADD(14); ADD(14); ADD(15);
+    SUB(10); SUB(11);                                     NEXT; // A5
+
+    ADD(14); ADD(14); ADD(15); ADD(15); ADD(14); ADD(13);
+    SUB(8);  SUB(9);                                      NEXT; // A6
+
+    ADD(15); ADD(15); ADD(15); ADD(8);
+    SUB(10); SUB(11); SUB(12); SUB(13);                         // A7
+
+    RESET;
+
+    /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1
+     * to modulo reduce the final carry. */
+    ADD_LAST; NEXT;                                             // A0
+    ;         NEXT;                                             // A1
+    ;         NEXT;                                             // A2
+    SUB_LAST; NEXT;                                             // A3
+    ;         NEXT;                                             // A4
+    ;         NEXT;                                             // A5
+    SUB_LAST; NEXT;                                             // A6
+    ADD_LAST;                                                   // A7
+
+    RESET;
+
+    /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1
+     * to modulo reduce the carry generated by the previous reduction. */
+    ADD_LAST; NEXT;                                             // A0
+    ;         NEXT;                                             // A1
+    ;         NEXT;                                             // A2
+    SUB_LAST; NEXT;                                             // A3
+    ;         NEXT;                                             // A4
+    ;         NEXT;                                             // A5
+    SUB_LAST; NEXT;                                             // A6
+    ADD_LAST;                                                   // A7
+
+    LAST;
+
+    return 0;
+}
+
+#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+
+#undef LOAD32
+#undef MAX32
+#undef A
+#undef STORE32
+#undef STORE0
+#undef ADD
+#undef SUB
+#undef ADD_CARRY
+#undef SUB_CARRY
+#undef ADD_LAST
+#undef SUB_LAST
+#undef INIT
+#undef NEXT
+#undef RESET
+#undef LAST
+
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED ||
+          MBEDTLS_ECP_DP_SECP256R1_ENABLED ||
+          MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+/*
+ * The reader is advised to first understand ecp_mod_p192() since the same
+ * general structure is used here, but with additional complications:
+ * (1) chunks of 32 bits, and (2) subtractions.
+ */
+
+/*
+ * For these primes, we need to handle data in chunks of 32 bits.
+ * This makes it more complicated if we use 64 bits limbs in MPI,
+ * which prevents us from using a uniform access method as for p192.
+ *
+ * So, we define a mini abstraction layer to access 32 bit chunks,
+ * load them in 'cur' for work, and store them back from 'cur' when done.
+ *
+ * While at it, also define the size of N in terms of 32-bit chunks.
+ */
+#define LOAD32      cur = A(i);
 
 #if defined(MBEDTLS_HAVE_INT32)  /* 32 bit */
 
 #define MAX32       N->n
-#define A( j )      N->p[j]
+#define A(j)      N->p[j]
 #define STORE32     N->p[i] = cur;
 
 #else                               /* 64-bit */
 
 #define MAX32       N->n * 2
-#define A( j ) (j) % 2 ? (uint32_t)( N->p[(j)/2] >> 32 ) : \
-                         (uint32_t)( N->p[(j)/2] )
+#define A(j) (j) % 2 ? (uint32_t) (N->p[(j)/2] >> 32) : \
+    (uint32_t) (N->p[(j)/2])
 #define STORE32                                   \
-    if( i % 2 ) {                                 \
+    if (i % 2) {                                 \
         N->p[i/2] &= 0x00000000FFFFFFFF;          \
         N->p[i/2] |= ((mbedtls_mpi_uint) cur) << 32;        \
     } else {                                      \
@@ -1018,190 +5292,129 @@
 /*
  * Helpers for addition and subtraction of chunks, with signed carry.
  */
-static inline void add32( uint32_t *dst, uint32_t src, signed char *carry )
+static inline void add32(uint32_t *dst, uint32_t src, signed char *carry)
 {
     *dst += src;
-    *carry += ( *dst < src );
+    *carry += (*dst < src);
 }
 
-static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry )
+static inline void sub32(uint32_t *dst, uint32_t src, signed char *carry)
 {
-    *carry -= ( *dst < src );
+    *carry -= (*dst < src);
     *dst -= src;
 }
 
-#define ADD( j )    add32( &cur, A( j ), &c );
-#define SUB( j )    sub32( &cur, A( j ), &c );
-
-#define ciL    (sizeof(mbedtls_mpi_uint))         /* chars in limb  */
-#define biL    (ciL << 3)                         /* bits  in limb  */
+#define ADD(j)    add32(&cur, A(j), &c);
+#define SUB(j)    sub32(&cur, A(j), &c);
 
 /*
  * Helpers for the main 'loop'
  */
-#define INIT( b )                                                       \
+#define INIT(b)                                                       \
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;                    \
     signed char c = 0, cc;                                              \
     uint32_t cur;                                                       \
     size_t i = 0, bits = (b);                                           \
     /* N is the size of the product of two b-bit numbers, plus one */   \
     /* limb for fix_negative */                                         \
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, ( b ) * 2 / biL + 1 ) );      \
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, (b) * 2 / biL + 1));      \
     LOAD32;
 
 #define NEXT                    \
     STORE32; i++; LOAD32;       \
     cc = c; c = 0;              \
-    if( cc < 0 )                \
-        sub32( &cur, -cc, &c ); \
+    if (cc < 0)                \
+    sub32(&cur, -cc, &c); \
     else                        \
-        add32( &cur, cc, &c );  \
+    add32(&cur, cc, &c);  \
 
 #define LAST                                    \
     STORE32; i++;                               \
     cur = c > 0 ? c : 0; STORE32;               \
-    cur = 0; while( ++i < MAX32 ) { STORE32; }  \
-    if( c < 0 ) mbedtls_ecp_fix_negative( N, c, bits );
+    cur = 0; while (++i < MAX32) { STORE32; }  \
+    if (c < 0) mbedtls_ecp_fix_negative(N, c, bits);
 
 /*
  * If the result is negative, we get it in the form
  * c * 2^bits + N, with c negative and N positive shorter than 'bits'
  */
 MBEDTLS_STATIC_TESTABLE
-void mbedtls_ecp_fix_negative( mbedtls_mpi *N, signed char c, size_t bits )
+void mbedtls_ecp_fix_negative(mbedtls_mpi *N, signed char c, size_t bits)
 {
     size_t i;
 
     /* Set N := 2^bits - 1 - N. We know that 0 <= N < 2^bits, so
      * set the absolute value to 0xfff...fff - N. There is no carry
      * since we're subtracting from all-bits-one.  */
-    for( i = 0; i <= bits / 8 / sizeof( mbedtls_mpi_uint ); i++ )
-    {
-        N->p[i] = ~(mbedtls_mpi_uint)0 - N->p[i];
+    for (i = 0; i <= bits / 8 / sizeof(mbedtls_mpi_uint); i++) {
+        N->p[i] = ~(mbedtls_mpi_uint) 0 - N->p[i];
     }
     /* Add 1, taking care of the carry. */
     i = 0;
-    do
+    do {
         ++N->p[i];
-    while( N->p[i++] == 0 && i <= bits / 8 / sizeof( mbedtls_mpi_uint ) );
+    } while (N->p[i++] == 0 && i <= bits / 8 / sizeof(mbedtls_mpi_uint));
     /* Invert the sign.
      * Now N = N0 - 2^bits where N0 is the initial value of N. */
     N->s = -1;
 
     /* Add |c| * 2^bits to the absolute value. Since c and N are
-    * negative, this adds c * 2^bits. */
+     * negative, this adds c * 2^bits. */
     mbedtls_mpi_uint msw = (mbedtls_mpi_uint) -c;
 #if defined(MBEDTLS_HAVE_INT64)
-    if( bits == 224 )
+    if (bits == 224) {
         msw <<= 32;
+    }
 #endif
-    N->p[bits / 8 / sizeof( mbedtls_mpi_uint)] += msw;
+    N->p[bits / 8 / sizeof(mbedtls_mpi_uint)] += msw;
 }
 
-#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
-/*
- * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
- */
-static int ecp_mod_p224( mbedtls_mpi *N )
-{
-    INIT( 224 );
-
-    SUB(  7 ); SUB( 11 );               NEXT; // A0 += -A7 - A11
-    SUB(  8 ); SUB( 12 );               NEXT; // A1 += -A8 - A12
-    SUB(  9 ); SUB( 13 );               NEXT; // A2 += -A9 - A13
-    SUB( 10 ); ADD(  7 ); ADD( 11 );    NEXT; // A3 += -A10 + A7 + A11
-    SUB( 11 ); ADD(  8 ); ADD( 12 );    NEXT; // A4 += -A11 + A8 + A12
-    SUB( 12 ); ADD(  9 ); ADD( 13 );    NEXT; // A5 += -A12 + A9 + A13
-    SUB( 13 ); ADD( 10 );               LAST; // A6 += -A13 + A10
-
-cleanup:
-    return( ret );
-}
-#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
-
-#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
-/*
- * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)
- */
-static int ecp_mod_p256( mbedtls_mpi *N )
-{
-    INIT( 256 );
-
-    ADD(  8 ); ADD(  9 );
-    SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 );             NEXT; // A0
-
-    ADD(  9 ); ADD( 10 );
-    SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 );             NEXT; // A1
-
-    ADD( 10 ); ADD( 11 );
-    SUB( 13 ); SUB( 14 ); SUB( 15 );                        NEXT; // A2
-
-    ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 );
-    SUB( 15 ); SUB(  8 ); SUB(  9 );                        NEXT; // A3
-
-    ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 );
-    SUB(  9 ); SUB( 10 );                                   NEXT; // A4
-
-    ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 );
-    SUB( 10 ); SUB( 11 );                                   NEXT; // A5
-
-    ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 );
-    SUB(  8 ); SUB(  9 );                                   NEXT; // A6
-
-    ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 );
-    SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 );             LAST; // A7
-
-cleanup:
-    return( ret );
-}
-#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
-
 #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
 /*
  * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4)
  */
-static int ecp_mod_p384( mbedtls_mpi *N )
+static int ecp_mod_p384(mbedtls_mpi *N)
 {
-    INIT( 384 );
+    INIT(384);
 
-    ADD( 12 ); ADD( 21 ); ADD( 20 );
-    SUB( 23 );                                              NEXT; // A0
+    ADD(12); ADD(21); ADD(20);
+    SUB(23);                                              NEXT;   // A0
 
-    ADD( 13 ); ADD( 22 ); ADD( 23 );
-    SUB( 12 ); SUB( 20 );                                   NEXT; // A2
+    ADD(13); ADD(22); ADD(23);
+    SUB(12); SUB(20);                                   NEXT;     // A2
 
-    ADD( 14 ); ADD( 23 );
-    SUB( 13 ); SUB( 21 );                                   NEXT; // A2
+    ADD(14); ADD(23);
+    SUB(13); SUB(21);                                   NEXT;     // A2
 
-    ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 );
-    SUB( 14 ); SUB( 22 ); SUB( 23 );                        NEXT; // A3
+    ADD(15); ADD(12); ADD(20); ADD(21);
+    SUB(14); SUB(22); SUB(23);                        NEXT;       // A3
 
-    ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 );
-    SUB( 15 ); SUB( 23 ); SUB( 23 );                        NEXT; // A4
+    ADD(21); ADD(21); ADD(16); ADD(13); ADD(12); ADD(20); ADD(22);
+    SUB(15); SUB(23); SUB(23);                        NEXT;       // A4
 
-    ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 );
-    SUB( 16 );                                              NEXT; // A5
+    ADD(22); ADD(22); ADD(17); ADD(14); ADD(13); ADD(21); ADD(23);
+    SUB(16);                                              NEXT;   // A5
 
-    ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 );
-    SUB( 17 );                                              NEXT; // A6
+    ADD(23); ADD(23); ADD(18); ADD(15); ADD(14); ADD(22);
+    SUB(17);                                              NEXT;   // A6
 
-    ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 );
-    SUB( 18 );                                              NEXT; // A7
+    ADD(19); ADD(16); ADD(15); ADD(23);
+    SUB(18);                                              NEXT;   // A7
 
-    ADD( 20 ); ADD( 17 ); ADD( 16 );
-    SUB( 19 );                                              NEXT; // A8
+    ADD(20); ADD(17); ADD(16);
+    SUB(19);                                              NEXT;   // A8
 
-    ADD( 21 ); ADD( 18 ); ADD( 17 );
-    SUB( 20 );                                              NEXT; // A9
+    ADD(21); ADD(18); ADD(17);
+    SUB(20);                                              NEXT;   // A9
 
-    ADD( 22 ); ADD( 19 ); ADD( 18 );
-    SUB( 21 );                                              NEXT; // A10
+    ADD(22); ADD(19); ADD(18);
+    SUB(21);                                              NEXT;   // A10
 
-    ADD( 23 ); ADD( 20 ); ADD( 19 );
-    SUB( 22 );                                              LAST; // A11
+    ADD(23); ADD(20); ADD(19);
+    SUB(22);                                              LAST;   // A11
 
 cleanup:
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
 
@@ -1213,62 +5426,92 @@
 #undef NEXT
 #undef LAST
 
-#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED ||
-          MBEDTLS_ECP_DP_SECP256R1_ENABLED ||
+#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED ||
           MBEDTLS_ECP_DP_SECP384R1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
-/*
- * Here we have an actual Mersenne prime, so things are more straightforward.
- * However, chunks are aligned on a 'weird' boundary (521 bits).
- */
-
 /* Size of p521 in terms of mbedtls_mpi_uint */
-#define P521_WIDTH      ( 521 / 8 / sizeof( mbedtls_mpi_uint ) + 1 )
+#define P521_WIDTH      (521 / 8 / sizeof(mbedtls_mpi_uint) + 1)
 
 /* Bits to keep in the most significant mbedtls_mpi_uint */
 #define P521_MASK       0x01FF
 
 /*
- * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5)
- * Write N as A1 + 2^521 A0, return A0 + A1
+ * Fast quasi-reduction modulo p521 = 2^521 - 1 (FIPS 186-3 D.2.5)
  */
-static int ecp_mod_p521( mbedtls_mpi *N )
+static int ecp_mod_p521(mbedtls_mpi *N)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t i;
-    mbedtls_mpi M;
-    mbedtls_mpi_uint Mp[P521_WIDTH + 1];
-    /* Worst case for the size of M is when mbedtls_mpi_uint is 16 bits:
-     * we need to hold bits 513 to 1056, which is 34 limbs, that is
-     * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */
-
-    if( N->n < P521_WIDTH )
-        return( 0 );
-
-    /* M = A1 */
-    M.s = 1;
-    M.n = N->n - ( P521_WIDTH - 1 );
-    if( M.n > P521_WIDTH + 1 )
-        M.n = P521_WIDTH + 1;
-    M.p = Mp;
-    memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 521 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) );
-
-    /* N = A0 */
-    N->p[P521_WIDTH - 1] &= P521_MASK;
-    for( i = P521_WIDTH; i < N->n; i++ )
-        N->p[i] = 0;
-
-    /* N = A0 + A1 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) );
-
+    size_t expected_width = 2 * P521_WIDTH;
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
+    ret = mbedtls_ecp_mod_p521_raw(N->p, expected_width);
 cleanup:
-    return( ret );
+    return ret;
+}
+
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs)
+{
+    mbedtls_mpi_uint carry = 0;
+
+    if (X_limbs != 2 * P521_WIDTH || X[2 * P521_WIDTH - 1] != 0) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    /* Step 1: Reduction to P521_WIDTH limbs */
+    /* Helper references for bottom part of X */
+    mbedtls_mpi_uint *X0 = X;
+    size_t X0_limbs = P521_WIDTH;
+    /* Helper references for top part of X */
+    mbedtls_mpi_uint *X1 = X + X0_limbs;
+    size_t X1_limbs = X_limbs - X0_limbs;
+    /* Split X as X0 + 2^P521_WIDTH X1 and compute X0 + 2^(biL - 9) X1.
+     * (We are using that 2^P521_WIDTH = 2^(512 + biL) and that
+     * 2^(512 + biL) X1 = 2^(biL - 9) X1 mod P521.)
+     * The high order limb of the result will be held in carry and the rest
+     * in X0 (that is the result will be represented as
+     * 2^P521_WIDTH carry + X0).
+     *
+     * Also, note that the resulting carry is either 0 or 1:
+     * X0 < 2^P521_WIDTH = 2^(512 + biL) and X1 < 2^(P521_WIDTH-biL) = 2^512
+     * therefore
+     * X0 + 2^(biL - 9) X1 < 2^(512 + biL) + 2^(512 + biL - 9)
+     * which in turn is less than 2 * 2^(512 + biL).
+     */
+    mbedtls_mpi_uint shift = ((mbedtls_mpi_uint) 1u) << (biL - 9);
+    carry = mbedtls_mpi_core_mla(X0, X0_limbs, X1, X1_limbs, shift);
+    /* Set X to X0 (by clearing the top part). */
+    memset(X1, 0, X1_limbs * sizeof(mbedtls_mpi_uint));
+
+    /* Step 2: Reduction modulo P521
+     *
+     * At this point X is reduced to P521_WIDTH limbs. What remains is to add
+     * the carry (that is 2^P521_WIDTH carry) and to reduce mod P521. */
+
+    /* 2^P521_WIDTH carry = 2^(512 + biL) carry = 2^(biL - 9) carry mod P521.
+     * Also, recall that carry is either 0 or 1. */
+    mbedtls_mpi_uint addend = carry << (biL - 9);
+    /* Keep the top 9 bits and reduce the rest, using 2^521 = 1 mod P521. */
+    addend += (X[P521_WIDTH - 1] >> 9);
+    X[P521_WIDTH - 1] &= P521_MASK;
+
+    /* Reuse the top part of X (already zeroed) as a helper array for
+     * carrying out the addition. */
+    mbedtls_mpi_uint *addend_arr = X + P521_WIDTH;
+    addend_arr[0] = addend;
+    (void) mbedtls_mpi_core_add(X, X, addend_arr, P521_WIDTH);
+    /* Both addends were less than P521 therefore X < 2 * P521. (This also means
+     * that the result fit in P521_WIDTH limbs and there won't be any carry.) */
+
+    /* Clear the reused part of X. */
+    addend_arr[0] = 0;
+
+    return 0;
 }
 
 #undef P521_WIDTH
 #undef P521_MASK
+
 #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
 
 #endif /* MBEDTLS_ECP_NIST_OPTIM */
@@ -1276,57 +5519,49 @@
 #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
 
 /* Size of p255 in terms of mbedtls_mpi_uint */
-#define P255_WIDTH      ( 255 / 8 / sizeof( mbedtls_mpi_uint ) + 1 )
+#define P255_WIDTH      (255 / 8 / sizeof(mbedtls_mpi_uint) + 1)
 
 /*
  * Fast quasi-reduction modulo p255 = 2^255 - 19
- * Write N as A0 + 2^255 A1, return A0 + 19 * A1
+ * Write N as A0 + 2^256 A1, return A0 + 38 * A1
  */
-static int ecp_mod_p255( mbedtls_mpi *N )
+static int ecp_mod_p255(mbedtls_mpi *N)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t i;
-    mbedtls_mpi M;
-    mbedtls_mpi_uint Mp[P255_WIDTH + 2];
+    mbedtls_mpi_uint Mp[P255_WIDTH];
 
-    if( N->n < P255_WIDTH )
-        return( 0 );
+    /* Helper references for top part of N */
+    mbedtls_mpi_uint * const NT_p = N->p + P255_WIDTH;
+    const size_t NT_n = N->n - P255_WIDTH;
+    if (N->n <= P255_WIDTH) {
+        return 0;
+    }
+    if (NT_n > P255_WIDTH) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
 
-    /* M = A1 */
-    M.s = 1;
-    M.n = N->n - ( P255_WIDTH - 1 );
-    if( M.n > P255_WIDTH + 1 )
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
-    M.p = Mp;
-    memset( Mp, 0, sizeof Mp );
-    memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 255 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) );
-    M.n++; /* Make room for multiplication by 19 */
+    /* Split N as N + 2^256 M */
+    memcpy(Mp,   NT_p, sizeof(mbedtls_mpi_uint) * NT_n);
+    memset(NT_p, 0,    sizeof(mbedtls_mpi_uint) * NT_n);
 
-    /* N = A0 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( N, 255, 0 ) );
-    for( i = P255_WIDTH; i < N->n; i++ )
-        N->p[i] = 0;
+    /* N = A0 + 38 * A1 */
+    mbedtls_mpi_core_mla(N->p, P255_WIDTH + 1,
+                         Mp, NT_n,
+                         38);
 
-    /* N = A0 + 19 * A1 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &M, 19 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) );
-
-cleanup:
-    return( ret );
+    return 0;
 }
 #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
 
 /* Size of p448 in terms of mbedtls_mpi_uint */
-#define P448_WIDTH      ( 448 / 8 / sizeof( mbedtls_mpi_uint ) )
+#define P448_WIDTH      (448 / 8 / sizeof(mbedtls_mpi_uint))
 
 /* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */
-#define DIV_ROUND_UP( X, Y ) ( ( ( X ) + ( Y ) - 1 ) / ( Y ) )
-#define P224_WIDTH_MIN   ( 28 / sizeof( mbedtls_mpi_uint ) )
-#define P224_WIDTH_MAX   DIV_ROUND_UP( 28, sizeof( mbedtls_mpi_uint ) )
-#define P224_UNUSED_BITS ( ( P224_WIDTH_MAX * sizeof( mbedtls_mpi_uint ) * 8 ) - 224 )
+#define DIV_ROUND_UP(X, Y) (((X) + (Y) -1) / (Y))
+#define P224_WIDTH_MIN   (28 / sizeof(mbedtls_mpi_uint))
+#define P224_WIDTH_MAX   DIV_ROUND_UP(28, sizeof(mbedtls_mpi_uint))
+#define P224_UNUSED_BITS ((P224_WIDTH_MAX * sizeof(mbedtls_mpi_uint) * 8) - 224)
 
 /*
  * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1
@@ -1339,52 +5574,57 @@
  * but for 64-bit targets it should use half the number of operations if we do
  * the reduction with 224-bit limbs, since mpi_add_mpi will then use 64-bit adds.
  */
-static int ecp_mod_p448( mbedtls_mpi *N )
+static int ecp_mod_p448(mbedtls_mpi *N)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i;
     mbedtls_mpi M, Q;
     mbedtls_mpi_uint Mp[P448_WIDTH + 1], Qp[P448_WIDTH];
 
-    if( N->n <= P448_WIDTH )
-        return( 0 );
+    if (N->n <= P448_WIDTH) {
+        return 0;
+    }
 
     /* M = A1 */
     M.s = 1;
-    M.n = N->n - ( P448_WIDTH );
-    if( M.n > P448_WIDTH )
+    M.n = N->n - (P448_WIDTH);
+    if (M.n > P448_WIDTH) {
         /* Shouldn't be called with N larger than 2^896! */
-        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
     M.p = Mp;
-    memset( Mp, 0, sizeof( Mp ) );
-    memcpy( Mp, N->p + P448_WIDTH, M.n * sizeof( mbedtls_mpi_uint ) );
+    memset(Mp, 0, sizeof(Mp));
+    memcpy(Mp, N->p + P448_WIDTH, M.n * sizeof(mbedtls_mpi_uint));
 
     /* N = A0 */
-    for( i = P448_WIDTH; i < N->n; i++ )
+    for (i = P448_WIDTH; i < N->n; i++) {
         N->p[i] = 0;
+    }
 
     /* N += A1 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(N, N, &M));
 
     /* Q = B1, N += B1 */
     Q = M;
     Q.p = Qp;
-    memcpy( Qp, Mp, sizeof( Qp ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Q, 224 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &Q ) );
+    memcpy(Qp, Mp, sizeof(Qp));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Q, 224));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(N, N, &Q));
 
     /* M = (B0 + B1) * 2^224, N += M */
-    if( sizeof( mbedtls_mpi_uint ) > 4 )
-        Mp[P224_WIDTH_MIN] &= ( (mbedtls_mpi_uint)-1 ) >> ( P224_UNUSED_BITS );
-    for( i = P224_WIDTH_MAX; i < M.n; ++i )
+    if (sizeof(mbedtls_mpi_uint) > 4) {
+        Mp[P224_WIDTH_MIN] &= ((mbedtls_mpi_uint)-1) >> (P224_UNUSED_BITS);
+    }
+    for (i = P224_WIDTH_MAX; i < M.n; ++i) {
         Mp[i] = 0;
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &Q ) );
+    }
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&M, &M, &Q));
     M.n = P448_WIDTH + 1; /* Make room for shifted carry bit from the addition */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &M, 224 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&M, 224));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(N, N, &M));
 
 cleanup:
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */
 
@@ -1398,18 +5638,19 @@
  * Write N as A0 + 2^224 A1, return A0 + R * A1.
  * Actually do two passes, since R is big.
  */
-#define P_KOBLITZ_MAX   ( 256 / 8 / sizeof( mbedtls_mpi_uint ) )  // Max limbs in P
-#define P_KOBLITZ_R     ( 8 / sizeof( mbedtls_mpi_uint ) )        // Limbs in R
-static inline int ecp_mod_koblitz( mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs,
-                                   size_t adjust, size_t shift, mbedtls_mpi_uint mask )
+#define P_KOBLITZ_MAX   (256 / 8 / sizeof(mbedtls_mpi_uint))      // Max limbs in P
+#define P_KOBLITZ_R     (8 / sizeof(mbedtls_mpi_uint))            // Limbs in R
+static inline int ecp_mod_koblitz(mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs,
+                                  size_t adjust, size_t shift, mbedtls_mpi_uint mask)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i;
     mbedtls_mpi M, R;
     mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1];
 
-    if( N->n < p_limbs )
-        return( 0 );
+    if (N->n < p_limbs) {
+        return 0;
+    }
 
     /* Init R */
     R.s = 1;
@@ -1421,49 +5662,57 @@
     M.p = Mp;
 
     /* M = A1 */
-    M.n = N->n - ( p_limbs - adjust );
-    if( M.n > p_limbs + adjust )
+    M.n = N->n - (p_limbs - adjust);
+    if (M.n > p_limbs + adjust) {
         M.n = p_limbs + adjust;
-    memset( Mp, 0, sizeof Mp );
-    memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) );
-    if( shift != 0 )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) );
+    }
+    memset(Mp, 0, sizeof(Mp));
+    memcpy(Mp, N->p + p_limbs - adjust, M.n * sizeof(mbedtls_mpi_uint));
+    if (shift != 0) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, shift));
+    }
     M.n += R.n; /* Make room for multiplication by R */
 
     /* N = A0 */
-    if( mask != 0 )
+    if (mask != 0) {
         N->p[p_limbs - 1] &= mask;
-    for( i = p_limbs; i < N->n; i++ )
+    }
+    for (i = p_limbs; i < N->n; i++) {
         N->p[i] = 0;
+    }
 
     /* N = A0 + R * A1 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&M, &M, &R));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(N, N, &M));
 
     /* Second pass */
 
     /* M = A1 */
-    M.n = N->n - ( p_limbs - adjust );
-    if( M.n > p_limbs + adjust )
+    M.n = N->n - (p_limbs - adjust);
+    if (M.n > p_limbs + adjust) {
         M.n = p_limbs + adjust;
-    memset( Mp, 0, sizeof Mp );
-    memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) );
-    if( shift != 0 )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) );
+    }
+    memset(Mp, 0, sizeof(Mp));
+    memcpy(Mp, N->p + p_limbs - adjust, M.n * sizeof(mbedtls_mpi_uint));
+    if (shift != 0) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, shift));
+    }
     M.n += R.n; /* Make room for multiplication by R */
 
     /* N = A0 */
-    if( mask != 0 )
+    if (mask != 0) {
         N->p[p_limbs - 1] &= mask;
-    for( i = p_limbs; i < N->n; i++ )
+    }
+    for (i = p_limbs; i < N->n; i++) {
         N->p[i] = 0;
+    }
 
     /* N = A0 + R * A1 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&M, &M, &R));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(N, N, &M));
 
 cleanup:
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) ||
           MBEDTLS_ECP_DP_SECP224K1_ENABLED) ||
@@ -1474,14 +5723,15 @@
  * Fast quasi-reduction modulo p192k1 = 2^192 - R,
  * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119
  */
-static int ecp_mod_p192k1( mbedtls_mpi *N )
+static int ecp_mod_p192k1(mbedtls_mpi *N)
 {
     static mbedtls_mpi_uint Rp[] = {
-        MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00,
-                                   0x00 ) };
+        MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00,
+                                  0x00)
+    };
 
-    return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0,
-                             0 ) );
+    return ecp_mod_koblitz(N, Rp, 192 / 8 / sizeof(mbedtls_mpi_uint), 0, 0,
+                           0);
 }
 #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
 
@@ -1490,17 +5740,18 @@
  * Fast quasi-reduction modulo p224k1 = 2^224 - R,
  * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93
  */
-static int ecp_mod_p224k1( mbedtls_mpi *N )
+static int ecp_mod_p224k1(mbedtls_mpi *N)
 {
     static mbedtls_mpi_uint Rp[] = {
-        MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00,
-                                   0x00 ) };
+        MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00,
+                                  0x00)
+    };
 
 #if defined(MBEDTLS_HAVE_INT64)
-    return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) );
+    return ecp_mod_koblitz(N, Rp, 4, 1, 32, 0xFFFFFFFF);
 #else
-    return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0,
-                             0 ) );
+    return ecp_mod_koblitz(N, Rp, 224 / 8 / sizeof(mbedtls_mpi_uint), 0, 0,
+                           0);
 #endif
 }
 
@@ -1511,16 +5762,199 @@
  * Fast quasi-reduction modulo p256k1 = 2^256 - R,
  * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1
  */
-static int ecp_mod_p256k1( mbedtls_mpi *N )
+static int ecp_mod_p256k1(mbedtls_mpi *N)
 {
     static mbedtls_mpi_uint Rp[] = {
-        MBEDTLS_BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00,
-                                   0x00 ) };
-    return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0,
-                             0 ) );
+        MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00,
+                                  0x00)
+    };
+    return ecp_mod_koblitz(N, Rp, 256 / 8 / sizeof(mbedtls_mpi_uint), 0, 0,
+                           0);
 }
 #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
 
-#endif /* !MBEDTLS_ECP_ALT */
+#if defined(MBEDTLS_TEST_HOOKS)
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N,
+                              const mbedtls_ecp_group_id id,
+                              const mbedtls_ecp_curve_type ctype)
+{
+    mbedtls_mpi_uint *p = NULL;
+    size_t p_limbs;
 
+    if (!(ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE || \
+          ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_SCALAR)) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    switch (id) {
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP192R1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) secp192r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp192r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP224R1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) secp224r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp224r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP256R1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) secp256r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp256r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP384R1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) secp384r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp384r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP521R1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) secp521r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp521r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
+        case MBEDTLS_ECP_DP_BP256R1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) brainpoolP256r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) brainpoolP256r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
+        case MBEDTLS_ECP_DP_BP384R1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) brainpoolP384r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) brainpoolP384r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
+        case MBEDTLS_ECP_DP_BP512R1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) brainpoolP512r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) brainpoolP512r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+        case MBEDTLS_ECP_DP_CURVE25519:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) curve25519_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_p));
+            } else {
+                p = (mbedtls_mpi_uint *) curve25519_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP192K1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) secp192k1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp192k1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP224K1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) secp224k1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp224k1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP256K1:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) secp256k1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp256k1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+        case MBEDTLS_ECP_DP_CURVE448:
+            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) curve448_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(curve448_p));
+            } else {
+                p = (mbedtls_mpi_uint *) curve448_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(curve448_n));
+            }
+            break;
+#endif
+
+        default:
+        case MBEDTLS_ECP_DP_NONE:
+            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    if (mbedtls_mpi_mod_modulus_setup(N, p, p_limbs,
+                                      MBEDTLS_MPI_MOD_REP_MONTGOMERY)) {
+        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    }
+    return 0;
+}
+#endif /* MBEDTLS_TEST_HOOKS */
+#endif /* !MBEDTLS_ECP_ALT */
 #endif /* MBEDTLS_ECP_C */
diff --git a/lib/libmbedtls/mbedtls/library/ecp_internal_alt.h b/lib/libmbedtls/mbedtls/library/ecp_internal_alt.h
new file mode 100644
index 0000000..f663d67
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/ecp_internal_alt.h
@@ -0,0 +1,299 @@
+/**
+ * \file ecp_internal_alt.h
+ *
+ * \brief Function declarations for alternative implementation of elliptic curve
+ * point arithmetic.
+ */
+/*
+ *  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.
+ */
+
+/*
+ * References:
+ *
+ * [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records.
+ *     <http://cr.yp.to/ecdh/curve25519-20060209.pdf>
+ *
+ * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis
+ *     for elliptic curve cryptosystems. In : Cryptographic Hardware and
+ *     Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
+ *     <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
+ *
+ * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to
+ *     render ECC resistant against Side Channel Attacks. IACR Cryptology
+ *     ePrint Archive, 2004, vol. 2004, p. 342.
+ *     <http://eprint.iacr.org/2004/342.pdf>
+ *
+ * [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters.
+ *     <http://www.secg.org/sec2-v2.pdf>
+ *
+ * [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic
+ *     Curve Cryptography.
+ *
+ * [6] Digital Signature Standard (DSS), FIPS 186-4.
+ *     <http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf>
+ *
+ * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer
+ *     Security (TLS), RFC 4492.
+ *     <https://tools.ietf.org/search/rfc4492>
+ *
+ * [8] <http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html>
+ *
+ * [9] COHEN, Henri. A Course in Computational Algebraic Number Theory.
+ *     Springer Science & Business Media, 1 Aug 2000
+ */
+
+#ifndef MBEDTLS_ECP_INTERNAL_H
+#define MBEDTLS_ECP_INTERNAL_H
+
+#include "mbedtls/build_info.h"
+
+#if defined(MBEDTLS_ECP_INTERNAL_ALT)
+
+/**
+ * \brief           Indicate if the Elliptic Curve Point module extension can
+ *                  handle the group.
+ *
+ * \param grp       The pointer to the elliptic curve group that will be the
+ *                  basis of the cryptographic computations.
+ *
+ * \return          Non-zero if successful.
+ */
+unsigned char mbedtls_internal_ecp_grp_capable(const mbedtls_ecp_group *grp);
+
+/**
+ * \brief           Initialise the Elliptic Curve Point module extension.
+ *
+ *                  If mbedtls_internal_ecp_grp_capable returns true for a
+ *                  group, this function has to be able to initialise the
+ *                  module for it.
+ *
+ *                  This module can be a driver to a crypto hardware
+ *                  accelerator, for which this could be an initialise function.
+ *
+ * \param grp       The pointer to the group the module needs to be
+ *                  initialised for.
+ *
+ * \return          0 if successful.
+ */
+int mbedtls_internal_ecp_init(const mbedtls_ecp_group *grp);
+
+/**
+ * \brief           Frees and deallocates the Elliptic Curve Point module
+ *                  extension.
+ *
+ * \param grp       The pointer to the group the module was initialised for.
+ */
+void mbedtls_internal_ecp_free(const mbedtls_ecp_group *grp);
+
+#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
+
+#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
+/**
+ * \brief           Randomize jacobian coordinates:
+ *                  (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l.
+ *
+ * \param grp       Pointer to the group representing the curve.
+ *
+ * \param pt        The point on the curve to be randomised, given with Jacobian
+ *                  coordinates.
+ *
+ * \param f_rng     A function pointer to the random number generator.
+ *
+ * \param p_rng     A pointer to the random number generator state.
+ *
+ * \return          0 if successful.
+ */
+int mbedtls_internal_ecp_randomize_jac(const mbedtls_ecp_group *grp,
+                                       mbedtls_ecp_point *pt, int (*f_rng)(void *,
+                                                                           unsigned char *,
+                                                                           size_t),
+                                       void *p_rng);
+#endif
+
+#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
+/**
+ * \brief           Addition: R = P + Q, mixed affine-Jacobian coordinates.
+ *
+ *                  The coordinates of Q must be normalized (= affine),
+ *                  but those of P don't need to. R is not normalized.
+ *
+ *                  This function is used only as a subrutine of
+ *                  ecp_mul_comb().
+ *
+ *                  Special cases: (1) P or Q is zero, (2) R is zero,
+ *                      (3) P == Q.
+ *                  None of these cases can happen as intermediate step in
+ *                  ecp_mul_comb():
+ *                      - at each step, P, Q and R are multiples of the base
+ *                      point, the factor being less than its order, so none of
+ *                      them is zero;
+ *                      - Q is an odd multiple of the base point, P an even
+ *                      multiple, due to the choice of precomputed points in the
+ *                      modified comb method.
+ *                  So branches for these cases do not leak secret information.
+ *
+ *                  We accept Q->Z being unset (saving memory in tables) as
+ *                  meaning 1.
+ *
+ *                  Cost in field operations if done by [5] 3.22:
+ *                      1A := 8M + 3S
+ *
+ * \param grp       Pointer to the group representing the curve.
+ *
+ * \param R         Pointer to a point structure to hold the result.
+ *
+ * \param P         Pointer to the first summand, given with Jacobian
+ *                  coordinates
+ *
+ * \param Q         Pointer to the second summand, given with affine
+ *                  coordinates.
+ *
+ * \return          0 if successful.
+ */
+int mbedtls_internal_ecp_add_mixed(const mbedtls_ecp_group *grp,
+                                   mbedtls_ecp_point *R, const mbedtls_ecp_point *P,
+                                   const mbedtls_ecp_point *Q);
+#endif
+
+/**
+ * \brief           Point doubling R = 2 P, Jacobian coordinates.
+ *
+ *                  Cost:   1D := 3M + 4S    (A ==  0)
+ *                          4M + 4S          (A == -3)
+ *                          3M + 6S + 1a     otherwise
+ *                  when the implementation is based on the "dbl-1998-cmo-2"
+ *                  doubling formulas in [8] and standard optimizations are
+ *                  applied when curve parameter A is one of { 0, -3 }.
+ *
+ * \param grp       Pointer to the group representing the curve.
+ *
+ * \param R         Pointer to a point structure to hold the result.
+ *
+ * \param P         Pointer to the point that has to be doubled, given with
+ *                  Jacobian coordinates.
+ *
+ * \return          0 if successful.
+ */
+#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
+int mbedtls_internal_ecp_double_jac(const mbedtls_ecp_group *grp,
+                                    mbedtls_ecp_point *R, const mbedtls_ecp_point *P);
+#endif
+
+/**
+ * \brief           Normalize jacobian coordinates of an array of (pointers to)
+ *                  points.
+ *
+ *                  Using Montgomery's trick to perform only one inversion mod P
+ *                  the cost is:
+ *                      1N(t) := 1I + (6t - 3)M + 1S
+ *                  (See for example Algorithm 10.3.4. in [9])
+ *
+ *                  This function is used only as a subrutine of
+ *                  ecp_mul_comb().
+ *
+ *                  Warning: fails (returning an error) if one of the points is
+ *                  zero!
+ *                  This should never happen, see choice of w in ecp_mul_comb().
+ *
+ * \param grp       Pointer to the group representing the curve.
+ *
+ * \param T         Array of pointers to the points to normalise.
+ *
+ * \param t_len     Number of elements in the array.
+ *
+ * \return          0 if successful,
+ *                      an error if one of the points is zero.
+ */
+#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
+int mbedtls_internal_ecp_normalize_jac_many(const mbedtls_ecp_group *grp,
+                                            mbedtls_ecp_point *T[], size_t t_len);
+#endif
+
+/**
+ * \brief           Normalize jacobian coordinates so that Z == 0 || Z == 1.
+ *
+ *                  Cost in field operations if done by [5] 3.2.1:
+ *                      1N := 1I + 3M + 1S
+ *
+ * \param grp       Pointer to the group representing the curve.
+ *
+ * \param pt        pointer to the point to be normalised. This is an
+ *                  input/output parameter.
+ *
+ * \return          0 if successful.
+ */
+#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
+int mbedtls_internal_ecp_normalize_jac(const mbedtls_ecp_group *grp,
+                                       mbedtls_ecp_point *pt);
+#endif
+
+#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
+
+#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
+
+#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
+int mbedtls_internal_ecp_double_add_mxz(const mbedtls_ecp_group *grp,
+                                        mbedtls_ecp_point *R,
+                                        mbedtls_ecp_point *S,
+                                        const mbedtls_ecp_point *P,
+                                        const mbedtls_ecp_point *Q,
+                                        const mbedtls_mpi *d);
+#endif
+
+/**
+ * \brief           Randomize projective x/z coordinates:
+ *                      (X, Z) -> (l X, l Z) for random l
+ *
+ * \param grp       pointer to the group representing the curve
+ *
+ * \param P         the point on the curve to be randomised given with
+ *                  projective coordinates. This is an input/output parameter.
+ *
+ * \param f_rng     a function pointer to the random number generator
+ *
+ * \param p_rng     a pointer to the random number generator state
+ *
+ * \return          0 if successful
+ */
+#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
+int mbedtls_internal_ecp_randomize_mxz(const mbedtls_ecp_group *grp,
+                                       mbedtls_ecp_point *P, int (*f_rng)(void *,
+                                                                          unsigned char *,
+                                                                          size_t),
+                                       void *p_rng);
+#endif
+
+/**
+ * \brief           Normalize Montgomery x/z coordinates: X = X/Z, Z = 1.
+ *
+ * \param grp       pointer to the group representing the curve
+ *
+ * \param P         pointer to the point to be normalised. This is an
+ *                  input/output parameter.
+ *
+ * \return          0 if successful
+ */
+#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
+int mbedtls_internal_ecp_normalize_mxz(const mbedtls_ecp_group *grp,
+                                       mbedtls_ecp_point *P);
+#endif
+
+#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
+
+#endif /* MBEDTLS_ECP_INTERNAL_ALT */
+
+#endif /* ecp_internal_alt.h */
diff --git a/lib/libmbedtls/mbedtls/library/ecp_invasive.h b/lib/libmbedtls/mbedtls/library/ecp_invasive.h
index 71c7702..cb16d23 100644
--- a/lib/libmbedtls/mbedtls/library/ecp_invasive.h
+++ b/lib/libmbedtls/mbedtls/library/ecp_invasive.h
@@ -28,13 +28,12 @@
 
 #include "common.h"
 #include "mbedtls/bignum.h"
+#include "bignum_mod.h"
 #include "mbedtls/ecp.h"
 
 #if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_C)
 
-#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \
-    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \
-    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
 /* Preconditions:
  *   - bits is a multiple of 64 or is 224
  *   - c is -1 or -2
@@ -44,7 +43,7 @@
  * Behavior:
  * Set N to c * 2^bits + old_value_of_N.
  */
-void mbedtls_ecp_fix_negative( mbedtls_mpi *N, signed char c, size_t bits );
+void mbedtls_ecp_fix_negative(mbedtls_mpi *N, signed char c, size_t bits);
 #endif
 
 #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
@@ -69,13 +68,120 @@
  * \return          \c 0 on success.
  * \return          \c MBEDTLS_ERR_ECP_xxx or MBEDTLS_ERR_MPI_xxx on failure.
  */
-int mbedtls_ecp_gen_privkey_mx( size_t n_bits,
-                                mbedtls_mpi *d,
-                                int (*f_rng)(void *, unsigned char *, size_t),
-                                void *p_rng );
+int mbedtls_ecp_gen_privkey_mx(size_t n_bits,
+                               mbedtls_mpi *d,
+                               int (*f_rng)(void *, unsigned char *, size_t),
+                               void *p_rng);
 
 #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
 
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
+
+/** Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1)
+ *
+ * This operation expects a 384 bit MPI and the result of the reduction
+ * is a 192 bit MPI.
+ *
+ * \param[in,out]   Np  The address of the MPI to be converted.
+ *                      Must have twice as many limbs as the modulus.
+ *                      Upon return this holds the reduced value. The bitlength
+ *                      of the reduced value is the same as that of the modulus
+ *                      (192 bits).
+ * \param[in]       Nn  The length of \p Np in limbs.
+ */
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn);
+
+#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+
+/** Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
+ *
+ * \param[in,out]   X       The address of the MPI to be converted.
+ *                          Must have exact limb size that stores a 448-bit MPI
+ *                          (double the bitlength of the modulus).
+ *                          Upon return holds the reduced value which is
+ *                          in range `0 <= X < 2 * N` (where N is the modulus).
+ *                          The bitlength of the reduced value is the same as
+ *                          that of the modulus (224 bits).
+ * \param[in]       X_limbs The length of \p X in limbs.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs is not the
+ *                  limb size that sores a 448-bit MPI.
+ */
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs);
+
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+
+/** Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)
+ *
+ * \param[in,out]   X       The address of the MPI to be converted.
+ *                          Must have exact limb size that stores a 512-bit MPI
+ *                          (double the bitlength of the modulus).
+ *                          Upon return holds the reduced value which is
+ *                          in range `0 <= X < 2 * N` (where N is the modulus).
+ *                          The bitlength of the reduced value is the same as
+ *                          that of the modulus (256 bits).
+ * \param[in]       X_limbs The length of \p X in limbs.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs is not the
+ *                  limb size that sores a 512-bit MPI.
+ */
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs);
+
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+
+/** Fast quasi-reduction modulo p521 = 2^521 - 1 (FIPS 186-3 D.2.5)
+ *
+ * \param[in,out]   X       The address of the MPI to be converted.
+ *                          Must have twice as many limbs as the modulus
+ *                          (the modulus is 521 bits long). Upon return this
+ *                          holds the reduced value. The reduced value is
+ *                          in range `0 <= X < 2 * N` (where N is the modulus).
+ *                          and its the bitlength is one plus the bitlength
+ *                          of the modulus.
+ * \param[in]       X_limbs The length of \p X in limbs.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs does not have
+ *                  twice as many limbs as the modulus.
+ */
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs);
+
+#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
+
+/** Initialise a modulus with hard-coded const curve data.
+ *
+ * \note            The caller is responsible for the \p N modulus' memory.
+ *                  mbedtls_mpi_mod_modulus_free(&N) should be invoked at the
+ *                  end of its lifecycle.
+ *
+ * \param[in,out] N The address of the modulus structure to populate.
+ *                  Must be initialized.
+ * \param[in] id    The mbedtls_ecp_group_id for which to initialise the modulus.
+ * \param[in] ctype The mbedtls_ecp_curve_type identifier for a coordinate modulus (P)
+ *                  or a scalar modulus (N).
+ *
+ * \return          \c 0 if successful.
+ * \return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the given MPIs do not
+ *                  have the correct number of limbs.
+ *
+ */
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N,
+                              const mbedtls_ecp_group_id id,
+                              const mbedtls_ecp_curve_type ctype);
+
 #endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_ECP_C */
 
 #endif /* MBEDTLS_ECP_INVASIVE_H */
diff --git a/lib/libmbedtls/mbedtls/library/entropy.c b/lib/libmbedtls/mbedtls/library/entropy.c
index 12fd3b9..e55410c 100644
--- a/lib/libmbedtls/mbedtls/library/entropy.c
+++ b/lib/libmbedtls/mbedtls/library/entropy.c
@@ -21,14 +21,8 @@
 
 #if defined(MBEDTLS_ENTROPY_C)
 
-#if defined(MBEDTLS_TEST_NULL_ENTROPY)
-#warning "**** WARNING!  MBEDTLS_TEST_NULL_ENTROPY defined! "
-#warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES "
-#warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE "
-#endif
-
 #include "mbedtls/entropy.h"
-#include "mbedtls/entropy_poll.h"
+#include "entropy_poll.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 
@@ -38,122 +32,90 @@
 #include <stdio.h>
 #endif
 
-#if defined(MBEDTLS_ENTROPY_NV_SEED)
 #include "mbedtls/platform.h"
-#endif
 
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf     printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
 
-#if defined(MBEDTLS_HAVEGE_C)
-#include "mbedtls/havege.h"
-#endif
 
 #define ENTROPY_MAX_LOOP    256     /**< Maximum amount to loop before error */
 
-void mbedtls_entropy_init( mbedtls_entropy_context *ctx )
+void mbedtls_entropy_init(mbedtls_entropy_context *ctx)
 {
     ctx->source_count = 0;
-    memset( ctx->source, 0, sizeof( ctx->source ) );
+    memset(ctx->source, 0, sizeof(ctx->source));
 
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_init( &ctx->mutex );
+    mbedtls_mutex_init(&ctx->mutex);
 #endif
 
     ctx->accumulator_started = 0;
 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
-    mbedtls_sha512_init( &ctx->accumulator );
+    mbedtls_sha512_init(&ctx->accumulator);
 #else
-    mbedtls_sha256_init( &ctx->accumulator );
-#endif
-#if defined(MBEDTLS_HAVEGE_C)
-    mbedtls_havege_init( &ctx->havege_data );
+    mbedtls_sha256_init(&ctx->accumulator);
 #endif
 
     /* Reminder: Update ENTROPY_HAVE_STRONG in the test files
      *           when adding more strong entropy sources here. */
 
-#if defined(MBEDTLS_TEST_NULL_ENTROPY)
-    mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL,
-                                1, MBEDTLS_ENTROPY_SOURCE_STRONG );
-#endif
-
 #if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
 #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
-    mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL,
-                                MBEDTLS_ENTROPY_MIN_PLATFORM,
-                                MBEDTLS_ENTROPY_SOURCE_STRONG );
-#endif
-#if defined(MBEDTLS_TIMING_C)
-    mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL,
-                                MBEDTLS_ENTROPY_MIN_HARDCLOCK,
-                                MBEDTLS_ENTROPY_SOURCE_WEAK );
-#endif
-#if defined(MBEDTLS_HAVEGE_C)
-    mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data,
-                                MBEDTLS_ENTROPY_MIN_HAVEGE,
-                                MBEDTLS_ENTROPY_SOURCE_STRONG );
+    mbedtls_entropy_add_source(ctx, mbedtls_platform_entropy_poll, NULL,
+                               MBEDTLS_ENTROPY_MIN_PLATFORM,
+                               MBEDTLS_ENTROPY_SOURCE_STRONG);
 #endif
 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
-    mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL,
-                                MBEDTLS_ENTROPY_MIN_HARDWARE,
-                                MBEDTLS_ENTROPY_SOURCE_STRONG );
+    mbedtls_entropy_add_source(ctx, mbedtls_hardware_poll, NULL,
+                               MBEDTLS_ENTROPY_MIN_HARDWARE,
+                               MBEDTLS_ENTROPY_SOURCE_STRONG);
 #endif
 #if defined(MBEDTLS_ENTROPY_NV_SEED)
-    mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL,
-                                MBEDTLS_ENTROPY_BLOCK_SIZE,
-                                MBEDTLS_ENTROPY_SOURCE_STRONG );
+    mbedtls_entropy_add_source(ctx, mbedtls_nv_seed_poll, NULL,
+                               MBEDTLS_ENTROPY_BLOCK_SIZE,
+                               MBEDTLS_ENTROPY_SOURCE_STRONG);
     ctx->initial_entropy_run = 0;
 #endif
 #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */
 }
 
-void mbedtls_entropy_free( mbedtls_entropy_context *ctx )
+void mbedtls_entropy_free(mbedtls_entropy_context *ctx)
 {
     /* If the context was already free, don't call free() again.
      * This is important for mutexes which don't allow double-free. */
-    if( ctx->accumulator_started == -1 )
+    if (ctx->accumulator_started == -1) {
         return;
+    }
 
-#if defined(MBEDTLS_HAVEGE_C)
-    mbedtls_havege_free( &ctx->havege_data );
-#endif
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_free( &ctx->mutex );
+    mbedtls_mutex_free(&ctx->mutex);
 #endif
 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
-    mbedtls_sha512_free( &ctx->accumulator );
+    mbedtls_sha512_free(&ctx->accumulator);
 #else
-    mbedtls_sha256_free( &ctx->accumulator );
+    mbedtls_sha256_free(&ctx->accumulator);
 #endif
 #if defined(MBEDTLS_ENTROPY_NV_SEED)
     ctx->initial_entropy_run = 0;
 #endif
     ctx->source_count = 0;
-    mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) );
+    mbedtls_platform_zeroize(ctx->source, sizeof(ctx->source));
     ctx->accumulator_started = -1;
 }
 
-int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx,
-                        mbedtls_entropy_f_source_ptr f_source, void *p_source,
-                        size_t threshold, int strong )
+int mbedtls_entropy_add_source(mbedtls_entropy_context *ctx,
+                               mbedtls_entropy_f_source_ptr f_source, void *p_source,
+                               size_t threshold, int strong)
 {
     int idx, ret = 0;
 
 #if defined(MBEDTLS_THREADING_C)
-    if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
+        return ret;
+    }
 #endif
 
     idx = ctx->source_count;
-    if( idx >= MBEDTLS_ENTROPY_MAX_SOURCES )
-    {
+    if (idx >= MBEDTLS_ENTROPY_MAX_SOURCES) {
         ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES;
         goto exit;
     }
@@ -167,18 +129,19 @@
 
 exit:
 #if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
-        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
+        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
+    }
 #endif
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Entropy accumulator update
  */
-static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id,
-                           const unsigned char *data, size_t len )
+static int entropy_update(mbedtls_entropy_context *ctx, unsigned char source_id,
+                          const unsigned char *data, size_t len)
 {
     unsigned char header[2];
     unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE];
@@ -186,14 +149,15 @@
     const unsigned char *p = data;
     int ret = 0;
 
-    if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE )
-    {
+    if (use_len > MBEDTLS_ENTROPY_BLOCK_SIZE) {
 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
-        if( ( ret = mbedtls_sha512_ret( data, len, tmp, 0 ) ) != 0 )
+        if ((ret = mbedtls_sha512(data, len, tmp, 0)) != 0) {
             goto cleanup;
+        }
 #else
-        if( ( ret = mbedtls_sha256_ret( data, len, tmp, 0 ) ) != 0 )
+        if ((ret = mbedtls_sha256(data, len, tmp, 0)) != 0) {
             goto cleanup;
+        }
 #endif
         p = tmp;
         use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
@@ -208,55 +172,61 @@
      * gather entropy eventually execute this code.
      */
 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
-    if( ctx->accumulator_started == 0 &&
-        ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
+    if (ctx->accumulator_started == 0 &&
+        (ret = mbedtls_sha512_starts(&ctx->accumulator, 0)) != 0) {
         goto cleanup;
-    else
+    } else {
         ctx->accumulator_started = 1;
-    if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, header, 2 ) ) != 0 )
+    }
+    if ((ret = mbedtls_sha512_update(&ctx->accumulator, header, 2)) != 0) {
         goto cleanup;
-    ret = mbedtls_sha512_update_ret( &ctx->accumulator, p, use_len );
+    }
+    ret = mbedtls_sha512_update(&ctx->accumulator, p, use_len);
 #else
-    if( ctx->accumulator_started == 0 &&
-        ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
+    if (ctx->accumulator_started == 0 &&
+        (ret = mbedtls_sha256_starts(&ctx->accumulator, 0)) != 0) {
         goto cleanup;
-    else
+    } else {
         ctx->accumulator_started = 1;
-    if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, header, 2 ) ) != 0 )
+    }
+    if ((ret = mbedtls_sha256_update(&ctx->accumulator, header, 2)) != 0) {
         goto cleanup;
-    ret = mbedtls_sha256_update_ret( &ctx->accumulator, p, use_len );
+    }
+    ret = mbedtls_sha256_update(&ctx->accumulator, p, use_len);
 #endif
 
 cleanup:
-    mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
+    mbedtls_platform_zeroize(tmp, sizeof(tmp));
 
-    return( ret );
+    return ret;
 }
 
-int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx,
-                           const unsigned char *data, size_t len )
+int mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx,
+                                  const unsigned char *data, size_t len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
 #if defined(MBEDTLS_THREADING_C)
-    if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
+        return ret;
+    }
 #endif
 
-    ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len );
+    ret = entropy_update(ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len);
 
 #if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
-        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
+        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
+    }
 #endif
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Run through the different sources to add entropy to our accumulator
  */
-static int entropy_gather_internal( mbedtls_entropy_context *ctx )
+static int entropy_gather_internal(mbedtls_entropy_context *ctx)
 {
     int ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
     int i;
@@ -264,121 +234,125 @@
     unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER];
     size_t olen;
 
-    if( ctx->source_count == 0 )
-        return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED );
+    if (ctx->source_count == 0) {
+        return MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED;
+    }
 
     /*
      * Run through our entropy sources
      */
-    for( i = 0; i < ctx->source_count; i++ )
-    {
-        if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG )
+    for (i = 0; i < ctx->source_count; i++) {
+        if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG) {
             have_one_strong = 1;
+        }
 
         olen = 0;
-        if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
-                        buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 )
-        {
+        if ((ret = ctx->source[i].f_source(ctx->source[i].p_source,
+                                           buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen)) != 0) {
             goto cleanup;
         }
 
         /*
          * Add if we actually gathered something
          */
-        if( olen > 0 )
-        {
-            if( ( ret = entropy_update( ctx, (unsigned char) i,
-                                        buf, olen ) ) != 0 )
-                return( ret );
+        if (olen > 0) {
+            if ((ret = entropy_update(ctx, (unsigned char) i,
+                                      buf, olen)) != 0) {
+                return ret;
+            }
             ctx->source[i].size += olen;
         }
     }
 
-    if( have_one_strong == 0 )
+    if (have_one_strong == 0) {
         ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE;
+    }
 
 cleanup:
-    mbedtls_platform_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize(buf, sizeof(buf));
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Thread-safe wrapper for entropy_gather_internal()
  */
-int mbedtls_entropy_gather( mbedtls_entropy_context *ctx )
+int mbedtls_entropy_gather(mbedtls_entropy_context *ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
 #if defined(MBEDTLS_THREADING_C)
-    if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
+        return ret;
+    }
 #endif
 
-    ret = entropy_gather_internal( ctx );
+    ret = entropy_gather_internal(ctx);
 
 #if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
-        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
+        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
+    }
 #endif
 
-    return( ret );
+    return ret;
 }
 
-int mbedtls_entropy_func( void *data, unsigned char *output, size_t len )
+int mbedtls_entropy_func(void *data, unsigned char *output, size_t len)
 {
     int ret, count = 0, i, thresholds_reached;
     size_t strong_size;
     mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data;
     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
 
-    if( len > MBEDTLS_ENTROPY_BLOCK_SIZE )
-        return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
+    if (len > MBEDTLS_ENTROPY_BLOCK_SIZE) {
+        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+    }
 
 #if defined(MBEDTLS_ENTROPY_NV_SEED)
     /* Update the NV entropy seed before generating any entropy for outside
      * use.
      */
-    if( ctx->initial_entropy_run == 0 )
-    {
+    if (ctx->initial_entropy_run == 0) {
         ctx->initial_entropy_run = 1;
-        if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 )
-            return( ret );
+        if ((ret = mbedtls_entropy_update_nv_seed(ctx)) != 0) {
+            return ret;
+        }
     }
 #endif
 
 #if defined(MBEDTLS_THREADING_C)
-    if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
+        return ret;
+    }
 #endif
 
     /*
      * Always gather extra entropy before a call
      */
-    do
-    {
-        if( count++ > ENTROPY_MAX_LOOP )
-        {
+    do {
+        if (count++ > ENTROPY_MAX_LOOP) {
             ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
             goto exit;
         }
 
-        if( ( ret = entropy_gather_internal( ctx ) ) != 0 )
+        if ((ret = entropy_gather_internal(ctx)) != 0) {
             goto exit;
+        }
 
         thresholds_reached = 1;
         strong_size = 0;
-        for( i = 0; i < ctx->source_count; i++ )
-        {
-            if( ctx->source[i].size < ctx->source[i].threshold )
+        for (i = 0; i < ctx->source_count; i++) {
+            if (ctx->source[i].size < ctx->source[i].threshold) {
                 thresholds_reached = 0;
-            if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG )
+            }
+            if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG) {
                 strong_size += ctx->source[i].size;
+            }
         }
-    }
-    while( ! thresholds_reached || strong_size < MBEDTLS_ENTROPY_BLOCK_SIZE );
+    } while (!thresholds_reached || strong_size < MBEDTLS_ENTROPY_BLOCK_SIZE);
 
-    memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
+    memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
 
 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
     /*
@@ -386,109 +360,121 @@
      * in a previous call to entropy_update(). If this is not guaranteed, the
      * code below will fail.
      */
-    if( ( ret = mbedtls_sha512_finish_ret( &ctx->accumulator, buf ) ) != 0 )
+    if ((ret = mbedtls_sha512_finish(&ctx->accumulator, buf)) != 0) {
         goto exit;
+    }
 
     /*
      * Reset accumulator and counters and recycle existing entropy
      */
-    mbedtls_sha512_free( &ctx->accumulator );
-    mbedtls_sha512_init( &ctx->accumulator );
-    if( ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
+    mbedtls_sha512_free(&ctx->accumulator);
+    mbedtls_sha512_init(&ctx->accumulator);
+    if ((ret = mbedtls_sha512_starts(&ctx->accumulator, 0)) != 0) {
         goto exit;
-    if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, buf,
-                                           MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
+    }
+    if ((ret = mbedtls_sha512_update(&ctx->accumulator, buf,
+                                     MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
         goto exit;
+    }
 
     /*
      * Perform second SHA-512 on entropy
      */
-    if( ( ret = mbedtls_sha512_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
-                                    buf, 0 ) ) != 0 )
+    if ((ret = mbedtls_sha512(buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
+                              buf, 0)) != 0) {
         goto exit;
+    }
 #else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
-    if( ( ret = mbedtls_sha256_finish_ret( &ctx->accumulator, buf ) ) != 0 )
+    if ((ret = mbedtls_sha256_finish(&ctx->accumulator, buf)) != 0) {
         goto exit;
+    }
 
     /*
      * Reset accumulator and counters and recycle existing entropy
      */
-    mbedtls_sha256_free( &ctx->accumulator );
-    mbedtls_sha256_init( &ctx->accumulator );
-    if( ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
+    mbedtls_sha256_free(&ctx->accumulator);
+    mbedtls_sha256_init(&ctx->accumulator);
+    if ((ret = mbedtls_sha256_starts(&ctx->accumulator, 0)) != 0) {
         goto exit;
-    if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, buf,
-                                           MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
+    }
+    if ((ret = mbedtls_sha256_update(&ctx->accumulator, buf,
+                                     MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
         goto exit;
+    }
 
     /*
      * Perform second SHA-256 on entropy
      */
-    if( ( ret = mbedtls_sha256_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
-                                    buf, 0 ) ) != 0 )
+    if ((ret = mbedtls_sha256(buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
+                              buf, 0)) != 0) {
         goto exit;
+    }
 #endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
 
-    for( i = 0; i < ctx->source_count; i++ )
+    for (i = 0; i < ctx->source_count; i++) {
         ctx->source[i].size = 0;
+    }
 
-    memcpy( output, buf, len );
+    memcpy(output, buf, len);
 
     ret = 0;
 
 exit:
-    mbedtls_platform_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize(buf, sizeof(buf));
 
 #if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
-        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
+        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
+    }
 #endif
 
-    return( ret );
+    return ret;
 }
 
 #if defined(MBEDTLS_ENTROPY_NV_SEED)
-int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx )
+int mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx)
 {
     int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
 
     /* Read new seed  and write it to NV */
-    if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
+        return ret;
+    }
 
-    if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 )
-        return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
+    if (mbedtls_nv_seed_write(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0) {
+        return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
+    }
 
     /* Manually update the remaining stream with a separator value to diverge */
-    memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
-    ret = mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
+    memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
+    ret = mbedtls_entropy_update_manual(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE);
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_ENTROPY_NV_SEED */
 
 #if defined(MBEDTLS_FS_IO)
-int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path )
+int mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *path)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     FILE *f = NULL;
     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
 
-    if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
-    {
+    if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
         ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
         goto exit;
     }
 
-    if( ( f = fopen( path, "wb" ) ) == NULL )
-    {
+    if ((f = fopen(path, "wb")) == NULL) {
         ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
         goto exit;
     }
 
-    if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE )
-    {
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf(f, NULL);
+
+    if (fwrite(buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f) != MBEDTLS_ENTROPY_BLOCK_SIZE) {
         ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
         goto exit;
     }
@@ -496,110 +482,114 @@
     ret = 0;
 
 exit:
-    mbedtls_platform_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize(buf, sizeof(buf));
 
-    if( f != NULL )
-        fclose( f );
+    if (f != NULL) {
+        fclose(f);
+    }
 
-    return( ret );
+    return ret;
 }
 
-int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path )
+int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *path)
 {
     int ret = 0;
     FILE *f;
     size_t n;
-    unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ];
+    unsigned char buf[MBEDTLS_ENTROPY_MAX_SEED_SIZE];
 
-    if( ( f = fopen( path, "rb" ) ) == NULL )
-        return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
+    if ((f = fopen(path, "rb")) == NULL) {
+        return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
+    }
 
-    fseek( f, 0, SEEK_END );
-    n = (size_t) ftell( f );
-    fseek( f, 0, SEEK_SET );
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf(f, NULL);
 
-    if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE )
+    fseek(f, 0, SEEK_END);
+    n = (size_t) ftell(f);
+    fseek(f, 0, SEEK_SET);
+
+    if (n > MBEDTLS_ENTROPY_MAX_SEED_SIZE) {
         n = MBEDTLS_ENTROPY_MAX_SEED_SIZE;
+    }
 
-    if( fread( buf, 1, n, f ) != n )
+    if (fread(buf, 1, n, f) != n) {
         ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
-    else
-        ret = mbedtls_entropy_update_manual( ctx, buf, n );
+    } else {
+        ret = mbedtls_entropy_update_manual(ctx, buf, n);
+    }
 
-    fclose( f );
+    fclose(f);
 
-    mbedtls_platform_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize(buf, sizeof(buf));
 
-    if( ret != 0 )
-        return( ret );
+    if (ret != 0) {
+        return ret;
+    }
 
-    return( mbedtls_entropy_write_seed_file( ctx, path ) );
+    return mbedtls_entropy_write_seed_file(ctx, path);
 }
 #endif /* MBEDTLS_FS_IO */
 
 #if defined(MBEDTLS_SELF_TEST)
-#if !defined(MBEDTLS_TEST_NULL_ENTROPY)
 /*
  * Dummy source function
  */
-static int entropy_dummy_source( void *data, unsigned char *output,
-                                 size_t len, size_t *olen )
+static int entropy_dummy_source(void *data, unsigned char *output,
+                                size_t len, size_t *olen)
 {
     ((void) data);
 
-    memset( output, 0x2a, len );
+    memset(output, 0x2a, len);
     *olen = len;
 
-    return( 0 );
+    return 0;
 }
-#endif /* !MBEDTLS_TEST_NULL_ENTROPY */
 
 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
 
-static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len )
+static int mbedtls_entropy_source_self_test_gather(unsigned char *buf, size_t buf_len)
 {
     int ret = 0;
     size_t entropy_len = 0;
     size_t olen = 0;
     size_t attempts = buf_len;
 
-    while( attempts > 0 && entropy_len < buf_len )
-    {
-        if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len,
-            buf_len - entropy_len, &olen ) ) != 0 )
-            return( ret );
+    while (attempts > 0 && entropy_len < buf_len) {
+        if ((ret = mbedtls_hardware_poll(NULL, buf + entropy_len,
+                                         buf_len - entropy_len, &olen)) != 0) {
+            return ret;
+        }
 
         entropy_len += olen;
         attempts--;
     }
 
-    if( entropy_len < buf_len )
-    {
+    if (entropy_len < buf_len) {
         ret = 1;
     }
 
-    return( ret );
+    return ret;
 }
 
 
-static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf,
-                                                        size_t buf_len )
+static int mbedtls_entropy_source_self_test_check_bits(const unsigned char *buf,
+                                                       size_t buf_len)
 {
-    unsigned char set= 0xFF;
+    unsigned char set = 0xFF;
     unsigned char unset = 0x00;
     size_t i;
 
-    for( i = 0; i < buf_len; i++ )
-    {
+    for (i = 0; i < buf_len; i++) {
         set &= buf[i];
         unset |= buf[i];
     }
 
-    return( set == 0xFF || unset == 0x00 );
+    return set == 0xFF || unset == 0x00;
 }
 
 /*
- * 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).
@@ -609,45 +599,50 @@
  *    are not equal.
  *  - The error code returned by the entropy source is not an error.
  */
-int mbedtls_entropy_source_self_test( int verbose )
+int mbedtls_entropy_source_self_test(int verbose)
 {
     int ret = 0;
-    unsigned char buf0[2 * sizeof( unsigned long long int )];
-    unsigned char buf1[2 * sizeof( unsigned long long int )];
+    unsigned char buf0[2 * sizeof(unsigned long long int)];
+    unsigned char buf1[2 * sizeof(unsigned long long int)];
 
-    if( verbose != 0 )
-        mbedtls_printf( "  ENTROPY_BIAS test: " );
+    if (verbose != 0) {
+        mbedtls_printf("  ENTROPY_BIAS test: ");
+    }
 
-    memset( buf0, 0x00, sizeof( buf0 ) );
-    memset( buf1, 0x00, sizeof( buf1 ) );
+    memset(buf0, 0x00, sizeof(buf0));
+    memset(buf1, 0x00, sizeof(buf1));
 
-    if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 )
+    if ((ret = mbedtls_entropy_source_self_test_gather(buf0, sizeof(buf0))) != 0) {
         goto cleanup;
-    if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 )
+    }
+    if ((ret = mbedtls_entropy_source_self_test_gather(buf1, sizeof(buf1))) != 0) {
         goto cleanup;
+    }
 
     /* Make sure that the returned values are not all 0 or 1 */
-    if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 )
+    if ((ret = mbedtls_entropy_source_self_test_check_bits(buf0, sizeof(buf0))) != 0) {
         goto cleanup;
-    if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 )
+    }
+    if ((ret = mbedtls_entropy_source_self_test_check_bits(buf1, sizeof(buf1))) != 0) {
         goto cleanup;
+    }
 
     /* Make sure that the entropy source is not returning values in a
      * pattern */
-    ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0;
+    ret = memcmp(buf0, buf1, sizeof(buf0)) == 0;
 
 cleanup:
-    if( verbose != 0 )
-    {
-        if( ret != 0 )
-            mbedtls_printf( "failed\n" );
-        else
-            mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        if (ret != 0) {
+            mbedtls_printf("failed\n");
+        } else {
+            mbedtls_printf("passed\n");
+        }
 
-        mbedtls_printf( "\n" );
+        mbedtls_printf("\n");
     }
 
-    return( ret != 0 );
+    return ret != 0;
 }
 
 #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */
@@ -657,33 +652,34 @@
  * test that the functions don't cause errors and write the correct
  * amount of data to buffers.
  */
-int mbedtls_entropy_self_test( int verbose )
+int mbedtls_entropy_self_test(int verbose)
 {
     int ret = 1;
-#if !defined(MBEDTLS_TEST_NULL_ENTROPY)
     mbedtls_entropy_context ctx;
     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
     unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
     size_t i, j;
-#endif /* !MBEDTLS_TEST_NULL_ENTROPY */
 
-    if( verbose != 0 )
-        mbedtls_printf( "  ENTROPY test: " );
+    if (verbose != 0) {
+        mbedtls_printf("  ENTROPY test: ");
+    }
 
-#if !defined(MBEDTLS_TEST_NULL_ENTROPY)
-    mbedtls_entropy_init( &ctx );
+    mbedtls_entropy_init(&ctx);
 
     /* First do a gather to make sure we have default sources */
-    if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 )
+    if ((ret = mbedtls_entropy_gather(&ctx)) != 0) {
         goto cleanup;
+    }
 
-    ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16,
-                                      MBEDTLS_ENTROPY_SOURCE_WEAK );
-    if( ret != 0 )
+    ret = mbedtls_entropy_add_source(&ctx, entropy_dummy_source, NULL, 16,
+                                     MBEDTLS_ENTROPY_SOURCE_WEAK);
+    if (ret != 0) {
         goto cleanup;
+    }
 
-    if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 )
+    if ((ret = mbedtls_entropy_update_manual(&ctx, buf, sizeof(buf))) != 0) {
         goto cleanup;
+    }
 
     /*
      * To test that mbedtls_entropy_func writes correct number of bytes:
@@ -693,44 +689,43 @@
      *   each of the 32 or 64 bytes to be non-zero has a false failure rate
      *   of at most 2^(-58) which is acceptable.
      */
-    for( i = 0; i < 8; i++ )
-    {
-        if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 )
+    for (i = 0; i < 8; i++) {
+        if ((ret = mbedtls_entropy_func(&ctx, buf, sizeof(buf))) != 0) {
             goto cleanup;
+        }
 
-        for( j = 0; j < sizeof( buf ); j++ )
+        for (j = 0; j < sizeof(buf); j++) {
             acc[j] |= buf[j];
+        }
     }
 
-    for( j = 0; j < sizeof( buf ); j++ )
-    {
-        if( acc[j] == 0 )
-        {
+    for (j = 0; j < sizeof(buf); j++) {
+        if (acc[j] == 0) {
             ret = 1;
             goto cleanup;
         }
     }
 
 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
-    if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 )
+    if ((ret = mbedtls_entropy_source_self_test(0)) != 0) {
         goto cleanup;
+    }
 #endif
 
 cleanup:
-    mbedtls_entropy_free( &ctx );
-#endif /* !MBEDTLS_TEST_NULL_ENTROPY */
+    mbedtls_entropy_free(&ctx);
 
-    if( verbose != 0 )
-    {
-        if( ret != 0 )
-            mbedtls_printf( "failed\n" );
-        else
-            mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        if (ret != 0) {
+            mbedtls_printf("failed\n");
+        } else {
+            mbedtls_printf("passed\n");
+        }
 
-        mbedtls_printf( "\n" );
+        mbedtls_printf("\n");
     }
 
-    return( ret != 0 );
+    return ret != 0;
 }
 #endif /* MBEDTLS_SELF_TEST */
 
diff --git a/lib/libmbedtls/mbedtls/library/entropy_poll.c b/lib/libmbedtls/mbedtls/library/entropy_poll.c
index 2c1e093..b5024c8 100644
--- a/lib/libmbedtls/mbedtls/library/entropy_poll.c
+++ b/lib/libmbedtls/mbedtls/library/entropy_poll.c
@@ -29,25 +29,21 @@
 #if defined(MBEDTLS_ENTROPY_C)
 
 #include "mbedtls/entropy.h"
-#include "mbedtls/entropy_poll.h"
+#include "entropy_poll.h"
 #include "mbedtls/error.h"
 
 #if defined(MBEDTLS_TIMING_C)
 #include "mbedtls/timing.h"
 #endif
-#if defined(MBEDTLS_HAVEGE_C)
-#include "mbedtls/havege.h"
-#endif
-#if defined(MBEDTLS_ENTROPY_NV_SEED)
 #include "mbedtls/platform.h"
-#endif
 
 #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
 
 #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
     !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
     !defined(__HAIKU__) && !defined(__midipix__)
-#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h"
+#error \
+    "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in mbedtls_config.h"
 #endif
 
 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
@@ -58,29 +54,27 @@
 #include <windows.h>
 #include <wincrypt.h>
 
-int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len,
-                           size_t *olen )
+int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len,
+                                  size_t *olen)
 {
     HCRYPTPROV provider;
     ((void) data);
     *olen = 0;
 
-    if( CryptAcquireContext( &provider, NULL, NULL,
-                              PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE )
-    {
-        return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
+    if (CryptAcquireContext(&provider, NULL, NULL,
+                            PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == FALSE) {
+        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
     }
 
-    if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE )
-    {
-        CryptReleaseContext( provider, 0 );
-        return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
+    if (CryptGenRandom(provider, (DWORD) len, output) == FALSE) {
+        CryptReleaseContext(provider, 0);
+        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
     }
 
-    CryptReleaseContext( provider, 0 );
+    CryptReleaseContext(provider, 0);
     *olen = len;
 
-    return( 0 );
+    return 0;
 }
 #else /* _WIN32 && !EFIX64 && !EFI32 */
 
@@ -96,15 +90,15 @@
 #define HAVE_GETRANDOM
 #include <errno.h>
 
-static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
+static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags)
 {
     /* MemSan cannot understand that the syscall writes to the buffer */
 #if defined(__has_feature)
 #if __has_feature(memory_sanitizer)
-    memset( buf, 0, buflen );
+    memset(buf, 0, buflen);
 #endif
 #endif
-    return( syscall( SYS_getrandom, buf, buflen, flags ) );
+    return syscall(SYS_getrandom, buf, buflen, flags);
 }
 #endif /* SYS_getrandom */
 #endif /* __linux__ || __midipix__ */
@@ -116,9 +110,9 @@
 #include <errno.h>
 #include <sys/random.h>
 #define HAVE_GETRANDOM
-static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
+static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags)
 {
-    return getrandom( buf, buflen, flags );
+    return getrandom(buf, buflen, flags);
 }
 #endif /* (__FreeBSD__ && __FreeBSD_version >= 1200000) ||
           (__DragonFly__ && __DragonFly_version >= 500700) */
@@ -138,7 +132,7 @@
 #if defined(KERN_ARND)
 #define HAVE_SYSCTL_ARND
 
-static int sysctl_arnd_wrapper( unsigned char *buf, size_t buflen )
+static int sysctl_arnd_wrapper(unsigned char *buf, size_t buflen)
 {
     int name[2];
     size_t len;
@@ -146,23 +140,23 @@
     name[0] = CTL_KERN;
     name[1] = KERN_ARND;
 
-    while( buflen > 0 )
-    {
+    while (buflen > 0) {
         len = buflen > 256 ? 256 : buflen;
-        if( sysctl(name, 2, buf, &len, NULL, 0) == -1 )
-            return( -1 );
+        if (sysctl(name, 2, buf, &len, NULL, 0) == -1) {
+            return -1;
+        }
         buflen -= len;
         buf += len;
     }
-    return( 0 );
+    return 0;
 }
 #endif /* KERN_ARND */
 #endif /* __FreeBSD__ || __NetBSD__ */
 
 #include <stdio.h>
 
-int mbedtls_platform_entropy_poll( void *data,
-                           unsigned char *output, size_t len, size_t *olen )
+int mbedtls_platform_entropy_poll(void *data,
+                                  unsigned char *output, size_t len, size_t *olen)
 {
     FILE *file;
     size_t read_len;
@@ -170,14 +164,13 @@
     ((void) data);
 
 #if defined(HAVE_GETRANDOM)
-    ret = getrandom_wrapper( output, len, 0 );
-    if( ret >= 0 )
-    {
+    ret = getrandom_wrapper(output, len, 0);
+    if (ret >= 0) {
         *olen = ret;
-        return( 0 );
+        return 0;
+    } else if (errno != ENOSYS) {
+        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
     }
-    else if( errno != ENOSYS )
-        return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
     /* Fall through if the system call isn't known. */
 #else
     ((void) ret);
@@ -186,105 +179,60 @@
 #if defined(HAVE_SYSCTL_ARND)
     ((void) file);
     ((void) read_len);
-    if( sysctl_arnd_wrapper( output, len ) == -1 )
-        return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
+    if (sysctl_arnd_wrapper(output, len) == -1) {
+        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+    }
     *olen = len;
-    return( 0 );
+    return 0;
 #else
 
     *olen = 0;
 
-    file = fopen( "/dev/urandom", "rb" );
-    if( file == NULL )
-        return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
-
-    read_len = fread( output, 1, len, file );
-    if( read_len != len )
-    {
-        fclose( file );
-        return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
+    file = fopen("/dev/urandom", "rb");
+    if (file == NULL) {
+        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
     }
 
-    fclose( file );
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf(file, NULL);
+
+    read_len = fread(output, 1, len, file);
+    if (read_len != len) {
+        fclose(file);
+        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+    }
+
+    fclose(file);
     *olen = len;
 
-    return( 0 );
+    return 0;
 #endif /* HAVE_SYSCTL_ARND */
 }
 #endif /* _WIN32 && !EFIX64 && !EFI32 */
 #endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */
 
-#if defined(MBEDTLS_TEST_NULL_ENTROPY)
-int mbedtls_null_entropy_poll( void *data,
-                    unsigned char *output, size_t len, size_t *olen )
-{
-    ((void) data);
-    ((void) output);
-
-    *olen = 0;
-    if( len < sizeof(unsigned char) )
-        return( 0 );
-
-    output[0] = 0;
-    *olen = sizeof(unsigned char);
-    return( 0 );
-}
-#endif
-
-#if defined(MBEDTLS_TIMING_C)
-int mbedtls_hardclock_poll( void *data,
-                    unsigned char *output, size_t len, size_t *olen )
-{
-    unsigned long timer = mbedtls_timing_hardclock();
-    ((void) data);
-    *olen = 0;
-
-    if( len < sizeof(unsigned long) )
-        return( 0 );
-
-    memcpy( output, &timer, sizeof(unsigned long) );
-    *olen = sizeof(unsigned long);
-
-    return( 0 );
-}
-#endif /* MBEDTLS_TIMING_C */
-
-#if defined(MBEDTLS_HAVEGE_C)
-int mbedtls_havege_poll( void *data,
-                 unsigned char *output, size_t len, size_t *olen )
-{
-    mbedtls_havege_state *hs = (mbedtls_havege_state *) data;
-    *olen = 0;
-
-    if( mbedtls_havege_random( hs, output, len ) != 0 )
-        return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
-
-    *olen = len;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_HAVEGE_C */
-
 #if defined(MBEDTLS_ENTROPY_NV_SEED)
-int mbedtls_nv_seed_poll( void *data,
-                          unsigned char *output, size_t len, size_t *olen )
+int mbedtls_nv_seed_poll(void *data,
+                         unsigned char *output, size_t len, size_t *olen)
 {
     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
     size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
     ((void) data);
 
-    memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
+    memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
 
-    if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 )
-      return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
+    if (mbedtls_nv_seed_read(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0) {
+        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+    }
 
-    if( len < use_len )
-      use_len = len;
+    if (len < use_len) {
+        use_len = len;
+    }
 
-    memcpy( output, buf, use_len );
+    memcpy(output, buf, use_len);
     *olen = use_len;
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_ENTROPY_NV_SEED */
 
diff --git a/lib/libmbedtls/mbedtls/library/entropy_poll.h b/lib/libmbedtls/mbedtls/library/entropy_poll.h
new file mode 100644
index 0000000..3cfd4a4
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/entropy_poll.h
@@ -0,0 +1,76 @@
+/**
+ * \file entropy_poll.h
+ *
+ * \brief Platform-specific and custom entropy polling functions
+ */
+/*
+ *  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_ENTROPY_POLL_H
+#define MBEDTLS_ENTROPY_POLL_H
+
+#include "mbedtls/build_info.h"
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Default thresholds for built-in sources, in bytes
+ */
+#define MBEDTLS_ENTROPY_MIN_PLATFORM     32     /**< Minimum for platform source    */
+#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE)
+#define MBEDTLS_ENTROPY_MIN_HARDWARE     32     /**< Minimum for the hardware source */
+#endif
+
+#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
+/**
+ * \brief           Platform-specific entropy poll callback
+ */
+int mbedtls_platform_entropy_poll(void *data,
+                                  unsigned char *output, size_t len, size_t *olen);
+#endif
+
+#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
+/**
+ * \brief           Entropy poll callback for a hardware source
+ *
+ * \warning         This is not provided by mbed TLS!
+ *                  See \c MBEDTLS_ENTROPY_HARDWARE_ALT in mbedtls_config.h.
+ *
+ * \note            This must accept NULL as its first argument.
+ */
+int mbedtls_hardware_poll(void *data,
+                          unsigned char *output, size_t len, size_t *olen);
+#endif
+
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
+/**
+ * \brief           Entropy poll callback for a non-volatile seed file
+ *
+ * \note            This must accept NULL as its first argument.
+ */
+int mbedtls_nv_seed_poll(void *data,
+                         unsigned char *output, size_t len, size_t *olen);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* entropy_poll.h */
diff --git a/lib/libmbedtls/mbedtls/library/error.c b/lib/libmbedtls/mbedtls/library/error.c
index afad389..85e3154 100644
--- a/lib/libmbedtls/mbedtls/library/error.c
+++ b/lib/libmbedtls/mbedtls/library/error.c
@@ -25,11 +25,7 @@
 
 #if defined(MBEDTLS_ERROR_C)
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#define mbedtls_snprintf snprintf
-#endif
 
 #include <stdio.h>
 #include <string.h>
@@ -38,10 +34,6 @@
 #include "mbedtls/aes.h"
 #endif
 
-#if defined(MBEDTLS_ARC4_C)
-#include "mbedtls/arc4.h"
-#endif
-
 #if defined(MBEDTLS_ARIA_C)
 #include "mbedtls/aria.h"
 #endif
@@ -58,10 +50,6 @@
 #include "mbedtls/bignum.h"
 #endif
 
-#if defined(MBEDTLS_BLOWFISH_C)
-#include "mbedtls/blowfish.h"
-#endif
-
 #if defined(MBEDTLS_CAMELLIA_C)
 #include "mbedtls/camellia.h"
 #endif
@@ -82,10 +70,6 @@
 #include "mbedtls/cipher.h"
 #endif
 
-#if defined(MBEDTLS_CMAC_C)
-#include "mbedtls/cmac.h"
-#endif
-
 #if defined(MBEDTLS_CTR_DRBG_C)
 #include "mbedtls/ctr_drbg.h"
 #endif
@@ -110,6 +94,10 @@
 #include "mbedtls/error.h"
 #endif
 
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#endif
+
 #if defined(MBEDTLS_GCM_C)
 #include "mbedtls/gcm.h"
 #endif
@@ -122,22 +110,14 @@
 #include "mbedtls/hmac_drbg.h"
 #endif
 
+#if defined(MBEDTLS_LMS_C)
+#include "mbedtls/lms.h"
+#endif
+
 #if defined(MBEDTLS_MD_C)
 #include "mbedtls/md.h"
 #endif
 
-#if defined(MBEDTLS_MD2_C)
-#include "mbedtls/md2.h"
-#endif
-
-#if defined(MBEDTLS_MD4_C)
-#include "mbedtls/md4.h"
-#endif
-
-#if defined(MBEDTLS_MD5_C)
-#include "mbedtls/md5.h"
-#endif
-
 #if defined(MBEDTLS_NET_C)
 #include "mbedtls/net_sockets.h"
 #endif
@@ -146,10 +126,6 @@
 #include "mbedtls/oid.h"
 #endif
 
-#if defined(MBEDTLS_PADLOCK_C)
-#include "mbedtls/padlock.h"
-#endif
-
 #if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
 #include "mbedtls/pem.h"
 #endif
@@ -166,18 +142,14 @@
 #include "mbedtls/pkcs5.h"
 #endif
 
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
+#if defined(MBEDTLS_PKCS7_C)
+#include "mbedtls/pkcs7.h"
 #endif
 
 #if defined(MBEDTLS_POLY1305_C)
 #include "mbedtls/poly1305.h"
 #endif
 
-#if defined(MBEDTLS_RIPEMD160_C)
-#include "mbedtls/ripemd160.h"
-#endif
-
 #if defined(MBEDTLS_RSA_C)
 #include "mbedtls/rsa.h"
 #endif
@@ -206,25 +178,21 @@
 #include "mbedtls/x509.h"
 #endif
 
-#if defined(MBEDTLS_XTEA_C)
-#include "mbedtls/xtea.h"
-#endif
 
-
-const char * mbedtls_high_level_strerr( int error_code )
+const char *mbedtls_high_level_strerr(int error_code)
 {
     int high_level_error_code;
 
-    if( error_code < 0 )
+    if (error_code < 0) {
         error_code = -error_code;
+    }
 
     /* Extract the high-level part from the error code. */
     high_level_error_code = error_code & 0xFF80;
 
-    switch( high_level_error_code )
-    {
-        /* Begin Auto-Generated Code. */
-#if defined(MBEDTLS_CIPHER_C)
+    switch (high_level_error_code) {
+    /* Begin Auto-Generated Code. */
+    #if defined(MBEDTLS_CIPHER_C)
         case -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE):
             return( "CIPHER - The selected feature is not available" );
         case -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA):
@@ -239,8 +207,6 @@
             return( "CIPHER - Authentication failed (for AEAD modes)" );
         case -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT):
             return( "CIPHER - The context is invalid. For example, because it was freed" );
-        case -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED):
-            return( "CIPHER - Cipher hardware accelerator failed" );
 #endif /* MBEDTLS_CIPHER_C */
 
 #if defined(MBEDTLS_DHM_C)
@@ -262,8 +228,6 @@
             return( "DHM - Allocation of memory failed" );
         case -(MBEDTLS_ERR_DHM_FILE_IO_ERROR):
             return( "DHM - Read or write of file failed" );
-        case -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED):
-            return( "DHM - DHM hardware accelerator failed" );
         case -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED):
             return( "DHM - Setting the modulus and generator failed" );
 #endif /* MBEDTLS_DHM_C */
@@ -285,8 +249,6 @@
             return( "ECP - Invalid private or public key" );
         case -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH):
             return( "ECP - The buffer contains a valid signature followed by more data" );
-        case -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED):
-            return( "ECP - The ECP hardware accelerator failed" );
         case -(MBEDTLS_ERR_ECP_IN_PROGRESS):
             return( "ECP - Operation in progress, call again with the same parameters to continue" );
 #endif /* MBEDTLS_ECP_C */
@@ -300,8 +262,6 @@
             return( "MD - Failed to allocate memory" );
         case -(MBEDTLS_ERR_MD_FILE_IO_ERROR):
             return( "MD - Opening or reading of file failed" );
-        case -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED):
-            return( "MD - MD hardware accelerator failed" );
 #endif /* MBEDTLS_MD_C */
 
 #if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
@@ -354,8 +314,8 @@
             return( "PK - Unavailable feature, e.g. RSA disabled for RSA key" );
         case -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH):
             return( "PK - The buffer contains a valid signature followed by more data" );
-        case -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED):
-            return( "PK - PK hardware accelerator failed" );
+        case -(MBEDTLS_ERR_PK_BUFFER_TOO_SMALL):
+            return( "PK - The output buffer is too small" );
 #endif /* MBEDTLS_PK_C */
 
 #if defined(MBEDTLS_PKCS12_C)
@@ -380,6 +340,33 @@
             return( "PKCS5 - Given private key password does not allow for correct decryption" );
 #endif /* MBEDTLS_PKCS5_C */
 
+#if defined(MBEDTLS_PKCS7_C)
+        case -(MBEDTLS_ERR_PKCS7_INVALID_FORMAT):
+            return( "PKCS7 - The format is invalid, e.g. different type expected" );
+        case -(MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE):
+            return( "PKCS7 - Unavailable feature, e.g. anything other than signed data" );
+        case -(MBEDTLS_ERR_PKCS7_INVALID_VERSION):
+            return( "PKCS7 - The PKCS #7 version element is invalid or cannot be parsed" );
+        case -(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO):
+            return( "PKCS7 - The PKCS #7 content info is invalid or cannot be parsed" );
+        case -(MBEDTLS_ERR_PKCS7_INVALID_ALG):
+            return( "PKCS7 - The algorithm tag or value is invalid or cannot be parsed" );
+        case -(MBEDTLS_ERR_PKCS7_INVALID_CERT):
+            return( "PKCS7 - The certificate tag or value is invalid or cannot be parsed" );
+        case -(MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE):
+            return( "PKCS7 - Error parsing the signature" );
+        case -(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO):
+            return( "PKCS7 - Error parsing the signer's info" );
+        case -(MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA):
+            return( "PKCS7 - Input invalid" );
+        case -(MBEDTLS_ERR_PKCS7_ALLOC_FAILED):
+            return( "PKCS7 - Allocation of memory failed" );
+        case -(MBEDTLS_ERR_PKCS7_VERIFY_FAIL):
+            return( "PKCS7 - Verification Failed" );
+        case -(MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID):
+            return( "PKCS7 - The PKCS #7 date issued/expired dates are invalid" );
+#endif /* MBEDTLS_PKCS7_C */
+
 #if defined(MBEDTLS_RSA_C)
         case -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA):
             return( "RSA - Bad input parameters to function" );
@@ -399,13 +386,11 @@
             return( "RSA - The output buffer for decryption is not large enough" );
         case -(MBEDTLS_ERR_RSA_RNG_FAILED):
             return( "RSA - The random generator failed to generate non-zeros" );
-        case -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION):
-            return( "RSA - The implementation does not offer the requested operation, for example, because of security violations or lack of functionality" );
-        case -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED):
-            return( "RSA - RSA hardware accelerator failed" );
 #endif /* MBEDTLS_RSA_C */
 
 #if defined(MBEDTLS_SSL_TLS_C)
+        case -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS):
+            return( "SSL - A cryptographic operation is in progress. Try again later" );
         case -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE):
             return( "SSL - The requested feature is not available" );
         case -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA):
@@ -416,18 +401,16 @@
             return( "SSL - An invalid SSL record was received" );
         case -(MBEDTLS_ERR_SSL_CONN_EOF):
             return( "SSL - The connection indicated an EOF" );
-        case -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER):
-            return( "SSL - An unknown cipher was received" );
-        case -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN):
-            return( "SSL - The server has no ciphersuites in common with the client" );
+        case -(MBEDTLS_ERR_SSL_DECODE_ERROR):
+            return( "SSL - A message could not be parsed due to a syntactic error" );
         case -(MBEDTLS_ERR_SSL_NO_RNG):
             return( "SSL - No RNG was provided to the SSL module" );
         case -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE):
             return( "SSL - No client certification received from the client, but required by the authentication mode" );
-        case -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE):
-            return( "SSL - Our own certificate(s) is/are too large to send in an SSL message" );
-        case -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED):
-            return( "SSL - The own certificate is not set, but needed by the server" );
+        case -(MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION):
+            return( "SSL - Client received an extended server hello containing an unsupported extension" );
+        case -(MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL):
+            return( "SSL - No ALPN protocols supported that the client advertises" );
         case -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED):
             return( "SSL - The own private key or pre-shared key is not set, but needed" );
         case -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED):
@@ -436,46 +419,28 @@
             return( "SSL - An unexpected message was received from our peer" );
         case -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE):
             return( "SSL - A fatal alert message was received from our peer" );
-        case -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED):
-            return( "SSL - Verification of our peer failed" );
+        case -(MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME):
+            return( "SSL - No server could be identified matching the client's SNI" );
         case -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY):
             return( "SSL - The peer notified us that the connection is going to be closed" );
-        case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO):
-            return( "SSL - Processing of the ClientHello handshake message failed" );
-        case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO):
-            return( "SSL - Processing of the ServerHello handshake message failed" );
-        case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE):
+        case -(MBEDTLS_ERR_SSL_BAD_CERTIFICATE):
             return( "SSL - Processing of the Certificate handshake message failed" );
-        case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST):
-            return( "SSL - Processing of the CertificateRequest handshake message failed" );
-        case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE):
-            return( "SSL - Processing of the ServerKeyExchange handshake message failed" );
-        case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE):
-            return( "SSL - Processing of the ServerHelloDone handshake message failed" );
-        case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE):
-            return( "SSL - Processing of the ClientKeyExchange handshake message failed" );
-        case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP):
-            return( "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" );
-        case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS):
-            return( "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" );
-        case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY):
-            return( "SSL - Processing of the CertificateVerify handshake message failed" );
-        case -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC):
-            return( "SSL - Processing of the ChangeCipherSpec handshake message failed" );
-        case -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED):
-            return( "SSL - Processing of the Finished handshake message failed" );
+        case -(MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET):
+            return( "SSL - * Received NewSessionTicket Post Handshake Message. This error code is experimental and may be changed or removed without notice" );
+        case -(MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA):
+            return( "SSL - Not possible to read early data" );
+        case -(MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA):
+            return( "SSL - Not possible to write early data" );
         case -(MBEDTLS_ERR_SSL_ALLOC_FAILED):
             return( "SSL - Memory allocation failed" );
         case -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED):
             return( "SSL - Hardware acceleration function returned with error" );
         case -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH):
             return( "SSL - Hardware acceleration function skipped / left alone data" );
-        case -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED):
-            return( "SSL - Processing of the compression / decompression failed" );
-        case -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION):
+        case -(MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION):
             return( "SSL - Handshake protocol not within min/max boundaries" );
-        case -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET):
-            return( "SSL - Processing of the NewSessionTicket handshake message failed" );
+        case -(MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE):
+            return( "SSL - The handshake negotiation failed" );
         case -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED):
             return( "SSL - Session ticket has expired" );
         case -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH):
@@ -492,8 +457,6 @@
             return( "SSL - DTLS client must retry for hello verification" );
         case -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL):
             return( "SSL - A buffer is too small to receive or write a message" );
-        case -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE):
-            return( "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" );
         case -(MBEDTLS_ERR_SSL_WANT_READ):
             return( "SSL - No data of requested type currently available on underlying transport" );
         case -(MBEDTLS_ERR_SSL_WANT_WRITE):
@@ -506,8 +469,8 @@
             return( "SSL - Record header looks valid but is not expected" );
         case -(MBEDTLS_ERR_SSL_NON_FATAL):
             return( "SSL - The alert message received indicates a non-fatal error" );
-        case -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH):
-            return( "SSL - Couldn't set the hash for verifying CertificateVerify" );
+        case -(MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER):
+            return( "SSL - A field in a message was incorrect or inconsistent with other fields" );
         case -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING):
             return( "SSL - Internal-only message signaling that further message-processing should be done" );
         case -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS):
@@ -518,8 +481,6 @@
             return( "SSL - An encrypted DTLS-frame with an unexpected CID was received" );
         case -(MBEDTLS_ERR_SSL_VERSION_MISMATCH):
             return( "SSL - An operation failed due to an unexpected version or configuration" );
-        case -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS):
-            return( "SSL - A cryptographic operation is in progress. Try again later" );
         case -(MBEDTLS_ERR_SSL_BAD_CONFIG):
             return( "SSL - Invalid value in SSL config" );
 #endif /* MBEDTLS_SSL_TLS_C */
@@ -572,49 +533,36 @@
             break;
     }
 
-    return( NULL );
+    return NULL;
 }
 
-const char * mbedtls_low_level_strerr( int error_code )
+const char *mbedtls_low_level_strerr(int error_code)
 {
     int low_level_error_code;
 
-    if( error_code < 0 )
+    if (error_code < 0) {
         error_code = -error_code;
+    }
 
     /* Extract the low-level part from the error code. */
     low_level_error_code = error_code & ~0xFF80;
 
-    switch( low_level_error_code )
-    {
-        /* Begin Auto-Generated Code. */
-#if defined(MBEDTLS_AES_C)
+    switch (low_level_error_code) {
+    /* Begin Auto-Generated Code. */
+    #if defined(MBEDTLS_AES_C)
         case -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH):
             return( "AES - Invalid key length" );
         case -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH):
             return( "AES - Invalid data input length" );
         case -(MBEDTLS_ERR_AES_BAD_INPUT_DATA):
             return( "AES - Invalid input data" );
-        case -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE):
-            return( "AES - Feature not available. For example, an unsupported AES key size" );
-        case -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED):
-            return( "AES - AES hardware accelerator failed" );
 #endif /* MBEDTLS_AES_C */
 
-#if defined(MBEDTLS_ARC4_C)
-        case -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED):
-            return( "ARC4 - ARC4 hardware accelerator failed" );
-#endif /* MBEDTLS_ARC4_C */
-
 #if defined(MBEDTLS_ARIA_C)
         case -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA):
             return( "ARIA - Bad input data" );
         case -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH):
             return( "ARIA - Invalid data input length" );
-        case -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE):
-            return( "ARIA - Feature not available. For example, an unsupported ARIA key size" );
-        case -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED):
-            return( "ARIA - ARIA hardware accelerator failed" );
 #endif /* MBEDTLS_ARIA_C */
 
 #if defined(MBEDTLS_ASN1_PARSE_C)
@@ -660,22 +608,11 @@
             return( "BIGNUM - Memory allocation failed" );
 #endif /* MBEDTLS_BIGNUM_C */
 
-#if defined(MBEDTLS_BLOWFISH_C)
-        case -(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA):
-            return( "BLOWFISH - Bad input data" );
-        case -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH):
-            return( "BLOWFISH - Invalid data input length" );
-        case -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED):
-            return( "BLOWFISH - Blowfish hardware accelerator failed" );
-#endif /* MBEDTLS_BLOWFISH_C */
-
 #if defined(MBEDTLS_CAMELLIA_C)
         case -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA):
             return( "CAMELLIA - Bad input data" );
         case -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH):
             return( "CAMELLIA - Invalid data input length" );
-        case -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED):
-            return( "CAMELLIA - Camellia hardware accelerator failed" );
 #endif /* MBEDTLS_CAMELLIA_C */
 
 #if defined(MBEDTLS_CCM_C)
@@ -683,17 +620,11 @@
             return( "CCM - Bad input parameters to the function" );
         case -(MBEDTLS_ERR_CCM_AUTH_FAILED):
             return( "CCM - Authenticated decryption failed" );
-        case -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED):
-            return( "CCM - CCM hardware accelerator failed" );
 #endif /* MBEDTLS_CCM_C */
 
 #if defined(MBEDTLS_CHACHA20_C)
         case -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA):
             return( "CHACHA20 - Invalid input parameter(s)" );
-        case -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE):
-            return( "CHACHA20 - Feature not available. For example, s part of the API is not implemented" );
-        case -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED):
-            return( "CHACHA20 - Chacha20 hardware accelerator failed" );
 #endif /* MBEDTLS_CHACHA20_C */
 
 #if defined(MBEDTLS_CHACHAPOLY_C)
@@ -703,11 +634,6 @@
             return( "CHACHAPOLY - Authenticated decryption failed: data was not authentic" );
 #endif /* MBEDTLS_CHACHAPOLY_C */
 
-#if defined(MBEDTLS_CMAC_C)
-        case -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED):
-            return( "CMAC - CMAC hardware accelerator failed" );
-#endif /* MBEDTLS_CMAC_C */
-
 #if defined(MBEDTLS_CTR_DRBG_C)
         case -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED):
             return( "CTR_DRBG - The entropy source failed" );
@@ -722,8 +648,6 @@
 #if defined(MBEDTLS_DES_C)
         case -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH):
             return( "DES - The data input has an invalid length" );
-        case -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED):
-            return( "DES - DES hardware accelerator failed" );
 #endif /* MBEDTLS_DES_C */
 
 #if defined(MBEDTLS_ENTROPY_C)
@@ -746,13 +670,20 @@
             return( "ERROR - This is a bug in the library" );
 #endif /* MBEDTLS_ERROR_C */
 
+#if defined(MBEDTLS_PLATFORM_C)
+        case -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED):
+            return( "PLATFORM - Hardware accelerator failed" );
+        case -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED):
+            return( "PLATFORM - The requested feature is not supported by the platform" );
+#endif /* MBEDTLS_PLATFORM_C */
+
 #if defined(MBEDTLS_GCM_C)
         case -(MBEDTLS_ERR_GCM_AUTH_FAILED):
             return( "GCM - Authenticated decryption failed" );
-        case -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED):
-            return( "GCM - GCM hardware accelerator failed" );
         case -(MBEDTLS_ERR_GCM_BAD_INPUT):
             return( "GCM - Bad input parameters to function" );
+        case -(MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL):
+            return( "GCM - An output buffer is too small" );
 #endif /* MBEDTLS_GCM_C */
 
 #if defined(MBEDTLS_HKDF_C)
@@ -771,20 +702,18 @@
             return( "HMAC_DRBG - The entropy source failed" );
 #endif /* MBEDTLS_HMAC_DRBG_C */
 
-#if defined(MBEDTLS_MD2_C)
-        case -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED):
-            return( "MD2 - MD2 hardware accelerator failed" );
-#endif /* MBEDTLS_MD2_C */
-
-#if defined(MBEDTLS_MD4_C)
-        case -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED):
-            return( "MD4 - MD4 hardware accelerator failed" );
-#endif /* MBEDTLS_MD4_C */
-
-#if defined(MBEDTLS_MD5_C)
-        case -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED):
-            return( "MD5 - MD5 hardware accelerator failed" );
-#endif /* MBEDTLS_MD5_C */
+#if defined(MBEDTLS_LMS_C)
+        case -(MBEDTLS_ERR_LMS_BAD_INPUT_DATA):
+            return( "LMS - Bad data has been input to an LMS function" );
+        case -(MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS):
+            return( "LMS - Specified LMS key has utilised all of its private keys" );
+        case -(MBEDTLS_ERR_LMS_VERIFY_FAILED):
+            return( "LMS - LMS signature verification failed" );
+        case -(MBEDTLS_ERR_LMS_ALLOC_FAILED):
+            return( "LMS - LMS failed to allocate space for a private key" );
+        case -(MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL):
+            return( "LMS - Input/output buffer is too small to contain requited data" );
+#endif /* MBEDTLS_LMS_C */
 
 #if defined(MBEDTLS_NET_C)
         case -(MBEDTLS_ERR_NET_SOCKET_FAILED):
@@ -822,159 +751,129 @@
             return( "OID - output buffer is too small" );
 #endif /* MBEDTLS_OID_C */
 
-#if defined(MBEDTLS_PADLOCK_C)
-        case -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED):
-            return( "PADLOCK - Input data should be aligned" );
-#endif /* MBEDTLS_PADLOCK_C */
-
-#if defined(MBEDTLS_PLATFORM_C)
-        case -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED):
-            return( "PLATFORM - Hardware accelerator failed" );
-        case -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED):
-            return( "PLATFORM - The requested feature is not supported by the platform" );
-#endif /* MBEDTLS_PLATFORM_C */
-
 #if defined(MBEDTLS_POLY1305_C)
         case -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA):
             return( "POLY1305 - Invalid input parameter(s)" );
-        case -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE):
-            return( "POLY1305 - Feature not available. For example, s part of the API is not implemented" );
-        case -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED):
-            return( "POLY1305 - Poly1305 hardware accelerator failed" );
 #endif /* MBEDTLS_POLY1305_C */
 
-#if defined(MBEDTLS_RIPEMD160_C)
-        case -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED):
-            return( "RIPEMD160 - RIPEMD160 hardware accelerator failed" );
-#endif /* MBEDTLS_RIPEMD160_C */
-
 #if defined(MBEDTLS_SHA1_C)
-        case -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED):
-            return( "SHA1 - SHA-1 hardware accelerator failed" );
         case -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA):
             return( "SHA1 - SHA-1 input data was malformed" );
 #endif /* MBEDTLS_SHA1_C */
 
 #if defined(MBEDTLS_SHA256_C)
-        case -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED):
-            return( "SHA256 - SHA-256 hardware accelerator failed" );
         case -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA):
             return( "SHA256 - SHA-256 input data was malformed" );
 #endif /* MBEDTLS_SHA256_C */
 
 #if defined(MBEDTLS_SHA512_C)
-        case -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED):
-            return( "SHA512 - SHA-512 hardware accelerator failed" );
         case -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA):
             return( "SHA512 - SHA-512 input data was malformed" );
 #endif /* MBEDTLS_SHA512_C */
 
 #if defined(MBEDTLS_THREADING_C)
-        case -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE):
-            return( "THREADING - The selected feature is not available" );
         case -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA):
             return( "THREADING - Bad input parameters to function" );
         case -(MBEDTLS_ERR_THREADING_MUTEX_ERROR):
             return( "THREADING - Locking / unlocking / free failed with error code" );
 #endif /* MBEDTLS_THREADING_C */
-
-#if defined(MBEDTLS_XTEA_C)
-        case -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH):
-            return( "XTEA - The data input has an invalid length" );
-        case -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED):
-            return( "XTEA - XTEA hardware accelerator failed" );
-#endif /* MBEDTLS_XTEA_C */
         /* End Auto-Generated Code. */
 
         default:
             break;
     }
 
-    return( NULL );
+    return NULL;
 }
 
-void mbedtls_strerror( int ret, char *buf, size_t buflen )
+void mbedtls_strerror(int ret, char *buf, size_t buflen)
 {
     size_t len;
     int use_ret;
-    const char * high_level_error_description = NULL;
-    const char * low_level_error_description = NULL;
+    const char *high_level_error_description = NULL;
+    const char *low_level_error_description = NULL;
 
-    if( buflen == 0 )
+    if (buflen == 0) {
         return;
+    }
 
-    memset( buf, 0x00, buflen );
+    memset(buf, 0x00, buflen);
 
-    if( ret < 0 )
+    if (ret < 0) {
         ret = -ret;
+    }
 
-    if( ret & 0xFF80 )
-    {
+    if (ret & 0xFF80) {
         use_ret = ret & 0xFF80;
 
         // Translate high level error code.
-        high_level_error_description = mbedtls_high_level_strerr( ret );
+        high_level_error_description = mbedtls_high_level_strerr(ret);
 
-        if( high_level_error_description == NULL )
-            mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", (unsigned int) use_ret );
-        else
-            mbedtls_snprintf( buf, buflen, "%s", high_level_error_description );
+        if (high_level_error_description == NULL) {
+            mbedtls_snprintf(buf, buflen, "UNKNOWN ERROR CODE (%04X)", (unsigned int) use_ret);
+        } else {
+            mbedtls_snprintf(buf, buflen, "%s", high_level_error_description);
+        }
 
 #if defined(MBEDTLS_SSL_TLS_C)
         // Early return in case of a fatal error - do not try to translate low
         // level code.
-        if(use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE))
+        if (use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) {
             return;
+        }
 #endif /* MBEDTLS_SSL_TLS_C */
     }
 
     use_ret = ret & ~0xFF80;
 
-    if( use_ret == 0 )
+    if (use_ret == 0) {
         return;
+    }
 
     // If high level code is present, make a concatenation between both
     // error strings.
     //
-    len = strlen( buf );
+    len = strlen(buf);
 
-    if( len > 0 )
-    {
-        if( buflen - len < 5 )
+    if (len > 0) {
+        if (buflen - len < 5) {
             return;
+        }
 
-        mbedtls_snprintf( buf + len, buflen - len, " : " );
+        mbedtls_snprintf(buf + len, buflen - len, " : ");
 
         buf += len + 3;
         buflen -= len + 3;
     }
 
     // Translate low level error code.
-    low_level_error_description = mbedtls_low_level_strerr( ret );
+    low_level_error_description = mbedtls_low_level_strerr(ret);
 
-    if( low_level_error_description == NULL )
-        mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", (unsigned int) use_ret );
-    else
-        mbedtls_snprintf( buf, buflen, "%s", low_level_error_description );
+    if (low_level_error_description == NULL) {
+        mbedtls_snprintf(buf, buflen, "UNKNOWN ERROR CODE (%04X)", (unsigned int) use_ret);
+    } else {
+        mbedtls_snprintf(buf, buflen, "%s", low_level_error_description);
+    }
 }
 
 #else /* MBEDTLS_ERROR_C */
 
 /*
- * Provide an non-function in case MBEDTLS_ERROR_C is not defined
+ * Provide a dummy implementation when MBEDTLS_ERROR_C is not defined
  */
-void mbedtls_strerror( int ret, char *buf, size_t buflen )
+void mbedtls_strerror(int ret, char *buf, size_t buflen)
 {
     ((void) ret);
 
-    if( buflen > 0 )
+    if (buflen > 0) {
         buf[0] = '\0';
+    }
 }
 
 #endif /* MBEDTLS_ERROR_C */
 
 #if defined(MBEDTLS_TEST_HOOKS)
-void (*mbedtls_test_hook_error_add)( int, int, const char *, int );
+void (*mbedtls_test_hook_error_add)(int, int, const char *, int);
 #endif
 
 #endif /* MBEDTLS_ERROR_C || MBEDTLS_ERROR_STRERROR_DUMMY */
diff --git a/lib/libmbedtls/mbedtls/library/gcm.c b/lib/libmbedtls/mbedtls/library/gcm.c
index 43a5e1b..71fcc35 100644
--- a/lib/libmbedtls/mbedtls/library/gcm.c
+++ b/lib/libmbedtls/mbedtls/library/gcm.c
@@ -32,39 +32,28 @@
 #if defined(MBEDTLS_GCM_C)
 
 #include "mbedtls/gcm.h"
+#include "mbedtls/platform.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 
 #include <string.h>
 
 #if defined(MBEDTLS_AESNI_C)
-#include "mbedtls/aesni.h"
+#include "aesni.h"
 #endif
 
-#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
-#include "mbedtls/aes.h"
-#include "mbedtls/platform.h"
-#if !defined(MBEDTLS_PLATFORM_C)
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
+#if defined(MBEDTLS_AESCE_C)
+#include "aesce.h"
+#endif
 
 #if !defined(MBEDTLS_GCM_ALT)
 
-/* Parameter validation macros */
-#define GCM_VALIDATE_RET( cond ) \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_GCM_BAD_INPUT )
-#define GCM_VALIDATE( cond ) \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
-
 /*
  * Initialize a context
  */
-void mbedtls_gcm_init( mbedtls_gcm_context *ctx )
+void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
 {
-    GCM_VALIDATE( ctx != NULL );
-    memset( ctx, 0, sizeof( mbedtls_gcm_context ) );
+    memset(ctx, 0, sizeof(mbedtls_gcm_context));
 }
 
 /*
@@ -75,7 +64,7 @@
  * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
  * corresponds to P^127.
  */
-static int gcm_gen_table( mbedtls_gcm_context *ctx )
+static int gcm_gen_table(mbedtls_gcm_context *ctx)
 {
     int ret, i, j;
     uint64_t hi, lo;
@@ -83,93 +72,101 @@
     unsigned char h[16];
     size_t olen = 0;
 
-    memset( h, 0, 16 );
-    if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
-        return( ret );
+    memset(h, 0, 16);
+    if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen)) != 0) {
+        return ret;
+    }
 
     /* pack h as two 64-bits ints, big-endian */
-    hi = MBEDTLS_GET_UINT32_BE( h,  0  );
-    lo = MBEDTLS_GET_UINT32_BE( h,  4  );
+    hi = MBEDTLS_GET_UINT32_BE(h,  0);
+    lo = MBEDTLS_GET_UINT32_BE(h,  4);
     vh = (uint64_t) hi << 32 | lo;
 
-    hi = MBEDTLS_GET_UINT32_BE( h,  8  );
-    lo = MBEDTLS_GET_UINT32_BE( h,  12 );
+    hi = MBEDTLS_GET_UINT32_BE(h,  8);
+    lo = MBEDTLS_GET_UINT32_BE(h,  12);
     vl = (uint64_t) hi << 32 | lo;
 
     /* 8 = 1000 corresponds to 1 in GF(2^128) */
     ctx->HL[8] = vl;
     ctx->HH[8] = vh;
 
-#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
     /* With CLMUL support, we need only h, not the rest of the table */
-    if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) )
-        return( 0 );
+    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
+        return 0;
+    }
+#endif
+
+#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
+    if (mbedtls_aesce_has_support()) {
+        return 0;
+    }
 #endif
 
     /* 0 corresponds to 0 in GF(2^128) */
     ctx->HH[0] = 0;
     ctx->HL[0] = 0;
 
-    for( i = 4; i > 0; i >>= 1 )
-    {
-        uint32_t T = ( vl & 1 ) * 0xe1000000U;
-        vl  = ( vh << 63 ) | ( vl >> 1 );
-        vh  = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
+    for (i = 4; i > 0; i >>= 1) {
+        uint32_t T = (vl & 1) * 0xe1000000U;
+        vl  = (vh << 63) | (vl >> 1);
+        vh  = (vh >> 1) ^ ((uint64_t) T << 32);
 
         ctx->HL[i] = vl;
         ctx->HH[i] = vh;
     }
 
-    for( i = 2; i <= 8; i *= 2 )
-    {
+    for (i = 2; i <= 8; i *= 2) {
         uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
         vh = *HiH;
         vl = *HiL;
-        for( j = 1; j < i; j++ )
-        {
+        for (j = 1; j < i; j++) {
             HiH[j] = vh ^ ctx->HH[j];
             HiL[j] = vl ^ ctx->HL[j];
         }
     }
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
-                        mbedtls_cipher_id_t cipher,
-                        const unsigned char *key,
-                        unsigned int keybits )
+int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
+                       mbedtls_cipher_id_t cipher,
+                       const unsigned char *key,
+                       unsigned int keybits)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const mbedtls_cipher_info_t *cipher_info;
 
-    GCM_VALIDATE_RET( ctx != NULL );
-    GCM_VALIDATE_RET( key != NULL );
-    GCM_VALIDATE_RET( keybits == 128 || keybits == 192 || keybits == 256 );
-
-    cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
-                                                   MBEDTLS_MODE_ECB );
-    if( cipher_info == NULL )
-        return( MBEDTLS_ERR_GCM_BAD_INPUT );
-
-    if( cipher_info->block_size != 16 )
-        return( MBEDTLS_ERR_GCM_BAD_INPUT );
-
-    mbedtls_cipher_free( &ctx->cipher_ctx );
-
-    if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
-        return( ret );
-
-    if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
-                               MBEDTLS_ENCRYPT ) ) != 0 )
-    {
-        return( ret );
+    if (keybits != 128 && keybits != 192 && keybits != 256) {
+        return MBEDTLS_ERR_GCM_BAD_INPUT;
     }
 
-    if( ( ret = gcm_gen_table( ctx ) ) != 0 )
-        return( ret );
+    cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
+                                                  MBEDTLS_MODE_ECB);
+    if (cipher_info == NULL) {
+        return MBEDTLS_ERR_GCM_BAD_INPUT;
+    }
 
-    return( 0 );
+    if (cipher_info->block_size != 16) {
+        return MBEDTLS_ERR_GCM_BAD_INPUT;
+    }
+
+    mbedtls_cipher_free(&ctx->cipher_ctx);
+
+    if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
+        return ret;
+    }
+
+    if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
+                                     MBEDTLS_ENCRYPT)) != 0) {
+        return ret;
+    }
+
+    if ((ret = gcm_gen_table(ctx)) != 0) {
+        return ret;
+    }
+
+    return 0;
 }
 
 /*
@@ -189,42 +186,56 @@
  * Sets output to x times H using the precomputed tables.
  * x and output are seen as elements of GF(2^128) as in [MGV].
  */
-static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16],
-                      unsigned char output[16] )
+static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
+                     unsigned char output[16])
 {
     int i = 0;
     unsigned char lo, hi, rem;
     uint64_t zh, zl;
 
-#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
-    if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) {
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
+    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
         unsigned char h[16];
 
-        MBEDTLS_PUT_UINT32_BE( ctx->HH[8] >> 32, h,  0 );
-        MBEDTLS_PUT_UINT32_BE( ctx->HH[8],       h,  4 );
-        MBEDTLS_PUT_UINT32_BE( ctx->HL[8] >> 32, h,  8 );
-        MBEDTLS_PUT_UINT32_BE( ctx->HL[8],       h, 12 );
+        /* mbedtls_aesni_gcm_mult needs big-endian input */
+        MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h,  0);
+        MBEDTLS_PUT_UINT32_BE(ctx->HH[8],       h,  4);
+        MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h,  8);
+        MBEDTLS_PUT_UINT32_BE(ctx->HL[8],       h, 12);
 
-        mbedtls_aesni_gcm_mult( output, x, h );
+        mbedtls_aesni_gcm_mult(output, x, h);
         return;
     }
-#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
+#endif /* MBEDTLS_AESNI_HAVE_CODE */
+
+#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
+    if (mbedtls_aesce_has_support()) {
+        unsigned char h[16];
+
+        /* mbedtls_aesce_gcm_mult needs big-endian input */
+        MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h,  0);
+        MBEDTLS_PUT_UINT32_BE(ctx->HH[8],       h,  4);
+        MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h,  8);
+        MBEDTLS_PUT_UINT32_BE(ctx->HL[8],       h, 12);
+
+        mbedtls_aesce_gcm_mult(output, x, h);
+        return;
+    }
+#endif
 
     lo = x[15] & 0xf;
 
     zh = ctx->HH[lo];
     zl = ctx->HL[lo];
 
-    for( i = 15; i >= 0; i-- )
-    {
+    for (i = 15; i >= 0; i--) {
         lo = x[i] & 0xf;
-        hi = ( x[i] >> 4 ) & 0xf;
+        hi = (x[i] >> 4) & 0xf;
 
-        if( i != 15 )
-        {
+        if (i != 15) {
             rem = (unsigned char) zl & 0xf;
-            zl = ( zh << 60 ) | ( zl >> 4 );
-            zh = ( zh >> 4 );
+            zl = (zh << 60) | (zl >> 4);
+            zh = (zh >> 4);
             zh ^= (uint64_t) last4[rem] << 48;
             zh ^= ctx->HH[lo];
             zl ^= ctx->HL[lo];
@@ -232,294 +243,393 @@
         }
 
         rem = (unsigned char) zl & 0xf;
-        zl = ( zh << 60 ) | ( zl >> 4 );
-        zh = ( zh >> 4 );
+        zl = (zh << 60) | (zl >> 4);
+        zh = (zh >> 4);
         zh ^= (uint64_t) last4[rem] << 48;
         zh ^= ctx->HH[hi];
         zl ^= ctx->HL[hi];
     }
 
-    MBEDTLS_PUT_UINT32_BE( zh >> 32, output, 0 );
-    MBEDTLS_PUT_UINT32_BE( zh, output, 4 );
-    MBEDTLS_PUT_UINT32_BE( zl >> 32, output, 8 );
-    MBEDTLS_PUT_UINT32_BE( zl, output, 12 );
+    MBEDTLS_PUT_UINT32_BE(zh >> 32, output, 0);
+    MBEDTLS_PUT_UINT32_BE(zh, output, 4);
+    MBEDTLS_PUT_UINT32_BE(zl >> 32, output, 8);
+    MBEDTLS_PUT_UINT32_BE(zl, output, 12);
 }
 
-int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
-                int mode,
-                const unsigned char *iv,
-                size_t iv_len,
-                const unsigned char *add,
-                size_t add_len )
+int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
+                       int mode,
+                       const unsigned char *iv, size_t iv_len)
 {
     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;
 
-    GCM_VALIDATE_RET( ctx != NULL );
-    GCM_VALIDATE_RET( iv != NULL );
-    GCM_VALIDATE_RET( add_len == 0 || add != NULL );
-
-    /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
+    /* IV is limited to 2^64 bits, so 2^61 bytes */
     /* IV is not allowed to be zero length */
-    if( iv_len == 0 ||
-      ( (uint64_t) iv_len  ) >> 61 != 0 ||
-      ( (uint64_t) add_len ) >> 61 != 0 )
-    {
-        return( MBEDTLS_ERR_GCM_BAD_INPUT );
+    if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) {
+        return MBEDTLS_ERR_GCM_BAD_INPUT;
     }
 
-    memset( ctx->y, 0x00, sizeof(ctx->y) );
-    memset( ctx->buf, 0x00, sizeof(ctx->buf) );
+    memset(ctx->y, 0x00, sizeof(ctx->y));
+    memset(ctx->buf, 0x00, sizeof(ctx->buf));
 
     ctx->mode = mode;
     ctx->len = 0;
     ctx->add_len = 0;
 
-    if( iv_len == 12 )
-    {
-        memcpy( ctx->y, iv, iv_len );
+    if (iv_len == 12) {
+        memcpy(ctx->y, iv, iv_len);
         ctx->y[15] = 1;
-    }
-    else
-    {
-        memset( work_buf, 0x00, 16 );
-        iv_bits = (uint64_t)iv_len * 8;
-        MBEDTLS_PUT_UINT64_BE( iv_bits, work_buf, 8 );
+    } else {
+        memset(work_buf, 0x00, 16);
+        iv_bits = (uint64_t) iv_len * 8;
+        MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8);
 
         p = iv;
-        while( iv_len > 0 )
-        {
-            use_len = ( iv_len < 16 ) ? iv_len : 16;
+        while (iv_len > 0) {
+            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 );
+            gcm_mult(ctx, ctx->y, ctx->y);
 
             iv_len -= use_len;
             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 );
+        gcm_mult(ctx, ctx->y, ctx->y);
     }
 
-    if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16,
-                                       ctx->base_ectr, &olen ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16,
+                                     ctx->base_ectr, &olen)) != 0) {
+        return ret;
     }
 
-    ctx->add_len = add_len;
+    return 0;
+}
+
+/**
+ * mbedtls_gcm_context::buf contains the partial state of the computation of
+ * the authentication tag.
+ * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate
+ * different stages of the computation:
+ *     * len == 0 && add_len == 0:      initial state
+ *     * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have
+ *                                      a partial block of AD that has been
+ *                                      xored in but not yet multiplied in.
+ *     * len == 0 && add_len % 16 == 0: the authentication tag is correct if
+ *                                      the data ends now.
+ *     * len % 16 != 0:                 the first `len % 16` bytes have
+ *                                      a partial block of ciphertext that has
+ *                                      been xored in but not yet multiplied in.
+ *     * len > 0 && len % 16 == 0:      the authentication tag is correct if
+ *                                      the data ends now.
+ */
+int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,
+                          const unsigned char *add, size_t add_len)
+{
+    const unsigned char *p;
+    size_t use_len, offset;
+
+    /* IV is limited to 2^64 bits, so 2^61 bytes */
+    if ((uint64_t) add_len >> 61 != 0) {
+        return MBEDTLS_ERR_GCM_BAD_INPUT;
+    }
+
+    offset = ctx->add_len % 16;
     p = add;
-    while( add_len > 0 )
-    {
-        use_len = ( add_len < 16 ) ? add_len : 16;
 
-        for( i = 0; i < use_len; i++ )
-            ctx->buf[i] ^= p[i];
+    if (offset != 0) {
+        use_len = 16 - offset;
+        if (use_len > add_len) {
+            use_len = add_len;
+        }
 
-        gcm_mult( ctx, ctx->buf, ctx->buf );
+        mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len);
 
+        if (offset + use_len == 16) {
+            gcm_mult(ctx, ctx->buf, ctx->buf);
+        }
+
+        ctx->add_len += use_len;
         add_len -= use_len;
         p += use_len;
     }
 
-    return( 0 );
+    ctx->add_len += add_len;
+
+    while (add_len >= 16) {
+        mbedtls_xor(ctx->buf, ctx->buf, p, 16);
+
+        gcm_mult(ctx, ctx->buf, ctx->buf);
+
+        add_len -= 16;
+        p += 16;
+    }
+
+    if (add_len > 0) {
+        mbedtls_xor(ctx->buf, ctx->buf, p, add_len);
+    }
+
+    return 0;
 }
 
-int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
-                size_t length,
-                const unsigned char *input,
-                unsigned char *output )
+/* Increment the counter. */
+static void gcm_incr(unsigned char y[16])
+{
+    size_t i;
+    for (i = 16; i > 12; i--) {
+        if (++y[i - 1] != 0) {
+            break;
+        }
+    }
+}
+
+/* Calculate and apply the encryption mask. Process use_len bytes of data,
+ * starting at position offset in the mask block. */
+static int gcm_mask(mbedtls_gcm_context *ctx,
+                    unsigned char ectr[16],
+                    size_t offset, size_t use_len,
+                    const unsigned char *input,
+                    unsigned char *output)
+{
+    size_t olen = 0;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr,
+                                     &olen)) != 0) {
+        mbedtls_platform_zeroize(ectr, 16);
+        return ret;
+    }
+
+    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;
+}
+
+int mbedtls_gcm_update(mbedtls_gcm_context *ctx,
+                       const unsigned char *input, size_t input_length,
+                       unsigned char *output, size_t output_size,
+                       size_t *output_length)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char ectr[16];
-    size_t i;
-    const unsigned char *p;
+    const unsigned char *p = input;
     unsigned char *out_p = output;
-    size_t use_len, olen = 0;
+    size_t offset;
+    unsigned char ectr[16] = { 0 };
 
-    GCM_VALIDATE_RET( ctx != NULL );
-    GCM_VALIDATE_RET( length == 0 || input != NULL );
-    GCM_VALIDATE_RET( length == 0 || output != NULL );
+    if (output_size < input_length) {
+        return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL;
+    }
+    *output_length = input_length;
 
-    if( output > input && (size_t) ( output - input ) < length )
-        return( MBEDTLS_ERR_GCM_BAD_INPUT );
+    /* Exit early if input_length==0 so that we don't do any pointer arithmetic
+     * on a potentially null pointer.
+     * Returning early also means that the last partial block of AD remains
+     * untouched for mbedtls_gcm_finish */
+    if (input_length == 0) {
+        return 0;
+    }
+
+    if (output > input && (size_t) (output - input) < input_length) {
+        return MBEDTLS_ERR_GCM_BAD_INPUT;
+    }
 
     /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
      * Also check for possible overflow */
-    if( ctx->len + length < ctx->len ||
-        (uint64_t) ctx->len + length > 0xFFFFFFFE0ull )
-    {
-        return( MBEDTLS_ERR_GCM_BAD_INPUT );
+    if (ctx->len + input_length < ctx->len ||
+        (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) {
+        return MBEDTLS_ERR_GCM_BAD_INPUT;
     }
 
-    ctx->len += length;
+    if (ctx->len == 0 && ctx->add_len % 16 != 0) {
+        gcm_mult(ctx, ctx->buf, ctx->buf);
+    }
 
-    p = input;
-    while( length > 0 )
-    {
-        use_len = ( length < 16 ) ? length : 16;
-
-        for( i = 16; i > 12; i-- )
-            if( ++ctx->y[i - 1] != 0 )
-                break;
-
-        if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
-                                   &olen ) ) != 0 )
-        {
-            return( ret );
+    offset = ctx->len % 16;
+    if (offset != 0) {
+        size_t use_len = 16 - offset;
+        if (use_len > input_length) {
+            use_len = input_length;
         }
 
-        for( i = 0; i < use_len; i++ )
-        {
-            if( ctx->mode == MBEDTLS_GCM_DECRYPT )
-                ctx->buf[i] ^= p[i];
-            out_p[i] = ectr[i] ^ p[i];
-            if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
-                ctx->buf[i] ^= out_p[i];
+        if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) {
+            return ret;
         }
 
-        gcm_mult( ctx, ctx->buf, ctx->buf );
+        if (offset + use_len == 16) {
+            gcm_mult(ctx, ctx->buf, ctx->buf);
+        }
 
-        length -= use_len;
+        ctx->len += use_len;
+        input_length -= use_len;
         p += use_len;
         out_p += use_len;
     }
 
-    return( 0 );
+    ctx->len += input_length;
+
+    while (input_length >= 16) {
+        gcm_incr(ctx->y);
+        if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) {
+            return ret;
+        }
+
+        gcm_mult(ctx, ctx->buf, ctx->buf);
+
+        input_length -= 16;
+        p += 16;
+        out_p += 16;
+    }
+
+    if (input_length > 0) {
+        gcm_incr(ctx->y);
+        if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) {
+            return ret;
+        }
+    }
+
+    mbedtls_platform_zeroize(ectr, sizeof(ectr));
+    return 0;
 }
 
-int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
-                unsigned char *tag,
-                size_t tag_len )
+int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
+                       unsigned char *output, size_t output_size,
+                       size_t *output_length,
+                       unsigned char *tag, size_t tag_len)
 {
     unsigned char work_buf[16];
-    size_t i;
     uint64_t orig_len;
     uint64_t orig_add_len;
 
-    GCM_VALIDATE_RET( ctx != NULL );
-    GCM_VALIDATE_RET( tag != NULL );
+    /* We never pass any output in finish(). The output parameter exists only
+     * for the sake of alternative implementations. */
+    (void) output;
+    (void) output_size;
+    *output_length = 0;
 
     orig_len = ctx->len * 8;
     orig_add_len = ctx->add_len * 8;
 
-    if( tag_len > 16 || tag_len < 4 )
-        return( MBEDTLS_ERR_GCM_BAD_INPUT );
-
-    memcpy( tag, ctx->base_ectr, tag_len );
-
-    if( orig_len || orig_add_len )
-    {
-        memset( work_buf, 0x00, 16 );
-
-        MBEDTLS_PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0  );
-        MBEDTLS_PUT_UINT32_BE( ( orig_add_len       ), work_buf, 4  );
-        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];
-
-        gcm_mult( ctx, ctx->buf, ctx->buf );
-
-        for( i = 0; i < tag_len; i++ )
-            tag[i] ^= ctx->buf[i];
+    if (ctx->len == 0 && ctx->add_len % 16 != 0) {
+        gcm_mult(ctx, ctx->buf, ctx->buf);
     }
 
-    return( 0 );
+    if (tag_len > 16 || tag_len < 4) {
+        return MBEDTLS_ERR_GCM_BAD_INPUT;
+    }
+
+    if (ctx->len % 16 != 0) {
+        gcm_mult(ctx, ctx->buf, ctx->buf);
+    }
+
+    memcpy(tag, ctx->base_ectr, tag_len);
+
+    if (orig_len || orig_add_len) {
+        memset(work_buf, 0x00, 16);
+
+        MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
+        MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4);
+        MBEDTLS_PUT_UINT32_BE((orig_len     >> 32), work_buf, 8);
+        MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12);
+
+        mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16);
+
+        gcm_mult(ctx, ctx->buf, ctx->buf);
+
+        mbedtls_xor(tag, tag, ctx->buf, tag_len);
+    }
+
+    return 0;
 }
 
-int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
-                       int mode,
-                       size_t length,
-                       const unsigned char *iv,
-                       size_t iv_len,
-                       const unsigned char *add,
-                       size_t add_len,
-                       const unsigned char *input,
-                       unsigned char *output,
-                       size_t tag_len,
-                       unsigned char *tag )
+int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx,
+                              int mode,
+                              size_t length,
+                              const unsigned char *iv,
+                              size_t iv_len,
+                              const unsigned char *add,
+                              size_t add_len,
+                              const unsigned char *input,
+                              unsigned char *output,
+                              size_t tag_len,
+                              unsigned char *tag)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t olen;
 
-    GCM_VALIDATE_RET( ctx != NULL );
-    GCM_VALIDATE_RET( iv != NULL );
-    GCM_VALIDATE_RET( add_len == 0 || add != NULL );
-    GCM_VALIDATE_RET( length == 0 || input != NULL );
-    GCM_VALIDATE_RET( length == 0 || output != NULL );
-    GCM_VALIDATE_RET( tag != NULL );
+    if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) {
+        return ret;
+    }
 
-    if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) {
+        return ret;
+    }
 
-    if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_gcm_update(ctx, input, length,
+                                  output, length, &olen)) != 0) {
+        return ret;
+    }
 
-    if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) {
+        return ret;
+    }
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
-                      size_t length,
-                      const unsigned char *iv,
-                      size_t iv_len,
-                      const unsigned char *add,
-                      size_t add_len,
-                      const unsigned char *tag,
-                      size_t tag_len,
-                      const unsigned char *input,
-                      unsigned char *output )
+int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
+                             size_t length,
+                             const unsigned char *iv,
+                             size_t iv_len,
+                             const unsigned char *add,
+                             size_t add_len,
+                             const unsigned char *tag,
+                             size_t tag_len,
+                             const unsigned char *input,
+                             unsigned char *output)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char check_tag[16];
     size_t i;
     int diff;
 
-    GCM_VALIDATE_RET( ctx != NULL );
-    GCM_VALIDATE_RET( iv != NULL );
-    GCM_VALIDATE_RET( add_len == 0 || add != NULL );
-    GCM_VALIDATE_RET( tag != NULL );
-    GCM_VALIDATE_RET( length == 0 || input != NULL );
-    GCM_VALIDATE_RET( length == 0 || output != NULL );
-
-    if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
-                                   iv, iv_len, add, add_len,
-                                   input, output, tag_len, check_tag ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
+                                         iv, iv_len, add, add_len,
+                                         input, output, tag_len, check_tag)) != 0) {
+        return ret;
     }
 
     /* Check tag in "constant-time" */
-    for( diff = 0, i = 0; i < tag_len; i++ )
+    for (diff = 0, i = 0; i < tag_len; i++) {
         diff |= tag[i] ^ check_tag[i];
-
-    if( diff != 0 )
-    {
-        mbedtls_platform_zeroize( output, length );
-        return( MBEDTLS_ERR_GCM_AUTH_FAILED );
     }
 
-    return( 0 );
+    if (diff != 0) {
+        mbedtls_platform_zeroize(output, length);
+        return MBEDTLS_ERR_GCM_AUTH_FAILED;
+    }
+
+    return 0;
 }
 
-void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
+void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
-    mbedtls_cipher_free( &ctx->cipher_ctx );
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
+    }
+    mbedtls_cipher_free(&ctx->cipher_ctx);
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
 }
 
 #endif /* !MBEDTLS_GCM_ALT */
@@ -533,7 +643,7 @@
 #define MAX_TESTS   6
 
 static const int key_index_test_data[MAX_TESTS] =
-    { 0, 0, 1, 1, 1, 1 };
+{ 0, 0, 1, 1, 1, 1 };
 
 static const unsigned char key_test_data[MAX_TESTS][32] =
 {
@@ -548,10 +658,10 @@
 };
 
 static const size_t iv_len_test_data[MAX_TESTS] =
-    { 12, 12, 12, 12, 8, 60 };
+{ 12, 12, 12, 12, 8, 60 };
 
 static const int iv_index_test_data[MAX_TESTS] =
-    { 0, 0, 1, 1, 1, 2 };
+{ 0, 0, 1, 1, 1, 2 };
 
 static const unsigned char iv_test_data[MAX_TESTS][64] =
 {
@@ -570,10 +680,10 @@
 };
 
 static const size_t add_len_test_data[MAX_TESTS] =
-    { 0, 0, 0, 20, 20, 20 };
+{ 0, 0, 0, 20, 20, 20 };
 
 static const int add_index_test_data[MAX_TESTS] =
-    { 0, 0, 0, 1, 1, 1 };
+{ 0, 0, 0, 1, 1, 1 };
 
 static const unsigned char additional_test_data[MAX_TESTS][64] =
 {
@@ -584,10 +694,10 @@
 };
 
 static const size_t pt_len_test_data[MAX_TESTS] =
-    { 0, 16, 64, 60, 60, 60 };
+{ 0, 16, 64, 60, 60, 60 };
 
 static const int pt_index_test_data[MAX_TESTS] =
-    { 0, 0, 1, 1, 1, 1 };
+{ 0, 0, 1, 1, 1, 1 };
 
 static const unsigned char pt_test_data[MAX_TESTS][64] =
 {
@@ -752,250 +862,305 @@
       0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
 };
 
-int mbedtls_gcm_self_test( int verbose )
+int mbedtls_gcm_self_test(int verbose)
 {
     mbedtls_gcm_context ctx;
     unsigned char buf[64];
     unsigned char tag_buf[16];
     int i, j, ret;
     mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
+    size_t olen;
 
-    for( j = 0; j < 3; j++ )
-    {
+    if (verbose != 0) {
+#if defined(MBEDTLS_GCM_ALT)
+        mbedtls_printf("  GCM note: alternative implementation.\n");
+#else /* MBEDTLS_GCM_ALT */
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
+        if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
+            mbedtls_printf("  GCM note: using AESNI.\n");
+        } else
+#endif
+        mbedtls_printf("  GCM note: built-in implementation.\n");
+#endif /* MBEDTLS_GCM_ALT */
+    }
+
+    for (j = 0; j < 3; j++) {
         int key_len = 128 + 64 * j;
 
-        for( i = 0; i < MAX_TESTS; i++ )
-        {
-            mbedtls_gcm_init( &ctx );
+        for (i = 0; i < MAX_TESTS; i++) {
+            mbedtls_gcm_init(&ctx);
 
-            if( verbose != 0 )
-                mbedtls_printf( "  AES-GCM-%3d #%d (%s): ",
-                                key_len, i, "enc" );
+            if (verbose != 0) {
+                mbedtls_printf("  AES-GCM-%3d #%d (%s): ",
+                               key_len, i, "enc");
+            }
 
-            ret = mbedtls_gcm_setkey( &ctx, cipher,
-                                      key_test_data[key_index_test_data[i]],
-                                      key_len );
+            ret = mbedtls_gcm_setkey(&ctx, cipher,
+                                     key_test_data[key_index_test_data[i]],
+                                     key_len);
             /*
              * AES-192 is an optional feature that may be unavailable when
              * there is an alternative underlying implementation i.e. when
              * MBEDTLS_AES_ALT is defined.
              */
-            if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192 )
-            {
-                mbedtls_printf( "skipped\n" );
+            if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) {
+                mbedtls_printf("skipped\n");
                 break;
-            }
-            else if( ret != 0 )
-            {
+            } else if (ret != 0) {
                 goto exit;
             }
 
-            ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
-                                pt_len_test_data[i],
-                                iv_test_data[iv_index_test_data[i]],
-                                iv_len_test_data[i],
-                                additional_test_data[add_index_test_data[i]],
-                                add_len_test_data[i],
-                                pt_test_data[pt_index_test_data[i]],
-                                buf, 16, tag_buf );
+            ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
+                                            pt_len_test_data[i],
+                                            iv_test_data[iv_index_test_data[i]],
+                                            iv_len_test_data[i],
+                                            additional_test_data[add_index_test_data[i]],
+                                            add_len_test_data[i],
+                                            pt_test_data[pt_index_test_data[i]],
+                                            buf, 16, tag_buf);
 #if defined(MBEDTLS_GCM_ALT)
             /* Allow alternative implementations to only support 12-byte nonces. */
-            if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
-                iv_len_test_data[i] != 12 )
-            {
-                mbedtls_printf( "skipped\n" );
+            if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED &&
+                iv_len_test_data[i] != 12) {
+                mbedtls_printf("skipped\n");
                 break;
             }
 #endif /* defined(MBEDTLS_GCM_ALT) */
-            if( ret != 0 )
+            if (ret != 0) {
                 goto exit;
+            }
 
-            if ( memcmp( buf, ct_test_data[j * 6 + i],
-                         pt_len_test_data[i] ) != 0 ||
-                 memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
-            {
+            if (memcmp(buf, ct_test_data[j * 6 + i],
+                       pt_len_test_data[i]) != 0 ||
+                memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
                 ret = 1;
                 goto exit;
             }
 
-            mbedtls_gcm_free( &ctx );
+            mbedtls_gcm_free(&ctx);
 
-            if( verbose != 0 )
-                mbedtls_printf( "passed\n" );
+            if (verbose != 0) {
+                mbedtls_printf("passed\n");
+            }
 
-            mbedtls_gcm_init( &ctx );
+            mbedtls_gcm_init(&ctx);
 
-            if( verbose != 0 )
-                mbedtls_printf( "  AES-GCM-%3d #%d (%s): ",
-                                key_len, i, "dec" );
+            if (verbose != 0) {
+                mbedtls_printf("  AES-GCM-%3d #%d (%s): ",
+                               key_len, i, "dec");
+            }
 
-            ret = mbedtls_gcm_setkey( &ctx, cipher,
-                                      key_test_data[key_index_test_data[i]],
-                                      key_len );
-            if( ret != 0 )
+            ret = mbedtls_gcm_setkey(&ctx, cipher,
+                                     key_test_data[key_index_test_data[i]],
+                                     key_len);
+            if (ret != 0) {
                 goto exit;
+            }
 
-            ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
-                                pt_len_test_data[i],
-                                iv_test_data[iv_index_test_data[i]],
-                                iv_len_test_data[i],
-                                additional_test_data[add_index_test_data[i]],
-                                add_len_test_data[i],
-                                ct_test_data[j * 6 + i], buf, 16, tag_buf );
+            ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
+                                            pt_len_test_data[i],
+                                            iv_test_data[iv_index_test_data[i]],
+                                            iv_len_test_data[i],
+                                            additional_test_data[add_index_test_data[i]],
+                                            add_len_test_data[i],
+                                            ct_test_data[j * 6 + i], buf, 16, tag_buf);
 
-            if( ret != 0 )
+            if (ret != 0) {
                 goto exit;
+            }
 
-            if( memcmp( buf, pt_test_data[pt_index_test_data[i]],
-                        pt_len_test_data[i] ) != 0 ||
-                memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
-            {
+            if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
+                       pt_len_test_data[i]) != 0 ||
+                memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
                 ret = 1;
                 goto exit;
             }
 
-            mbedtls_gcm_free( &ctx );
+            mbedtls_gcm_free(&ctx);
 
-            if( verbose != 0 )
-                mbedtls_printf( "passed\n" );
+            if (verbose != 0) {
+                mbedtls_printf("passed\n");
+            }
 
-            mbedtls_gcm_init( &ctx );
+            mbedtls_gcm_init(&ctx);
 
-            if( verbose != 0 )
-                mbedtls_printf( "  AES-GCM-%3d #%d split (%s): ",
-                                key_len, i, "enc" );
+            if (verbose != 0) {
+                mbedtls_printf("  AES-GCM-%3d #%d split (%s): ",
+                               key_len, i, "enc");
+            }
 
-            ret = mbedtls_gcm_setkey( &ctx, cipher,
-                                      key_test_data[key_index_test_data[i]],
-                                      key_len );
-            if( ret != 0 )
+            ret = mbedtls_gcm_setkey(&ctx, cipher,
+                                     key_test_data[key_index_test_data[i]],
+                                     key_len);
+            if (ret != 0) {
                 goto exit;
+            }
 
-            ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
-                                  iv_test_data[iv_index_test_data[i]],
-                                  iv_len_test_data[i],
-                                  additional_test_data[add_index_test_data[i]],
-                                  add_len_test_data[i] );
-            if( ret != 0 )
+            ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT,
+                                     iv_test_data[iv_index_test_data[i]],
+                                     iv_len_test_data[i]);
+            if (ret != 0) {
                 goto exit;
+            }
 
-            if( pt_len_test_data[i] > 32 )
-            {
+            ret = mbedtls_gcm_update_ad(&ctx,
+                                        additional_test_data[add_index_test_data[i]],
+                                        add_len_test_data[i]);
+            if (ret != 0) {
+                goto exit;
+            }
+
+            if (pt_len_test_data[i] > 32) {
                 size_t rest_len = pt_len_test_data[i] - 32;
-                ret = mbedtls_gcm_update( &ctx, 32,
-                                          pt_test_data[pt_index_test_data[i]],
-                                          buf );
-                if( ret != 0 )
+                ret = mbedtls_gcm_update(&ctx,
+                                         pt_test_data[pt_index_test_data[i]],
+                                         32,
+                                         buf, sizeof(buf), &olen);
+                if (ret != 0) {
                     goto exit;
+                }
+                if (olen != 32) {
+                    goto exit;
+                }
 
-                ret = mbedtls_gcm_update( &ctx, rest_len,
-                                      pt_test_data[pt_index_test_data[i]] + 32,
-                                      buf + 32 );
-                if( ret != 0 )
+                ret = mbedtls_gcm_update(&ctx,
+                                         pt_test_data[pt_index_test_data[i]] + 32,
+                                         rest_len,
+                                         buf + 32, sizeof(buf) - 32, &olen);
+                if (ret != 0) {
                     goto exit;
-            }
-            else
-            {
-                ret = mbedtls_gcm_update( &ctx, pt_len_test_data[i],
-                                          pt_test_data[pt_index_test_data[i]],
-                                          buf );
-                if( ret != 0 )
+                }
+                if (olen != rest_len) {
                     goto exit;
+                }
+            } else {
+                ret = mbedtls_gcm_update(&ctx,
+                                         pt_test_data[pt_index_test_data[i]],
+                                         pt_len_test_data[i],
+                                         buf, sizeof(buf), &olen);
+                if (ret != 0) {
+                    goto exit;
+                }
+                if (olen != pt_len_test_data[i]) {
+                    goto exit;
+                }
             }
 
-            ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
-            if( ret != 0 )
+            ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
+            if (ret != 0) {
                 goto exit;
+            }
 
-            if( memcmp( buf, ct_test_data[j * 6 + i],
-                        pt_len_test_data[i] ) != 0 ||
-                memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
-            {
+            if (memcmp(buf, ct_test_data[j * 6 + i],
+                       pt_len_test_data[i]) != 0 ||
+                memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
                 ret = 1;
                 goto exit;
             }
 
-            mbedtls_gcm_free( &ctx );
+            mbedtls_gcm_free(&ctx);
 
-            if( verbose != 0 )
-                mbedtls_printf( "passed\n" );
+            if (verbose != 0) {
+                mbedtls_printf("passed\n");
+            }
 
-            mbedtls_gcm_init( &ctx );
+            mbedtls_gcm_init(&ctx);
 
-            if( verbose != 0 )
-                mbedtls_printf( "  AES-GCM-%3d #%d split (%s): ",
-                                key_len, i, "dec" );
+            if (verbose != 0) {
+                mbedtls_printf("  AES-GCM-%3d #%d split (%s): ",
+                               key_len, i, "dec");
+            }
 
-            ret = mbedtls_gcm_setkey( &ctx, cipher,
-                                      key_test_data[key_index_test_data[i]],
-                                      key_len );
-            if( ret != 0 )
+            ret = mbedtls_gcm_setkey(&ctx, cipher,
+                                     key_test_data[key_index_test_data[i]],
+                                     key_len);
+            if (ret != 0) {
                 goto exit;
+            }
 
-            ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
-                              iv_test_data[iv_index_test_data[i]],
-                              iv_len_test_data[i],
-                              additional_test_data[add_index_test_data[i]],
-                              add_len_test_data[i] );
-            if( ret != 0 )
+            ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT,
+                                     iv_test_data[iv_index_test_data[i]],
+                                     iv_len_test_data[i]);
+            if (ret != 0) {
                 goto exit;
+            }
+            ret = mbedtls_gcm_update_ad(&ctx,
+                                        additional_test_data[add_index_test_data[i]],
+                                        add_len_test_data[i]);
+            if (ret != 0) {
+                goto exit;
+            }
 
-            if( pt_len_test_data[i] > 32 )
-            {
+            if (pt_len_test_data[i] > 32) {
                 size_t rest_len = pt_len_test_data[i] - 32;
-                ret = mbedtls_gcm_update( &ctx, 32, ct_test_data[j * 6 + i],
-                                          buf );
-                if( ret != 0 )
+                ret = mbedtls_gcm_update(&ctx,
+                                         ct_test_data[j * 6 + i], 32,
+                                         buf, sizeof(buf), &olen);
+                if (ret != 0) {
                     goto exit;
+                }
+                if (olen != 32) {
+                    goto exit;
+                }
 
-                ret = mbedtls_gcm_update( &ctx, rest_len,
-                                          ct_test_data[j * 6 + i] + 32,
-                                          buf + 32 );
-                if( ret != 0 )
+                ret = mbedtls_gcm_update(&ctx,
+                                         ct_test_data[j * 6 + i] + 32,
+                                         rest_len,
+                                         buf + 32, sizeof(buf) - 32, &olen);
+                if (ret != 0) {
                     goto exit;
-            }
-            else
-            {
-                ret = mbedtls_gcm_update( &ctx, pt_len_test_data[i],
-                                          ct_test_data[j * 6 + i],
-                                          buf );
-                if( ret != 0 )
+                }
+                if (olen != rest_len) {
                     goto exit;
+                }
+            } else {
+                ret = mbedtls_gcm_update(&ctx,
+                                         ct_test_data[j * 6 + i],
+                                         pt_len_test_data[i],
+                                         buf, sizeof(buf), &olen);
+                if (ret != 0) {
+                    goto exit;
+                }
+                if (olen != pt_len_test_data[i]) {
+                    goto exit;
+                }
             }
 
-            ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
-            if( ret != 0 )
+            ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16);
+            if (ret != 0) {
                 goto exit;
+            }
 
-            if( memcmp( buf, pt_test_data[pt_index_test_data[i]],
-                        pt_len_test_data[i] ) != 0 ||
-                memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
-            {
+            if (memcmp(buf, pt_test_data[pt_index_test_data[i]],
+                       pt_len_test_data[i]) != 0 ||
+                memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) {
                 ret = 1;
                 goto exit;
             }
 
-            mbedtls_gcm_free( &ctx );
+            mbedtls_gcm_free(&ctx);
 
-            if( verbose != 0 )
-                mbedtls_printf( "passed\n" );
+            if (verbose != 0) {
+                mbedtls_printf("passed\n");
+            }
         }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
     ret = 0;
 
 exit:
-    if( ret != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
-        mbedtls_gcm_free( &ctx );
+    if (ret != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("failed\n");
+        }
+        mbedtls_gcm_free(&ctx);
     }
 
-    return( ret );
+    return ret;
 }
 
 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
diff --git a/lib/libmbedtls/mbedtls/library/hash_info.c b/lib/libmbedtls/mbedtls/library/hash_info.c
new file mode 100644
index 0000000..0e445b6
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/hash_info.c
@@ -0,0 +1,123 @@
+/*
+ * Hash information that's independent from the crypto implementation.
+ *
+ * (See the corresponding header file for usage notes.)
+ */
+/*
+ *  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.
+ */
+
+#include "hash_info.h"
+#include "mbedtls/legacy_or_psa.h"
+#include "mbedtls/error.h"
+
+typedef struct {
+    psa_algorithm_t psa_alg;
+    mbedtls_md_type_t md_type;
+    unsigned char size;
+    unsigned char block_size;
+} hash_entry;
+
+static const hash_entry hash_table[] = {
+#if defined(MBEDTLS_HAS_ALG_MD5_VIA_LOWLEVEL_OR_PSA)
+    { PSA_ALG_MD5, MBEDTLS_MD_MD5, 16, 64 },
+#endif
+#if defined(MBEDTLS_HAS_ALG_RIPEMD160_VIA_LOWLEVEL_OR_PSA)
+    { PSA_ALG_RIPEMD160, MBEDTLS_MD_RIPEMD160, 20, 64 },
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA)
+    { PSA_ALG_SHA_1, MBEDTLS_MD_SHA1, 20, 64 },
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA)
+    { PSA_ALG_SHA_224, MBEDTLS_MD_SHA224, 28, 64 },
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA)
+    { PSA_ALG_SHA_256, MBEDTLS_MD_SHA256, 32, 64 },
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA)
+    { PSA_ALG_SHA_384, MBEDTLS_MD_SHA384, 48, 128 },
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA)
+    { PSA_ALG_SHA_512, MBEDTLS_MD_SHA512, 64, 128 },
+#endif
+    { PSA_ALG_NONE, MBEDTLS_MD_NONE, 0, 0 },
+};
+
+/* Get size from MD type */
+unsigned char mbedtls_hash_info_get_size(mbedtls_md_type_t md_type)
+{
+    const hash_entry *entry = hash_table;
+    while (entry->md_type != MBEDTLS_MD_NONE &&
+           entry->md_type != md_type) {
+        entry++;
+    }
+
+    return entry->size;
+}
+
+/* Get block size from MD type */
+unsigned char mbedtls_hash_info_get_block_size(mbedtls_md_type_t md_type)
+{
+    const hash_entry *entry = hash_table;
+    while (entry->md_type != MBEDTLS_MD_NONE &&
+           entry->md_type != md_type) {
+        entry++;
+    }
+
+    return entry->block_size;
+}
+
+/* Get PSA from MD */
+psa_algorithm_t mbedtls_hash_info_psa_from_md(mbedtls_md_type_t md_type)
+{
+    const hash_entry *entry = hash_table;
+    while (entry->md_type != MBEDTLS_MD_NONE &&
+           entry->md_type != md_type) {
+        entry++;
+    }
+
+    return entry->psa_alg;
+}
+
+/* Get MD from PSA */
+mbedtls_md_type_t mbedtls_hash_info_md_from_psa(psa_algorithm_t psa_alg)
+{
+    const hash_entry *entry = hash_table;
+    while (entry->md_type != MBEDTLS_MD_NONE &&
+           entry->psa_alg != psa_alg) {
+        entry++;
+    }
+
+    return entry->md_type;
+}
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+int mbedtls_md_error_from_psa(psa_status_t status)
+{
+    switch (status) {
+        case PSA_SUCCESS:
+            return 0;
+        case PSA_ERROR_NOT_SUPPORTED:
+            return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
+        case PSA_ERROR_INVALID_ARGUMENT:
+            return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
+        case PSA_ERROR_INSUFFICIENT_MEMORY:
+            return MBEDTLS_ERR_MD_ALLOC_FAILED;
+        default:
+            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+    }
+}
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
diff --git a/lib/libmbedtls/mbedtls/library/hash_info.h b/lib/libmbedtls/mbedtls/library/hash_info.h
new file mode 100644
index 0000000..f984c82
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/hash_info.h
@@ -0,0 +1,101 @@
+/**
+ * Hash information that's independent from the crypto implementation.
+ *
+ *  This can be used by:
+ *  - code based on PSA
+ *  - code based on the legacy API
+ *  - code based on either of them depending on MBEDTLS_USE_PSA_CRYPTO
+ *  - code based on either of them depending on what's available
+ *
+ *  Note: this internal module will go away when everything becomes based on
+ *  PSA Crypto; it is a helper for the transition while hash algorithms are
+ *  still represented using mbedtls_md_type_t in most places even when PSA is
+ *  used for the actual crypto computations.
+ *
+ *  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_HASH_INFO_H
+#define MBEDTLS_HASH_INFO_H
+
+#include "common.h"
+
+#include "mbedtls/md.h"
+#include "psa/crypto.h"
+#include "mbedtls/platform_util.h"
+
+/** \def MBEDTLS_HASH_MAX_SIZE
+ *
+ * Maximum size of a hash based on configuration.
+ */
+#if defined(MBEDTLS_MD_C) && ( \
+    !defined(MBEDTLS_PSA_CRYPTO_C) || \
+    MBEDTLS_MD_MAX_SIZE >= PSA_HASH_MAX_SIZE)
+#define MBEDTLS_HASH_MAX_SIZE MBEDTLS_MD_MAX_SIZE
+#elif defined(MBEDTLS_PSA_CRYPTO_C) && ( \
+    !defined(MBEDTLS_MD_C) || \
+    PSA_HASH_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE)
+#define MBEDTLS_HASH_MAX_SIZE PSA_HASH_MAX_SIZE
+#endif
+
+/** Get the output length of the given hash type from its MD type.
+ *
+ * \note To get the output length from the PSA alg, use \c PSA_HASH_LENGTH().
+ *
+ * \param md_type   The hash MD type.
+ *
+ * \return          The output length in bytes, or 0 if not known.
+ */
+unsigned char mbedtls_hash_info_get_size(mbedtls_md_type_t md_type);
+
+/** Get the block size of the given hash type from its MD type.
+ *
+ * \note To get the output length from the PSA alg, use
+ *       \c PSA_HASH_BLOCK_LENGTH().
+ *
+ * \param md_type   The hash MD type.
+ *
+ * \return          The block size in bytes, or 0 if not known.
+ */
+unsigned char mbedtls_hash_info_get_block_size(mbedtls_md_type_t md_type);
+
+/** Get the PSA alg from the MD type.
+ *
+ * \param md_type   The hash MD type.
+ *
+ * \return          The corresponding PSA algorithm identifier,
+ *                  or PSA_ALG_NONE if not known.
+ */
+psa_algorithm_t mbedtls_hash_info_psa_from_md(mbedtls_md_type_t md_type);
+
+/** Get the MD type alg from the PSA algorithm identifier.
+ *
+ * \param psa_alg   The PSA hash algorithm.
+ *
+ * \return          The corresponding MD type,
+ *                  or MBEDTLS_MD_NONE if not known.
+ */
+mbedtls_md_type_t mbedtls_hash_info_md_from_psa(psa_algorithm_t psa_alg);
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+/** Convert PSA status to MD error code.
+ *
+ * \param status    PSA status.
+ *
+ * \return          The corresponding MD error code,
+ */
+int MBEDTLS_DEPRECATED mbedtls_md_error_from_psa(psa_status_t status);
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+#endif /* MBEDTLS_HASH_INFO_H */
diff --git a/lib/libmbedtls/mbedtls/library/havege.c b/lib/libmbedtls/mbedtls/library/havege.c
deleted file mode 100644
index 2a360a1..0000000
--- a/lib/libmbedtls/mbedtls/library/havege.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/**
- *  \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
- *
- *  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.
- */
-/*
- *  The HAVEGE RNG was designed by Andre Seznec in 2002.
- *
- *  http://www.irisa.fr/caps/projects/hipsor/publi.php
- *
- *  Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr
- */
-
-#include "common.h"
-
-#if defined(MBEDTLS_HAVEGE_C)
-
-#include "mbedtls/havege.h"
-#include "mbedtls/timing.h"
-#include "mbedtls/platform_util.h"
-
-#include <stdint.h>
-#include <string.h>
-
-/* ------------------------------------------------------------------------
- * On average, one iteration accesses two 8-word blocks in the havege WALK
- * table, and generates 16 words in the RES array.
- *
- * The data read in the WALK table is updated and permuted after each use.
- * The result of the hardware clock counter read is used  for this update.
- *
- * 25 conditional tests are present.  The conditional tests are grouped in
- * two nested  groups of 12 conditional tests and 1 test that controls the
- * permutation; on average, there should be 6 tests executed and 3 of them
- * should be mispredicted.
- * ------------------------------------------------------------------------
- */
-
-#define SWAP(X,Y) { uint32_t *T = (X); (X) = (Y); (Y) = T; }
-
-#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
-#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
-
-#define TST1_LEAVE U1++; }
-#define TST2_LEAVE U2++; }
-
-#define ONE_ITERATION                                   \
-                                                        \
-    PTEST = PT1 >> 20;                                  \
-                                                        \
-    TST1_ENTER  TST1_ENTER  TST1_ENTER  TST1_ENTER      \
-    TST1_ENTER  TST1_ENTER  TST1_ENTER  TST1_ENTER      \
-    TST1_ENTER  TST1_ENTER  TST1_ENTER  TST1_ENTER      \
-                                                        \
-    TST1_LEAVE  TST1_LEAVE  TST1_LEAVE  TST1_LEAVE      \
-    TST1_LEAVE  TST1_LEAVE  TST1_LEAVE  TST1_LEAVE      \
-    TST1_LEAVE  TST1_LEAVE  TST1_LEAVE  TST1_LEAVE      \
-                                                        \
-    PTX = (PT1 >> 18) & 7;                              \
-    PT1 &= 0x1FFF;                                      \
-    PT2 &= 0x1FFF;                                      \
-    CLK = (uint32_t) mbedtls_timing_hardclock();        \
-                                                        \
-    i = 0;                                              \
-    A = &WALK[PT1    ]; RES[i++] ^= *A;                 \
-    B = &WALK[PT2    ]; RES[i++] ^= *B;                 \
-    C = &WALK[PT1 ^ 1]; RES[i++] ^= *C;                 \
-    D = &WALK[PT2 ^ 4]; RES[i++] ^= *D;                 \
-                                                        \
-    IN = (*A >> (1)) ^ (*A << (31)) ^ CLK;              \
-    *A = (*B >> (2)) ^ (*B << (30)) ^ CLK;              \
-    *B = IN ^ U1;                                       \
-    *C = (*C >> (3)) ^ (*C << (29)) ^ CLK;              \
-    *D = (*D >> (4)) ^ (*D << (28)) ^ CLK;              \
-                                                        \
-    A = &WALK[PT1 ^ 2]; RES[i++] ^= *A;                 \
-    B = &WALK[PT2 ^ 2]; RES[i++] ^= *B;                 \
-    C = &WALK[PT1 ^ 3]; RES[i++] ^= *C;                 \
-    D = &WALK[PT2 ^ 6]; RES[i++] ^= *D;                 \
-                                                        \
-    if( PTEST & 1 ) SWAP( A, C );                       \
-                                                        \
-    IN = (*A >> (5)) ^ (*A << (27)) ^ CLK;              \
-    *A = (*B >> (6)) ^ (*B << (26)) ^ CLK;              \
-    *B = IN; CLK = (uint32_t) mbedtls_timing_hardclock();       \
-    *C = (*C >> (7)) ^ (*C << (25)) ^ CLK;              \
-    *D = (*D >> (8)) ^ (*D << (24)) ^ CLK;              \
-                                                        \
-    A = &WALK[PT1 ^ 4];                                 \
-    B = &WALK[PT2 ^ 1];                                 \
-                                                        \
-    PTEST = PT2 >> 1;                                   \
-                                                        \
-    PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]);   \
-    PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8);  \
-    PTY = (PT2 >> 10) & 7;                              \
-                                                        \
-    TST2_ENTER  TST2_ENTER  TST2_ENTER  TST2_ENTER      \
-    TST2_ENTER  TST2_ENTER  TST2_ENTER  TST2_ENTER      \
-    TST2_ENTER  TST2_ENTER  TST2_ENTER  TST2_ENTER      \
-                                                        \
-    TST2_LEAVE  TST2_LEAVE  TST2_LEAVE  TST2_LEAVE      \
-    TST2_LEAVE  TST2_LEAVE  TST2_LEAVE  TST2_LEAVE      \
-    TST2_LEAVE  TST2_LEAVE  TST2_LEAVE  TST2_LEAVE      \
-                                                        \
-    C = &WALK[PT1 ^ 5];                                 \
-    D = &WALK[PT2 ^ 5];                                 \
-                                                        \
-    RES[i++] ^= *A;                                     \
-    RES[i++] ^= *B;                                     \
-    RES[i++] ^= *C;                                     \
-    RES[i++] ^= *D;                                     \
-                                                        \
-    IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK;             \
-    *A = (*B >> (10)) ^ (*B << (22)) ^ CLK;             \
-    *B = IN ^ U2;                                       \
-    *C = (*C >> (11)) ^ (*C << (21)) ^ CLK;             \
-    *D = (*D >> (12)) ^ (*D << (20)) ^ CLK;             \
-                                                        \
-    A = &WALK[PT1 ^ 6]; RES[i++] ^= *A;                 \
-    B = &WALK[PT2 ^ 3]; RES[i++] ^= *B;                 \
-    C = &WALK[PT1 ^ 7]; RES[i++] ^= *C;                 \
-    D = &WALK[PT2 ^ 7]; RES[i++] ^= *D;                 \
-                                                        \
-    IN = (*A >> (13)) ^ (*A << (19)) ^ CLK;             \
-    *A = (*B >> (14)) ^ (*B << (18)) ^ CLK;             \
-    *B = IN;                                            \
-    *C = (*C >> (15)) ^ (*C << (17)) ^ CLK;             \
-    *D = (*D >> (16)) ^ (*D << (16)) ^ CLK;             \
-                                                        \
-    PT1 = ( RES[( i - 8 ) ^ PTX] ^                      \
-            WALK[PT1 ^ PTX ^ 7] ) & (~1);               \
-    PT1 ^= (PT2 ^ 0x10) & 0x10;                         \
-                                                        \
-    for( n++, i = 0; i < 16; i++ )                      \
-        hs->pool[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i];
-
-/*
- * Entropy gathering function
- */
-static void havege_fill( mbedtls_havege_state *hs )
-{
-    size_t n = 0;
-    size_t i;
-    uint32_t  U1,  U2, *A, *B, *C, *D;
-    uint32_t PT1, PT2, *WALK, RES[16];
-    uint32_t PTX, PTY, CLK, PTEST, IN;
-
-    WALK = hs->WALK;
-    PT1  = hs->PT1;
-    PT2  = hs->PT2;
-
-    PTX  = U1 = 0;
-    PTY  = U2 = 0;
-
-    (void)PTX;
-
-    memset( RES, 0, sizeof( RES ) );
-
-    while( n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4 )
-    {
-        ONE_ITERATION
-        ONE_ITERATION
-        ONE_ITERATION
-        ONE_ITERATION
-    }
-
-    hs->PT1 = PT1;
-    hs->PT2 = PT2;
-
-    hs->offset[0] = 0;
-    hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2;
-}
-
-/*
- * HAVEGE initialization
- */
-void mbedtls_havege_init( mbedtls_havege_state *hs )
-{
-    memset( hs, 0, sizeof( mbedtls_havege_state ) );
-
-    havege_fill( hs );
-}
-
-void mbedtls_havege_free( mbedtls_havege_state *hs )
-{
-    if( hs == NULL )
-        return;
-
-    mbedtls_platform_zeroize( hs, sizeof( mbedtls_havege_state ) );
-}
-
-/*
- * HAVEGE rand function
- */
-int mbedtls_havege_random( void *p_rng, unsigned char *buf, size_t len )
-{
-    uint32_t val;
-    size_t use_len;
-    mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng;
-    unsigned char *p = buf;
-
-    while( len > 0 )
-    {
-        use_len = len;
-        if( use_len > sizeof( val ) )
-            use_len = sizeof( val );
-
-        if( hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE )
-            havege_fill( hs );
-
-        val  = hs->pool[hs->offset[0]++];
-        val ^= hs->pool[hs->offset[1]++];
-
-        memcpy( p, &val, use_len );
-
-        len -= use_len;
-        p += use_len;
-    }
-
-    return( 0 );
-}
-
-#endif /* MBEDTLS_HAVEGE_C */
diff --git a/lib/libmbedtls/mbedtls/library/hkdf.c b/lib/libmbedtls/mbedtls/library/hkdf.c
index 5013729..a3f071e 100644
--- a/lib/libmbedtls/mbedtls/library/hkdf.c
+++ b/lib/libmbedtls/mbedtls/library/hkdf.c
@@ -25,47 +25,43 @@
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 
-int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt,
-                  size_t salt_len, const unsigned char *ikm, size_t ikm_len,
-                  const unsigned char *info, size_t info_len,
-                  unsigned char *okm, size_t okm_len )
+int mbedtls_hkdf(const mbedtls_md_info_t *md, const unsigned char *salt,
+                 size_t salt_len, const unsigned char *ikm, size_t ikm_len,
+                 const unsigned char *info, size_t info_len,
+                 unsigned char *okm, size_t okm_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char prk[MBEDTLS_MD_MAX_SIZE];
 
-    ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, prk );
+    ret = mbedtls_hkdf_extract(md, salt, salt_len, ikm, ikm_len, prk);
 
-    if( ret == 0 )
-    {
-        ret = mbedtls_hkdf_expand( md, prk, mbedtls_md_get_size( md ),
-                                   info, info_len, okm, okm_len );
+    if (ret == 0) {
+        ret = mbedtls_hkdf_expand(md, prk, mbedtls_md_get_size(md),
+                                  info, info_len, okm, okm_len);
     }
 
-    mbedtls_platform_zeroize( prk, sizeof( prk ) );
+    mbedtls_platform_zeroize(prk, sizeof(prk));
 
-    return( ret );
+    return ret;
 }
 
-int mbedtls_hkdf_extract( const mbedtls_md_info_t *md,
-                          const unsigned char *salt, size_t salt_len,
-                          const unsigned char *ikm, size_t ikm_len,
-                          unsigned char *prk )
+int mbedtls_hkdf_extract(const mbedtls_md_info_t *md,
+                         const unsigned char *salt, size_t salt_len,
+                         const unsigned char *ikm, size_t ikm_len,
+                         unsigned char *prk)
 {
     unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' };
 
-    if( salt == NULL )
-    {
+    if (salt == NULL) {
         size_t hash_len;
 
-        if( salt_len != 0 )
-        {
+        if (salt_len != 0) {
             return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
         }
 
-        hash_len = mbedtls_md_get_size( md );
+        hash_len = mbedtls_md_get_size(md);
 
-        if( hash_len == 0 )
-        {
+        if (hash_len == 0) {
             return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
         }
 
@@ -73,12 +69,12 @@
         salt_len = hash_len;
     }
 
-    return( mbedtls_md_hmac( md, salt, salt_len, ikm, ikm_len, prk ) );
+    return mbedtls_md_hmac(md, salt, salt_len, ikm, ikm_len, prk);
 }
 
-int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk,
-                         size_t prk_len, const unsigned char *info,
-                         size_t info_len, unsigned char *okm, size_t okm_len )
+int mbedtls_hkdf_expand(const mbedtls_md_info_t *md, const unsigned char *prk,
+                        size_t prk_len, const unsigned char *info,
+                        size_t info_len, unsigned char *okm, size_t okm_len)
 {
     size_t hash_len;
     size_t where = 0;
@@ -89,28 +85,24 @@
     mbedtls_md_context_t ctx;
     unsigned char t[MBEDTLS_MD_MAX_SIZE];
 
-    if( okm == NULL )
-    {
-        return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );
+    if (okm == NULL) {
+        return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
     }
 
-    hash_len = mbedtls_md_get_size( md );
+    hash_len = mbedtls_md_get_size(md);
 
-    if( prk_len < hash_len || hash_len == 0 )
-    {
-        return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );
+    if (prk_len < hash_len || hash_len == 0) {
+        return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
     }
 
-    if( info == NULL )
-    {
+    if (info == NULL) {
         info = (const unsigned char *) "";
         info_len = 0;
     }
 
     n = okm_len / hash_len;
 
-    if( okm_len % hash_len != 0 )
-    {
+    if (okm_len % hash_len != 0) {
         n++;
     }
 
@@ -118,72 +110,64 @@
      * Per RFC 5869 Section 2.3, okm_len must not exceed
      * 255 times the hash length
      */
-    if( n > 255 )
-    {
-        return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA );
+    if (n > 255) {
+        return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
     }
 
-    mbedtls_md_init( &ctx );
+    mbedtls_md_init(&ctx);
 
-    if( ( ret = mbedtls_md_setup( &ctx, md, 1 ) ) != 0 )
-    {
+    if ((ret = mbedtls_md_setup(&ctx, md, 1)) != 0) {
         goto exit;
     }
 
-    memset( t, 0, hash_len );
+    memset(t, 0, hash_len);
 
     /*
      * Compute T = T(1) | T(2) | T(3) | ... | T(N)
      * Where T(N) is defined in RFC 5869 Section 2.3
      */
-    for( i = 1; i <= n; i++ )
-    {
+    for (i = 1; i <= n; i++) {
         size_t num_to_copy;
         unsigned char c = i & 0xff;
 
-        ret = mbedtls_md_hmac_starts( &ctx, prk, prk_len );
-        if( ret != 0 )
-        {
+        ret = mbedtls_md_hmac_starts(&ctx, prk, prk_len);
+        if (ret != 0) {
             goto exit;
         }
 
-        ret = mbedtls_md_hmac_update( &ctx, t, t_len );
-        if( ret != 0 )
-        {
+        ret = mbedtls_md_hmac_update(&ctx, t, t_len);
+        if (ret != 0) {
             goto exit;
         }
 
-        ret = mbedtls_md_hmac_update( &ctx, info, info_len );
-        if( ret != 0 )
-        {
+        ret = mbedtls_md_hmac_update(&ctx, info, info_len);
+        if (ret != 0) {
             goto exit;
         }
 
         /* The constant concatenated to the end of each T(n) is a single octet.
          * */
-        ret = mbedtls_md_hmac_update( &ctx, &c, 1 );
-        if( ret != 0 )
-        {
+        ret = mbedtls_md_hmac_update(&ctx, &c, 1);
+        if (ret != 0) {
             goto exit;
         }
 
-        ret = mbedtls_md_hmac_finish( &ctx, t );
-        if( ret != 0 )
-        {
+        ret = mbedtls_md_hmac_finish(&ctx, t);
+        if (ret != 0) {
             goto exit;
         }
 
         num_to_copy = i != n ? hash_len : okm_len - where;
-        memcpy( okm + where, t, num_to_copy );
+        memcpy(okm + where, t, num_to_copy);
         where += hash_len;
         t_len = hash_len;
     }
 
 exit:
-    mbedtls_md_free( &ctx );
-    mbedtls_platform_zeroize( t, sizeof( t ) );
+    mbedtls_md_free(&ctx);
+    mbedtls_platform_zeroize(t, sizeof(t));
 
-    return( ret );
+    return ret;
 }
 
 #endif /* MBEDTLS_HKDF_C */
diff --git a/lib/libmbedtls/mbedtls/library/hmac_drbg.c b/lib/libmbedtls/mbedtls/library/hmac_drbg.c
index de97068..b157302 100644
--- a/lib/libmbedtls/mbedtls/library/hmac_drbg.c
+++ b/lib/libmbedtls/mbedtls/library/hmac_drbg.c
@@ -37,21 +37,14 @@
 #include <stdio.h>
 #endif
 
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_SELF_TEST */
-#endif /* MBEDTLS_PLATFORM_C */
 
 /*
  * HMAC_DRBG context initialization
  */
-void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
+void mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context *ctx)
 {
-    memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
+    memset(ctx, 0, sizeof(mbedtls_hmac_drbg_context));
 
     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
 }
@@ -59,74 +52,72 @@
 /*
  * HMAC_DRBG update, using optional additional data (10.1.2.2)
  */
-int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
-                                  const unsigned char *additional,
-                                  size_t add_len )
+int mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx,
+                             const unsigned char *additional,
+                             size_t add_len)
 {
-    size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
-    unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
+    size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info);
+    unsigned char rounds = (additional != NULL && add_len != 0) ? 2 : 1;
     unsigned char sep[1];
     unsigned char K[MBEDTLS_MD_MAX_SIZE];
     int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
 
-    for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
-    {
+    for (sep[0] = 0; sep[0] < rounds; sep[0]++) {
         /* Step 1 or 4 */
-        if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
-            goto exit;
-        if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
-                                            ctx->V, md_len ) ) != 0 )
-            goto exit;
-        if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
-                                            sep, 1 ) ) != 0 )
-            goto exit;
-        if( rounds == 2 )
-        {
-            if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
-                                                additional, add_len ) ) != 0 )
+        if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) {
             goto exit;
         }
-        if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
+        if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
+                                          ctx->V, md_len)) != 0) {
             goto exit;
+        }
+        if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
+                                          sep, 1)) != 0) {
+            goto exit;
+        }
+        if (rounds == 2) {
+            if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
+                                              additional, add_len)) != 0) {
+                goto exit;
+            }
+        }
+        if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, K)) != 0) {
+            goto exit;
+        }
 
         /* Step 2 or 5 */
-        if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
+        if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, K, md_len)) != 0) {
             goto exit;
-        if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
-                                            ctx->V, md_len ) ) != 0 )
+        }
+        if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
+                                          ctx->V, md_len)) != 0) {
             goto exit;
-        if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
+        }
+        if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) {
             goto exit;
+        }
     }
 
 exit:
-    mbedtls_platform_zeroize( K, sizeof( K ) );
-    return( ret );
+    mbedtls_platform_zeroize(K, sizeof(K));
+    return ret;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
-                               const unsigned char *additional,
-                               size_t add_len )
-{
-    (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
-}
-#endif /* MBEDTLS_DEPRECATED_REMOVED */
-
 /*
  * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
  */
-int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
-                        const mbedtls_md_info_t * md_info,
-                        const unsigned char *data, size_t data_len )
+int mbedtls_hmac_drbg_seed_buf(mbedtls_hmac_drbg_context *ctx,
+                               const mbedtls_md_info_t *md_info,
+                               const unsigned char *data, size_t data_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {
+        return ret;
+    }
 
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_init( &ctx->mutex );
+    mbedtls_mutex_init(&ctx->mutex);
 #endif
 
     /*
@@ -134,15 +125,17 @@
      * Use the V memory location, which is currently all 0, to initialize the
      * MD context with an all-zero key. Then set V to its initial value.
      */
-    if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
-                                        mbedtls_md_get_size( md_info ) ) ) != 0 )
-        return( ret );
-    memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
+    if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V,
+                                      mbedtls_md_get_size(md_info))) != 0) {
+        return ret;
+    }
+    memset(ctx->V, 0x01, mbedtls_md_get_size(md_info));
 
-    if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_hmac_drbg_update(ctx, data, data_len)) != 0) {
+        return ret;
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -150,9 +143,9 @@
  * Comments starting with arabic numbers refer to section 10.1.2.4
  * of SP800-90A, while roman numbers refer to section 9.2.
  */
-static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx,
-                                  const unsigned char *additional, size_t len,
-                                  int use_nonce )
+static int hmac_drbg_reseed_core(mbedtls_hmac_drbg_context *ctx,
+                                 const unsigned char *additional, size_t len,
+                                 int use_nonce)
 {
     unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
     size_t seedlen = 0;
@@ -161,33 +154,31 @@
     {
         size_t total_entropy_len;
 
-        if( use_nonce == 0 )
+        if (use_nonce == 0) {
             total_entropy_len = ctx->entropy_len;
-        else
+        } else {
             total_entropy_len = ctx->entropy_len * 3 / 2;
+        }
 
         /* III. Check input length */
-        if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
-            total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
-        {
-            return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
+        if (len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
+            total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) {
+            return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
         }
     }
 
-    memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
+    memset(seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT);
 
     /* IV. Gather entropy_len bytes of entropy for the seed */
-    if( ( ret = ctx->f_entropy( ctx->p_entropy,
-                                seed, ctx->entropy_len ) ) != 0 )
-    {
-        return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
+    if ((ret = ctx->f_entropy(ctx->p_entropy,
+                              seed, ctx->entropy_len)) != 0) {
+        return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;
     }
     seedlen += ctx->entropy_len;
 
     /* For initial seeding, allow adding of nonce generated
      * from the entropy source. See Sect 8.6.7 in SP800-90A. */
-    if( use_nonce )
-    {
+    if (use_nonce) {
         /* Note: We don't merge the two calls to f_entropy() in order
          *       to avoid requesting too much entropy from f_entropy()
          *       at once. Specifically, if the underlying digest is not
@@ -195,11 +186,10 @@
          *       is larger than the maximum of 32 Bytes that our own
          *       entropy source implementation can emit in a single
          *       call in configurations disabling SHA-512. */
-        if( ( ret = ctx->f_entropy( ctx->p_entropy,
-                                    seed + seedlen,
-                                    ctx->entropy_len / 2 ) ) != 0 )
-        {
-            return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
+        if ((ret = ctx->f_entropy(ctx->p_entropy,
+                                  seed + seedlen,
+                                  ctx->entropy_len / 2)) != 0) {
+            return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;
         }
 
         seedlen += ctx->entropy_len / 2;
@@ -207,32 +197,32 @@
 
 
     /* 1. Concatenate entropy and additional data if any */
-    if( additional != NULL && len != 0 )
-    {
-        memcpy( seed + seedlen, additional, len );
+    if (additional != NULL && len != 0) {
+        memcpy(seed + seedlen, additional, len);
         seedlen += len;
     }
 
     /* 2. Update state */
-    if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
+    if ((ret = mbedtls_hmac_drbg_update(ctx, seed, seedlen)) != 0) {
         goto exit;
+    }
 
     /* 3. Reset reseed_counter */
     ctx->reseed_counter = 1;
 
 exit:
     /* 4. Done */
-    mbedtls_platform_zeroize( seed, seedlen );
-    return( ret );
+    mbedtls_platform_zeroize(seed, seedlen);
+    return ret;
 }
 
 /*
  * HMAC_DRBG reseeding: 10.1.2.4 + 9.2
  */
-int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
-                      const unsigned char *additional, size_t len )
+int mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context *ctx,
+                             const unsigned char *additional, size_t len)
 {
-    return( hmac_drbg_reseed_core( ctx, additional, len, 0 ) );
+    return hmac_drbg_reseed_core(ctx, additional, len, 0);
 }
 
 /*
@@ -241,40 +231,41 @@
  * The nonce is not passed as a separate parameter but extracted
  * from the entropy source as suggested in 8.6.7.
  */
-int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
-                    const mbedtls_md_info_t * md_info,
-                    int (*f_entropy)(void *, unsigned char *, size_t),
-                    void *p_entropy,
-                    const unsigned char *custom,
-                    size_t len )
+int mbedtls_hmac_drbg_seed(mbedtls_hmac_drbg_context *ctx,
+                           const mbedtls_md_info_t *md_info,
+                           int (*f_entropy)(void *, unsigned char *, size_t),
+                           void *p_entropy,
+                           const unsigned char *custom,
+                           size_t len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t md_size;
 
-    if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {
+        return ret;
+    }
 
     /* The mutex is initialized iff the md context is set up. */
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_init( &ctx->mutex );
+    mbedtls_mutex_init(&ctx->mutex);
 #endif
 
-    md_size = mbedtls_md_get_size( md_info );
+    md_size = mbedtls_md_get_size(md_info);
 
     /*
      * Set initial working state.
      * Use the V memory location, which is currently all 0, to initialize the
      * MD context with an all-zero key. Then set V to its initial value.
      */
-    if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
-        return( ret );
-    memset( ctx->V, 0x01, md_size );
+    if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V, md_size)) != 0) {
+        return ret;
+    }
+    memset(ctx->V, 0x01, md_size);
 
     ctx->f_entropy = f_entropy;
     ctx->p_entropy = p_entropy;
 
-    if( ctx->entropy_len == 0 )
-    {
+    if (ctx->entropy_len == 0) {
         /*
          * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
          * each hash function, then according to SP800-90A rev1 10.1 table 2,
@@ -287,20 +278,19 @@
                            32;  /* better (256+) -> 256 bits */
     }
 
-    if( ( ret = hmac_drbg_reseed_core( ctx, custom, len,
-                                       1 /* add nonce */ ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = hmac_drbg_reseed_core(ctx, custom, len,
+                                     1 /* add nonce */)) != 0) {
+        return ret;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Set prediction resistance
  */
-void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
-                                          int resistance )
+void mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context *ctx,
+                                                 int resistance)
 {
     ctx->prediction_resistance = resistance;
 }
@@ -308,7 +298,7 @@
 /*
  * Set entropy length grabbed for seeding
  */
-void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
+void mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context *ctx, size_t len)
 {
     ctx->entropy_len = len;
 }
@@ -316,7 +306,7 @@
 /*
  * Set reseed interval
  */
-void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
+void mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context *ctx, int interval)
 {
     ctx->reseed_interval = interval;
 }
@@ -325,131 +315,144 @@
  * HMAC_DRBG random function with optional additional data:
  * 10.1.2.5 (arabic) + 9.3 (Roman)
  */
-int mbedtls_hmac_drbg_random_with_add( void *p_rng,
-                               unsigned char *output, size_t out_len,
-                               const unsigned char *additional, size_t add_len )
+int mbedtls_hmac_drbg_random_with_add(void *p_rng,
+                                      unsigned char *output, size_t out_len,
+                                      const unsigned char *additional, size_t add_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
-    size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
+    size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info);
     size_t left = out_len;
     unsigned char *out = output;
 
     /* II. Check request length */
-    if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
-        return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
+    if (out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST) {
+        return MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG;
+    }
 
     /* III. Check input length */
-    if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
-        return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
+    if (add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT) {
+        return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
+    }
 
     /* 1. (aka VII and IX) Check reseed counter and PR */
-    if( ctx->f_entropy != NULL && /* For no-reseeding instances */
-        ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
-          ctx->reseed_counter > ctx->reseed_interval ) )
-    {
-        if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
-            return( ret );
+    if (ctx->f_entropy != NULL && /* For no-reseeding instances */
+        (ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
+         ctx->reseed_counter > ctx->reseed_interval)) {
+        if ((ret = mbedtls_hmac_drbg_reseed(ctx, additional, add_len)) != 0) {
+            return ret;
+        }
 
         add_len = 0; /* VII.4 */
     }
 
     /* 2. Use additional data if any */
-    if( additional != NULL && add_len != 0 )
-    {
-        if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
-                                                  additional, add_len ) ) != 0 )
+    if (additional != NULL && add_len != 0) {
+        if ((ret = mbedtls_hmac_drbg_update(ctx,
+                                            additional, add_len)) != 0) {
             goto exit;
+        }
     }
 
     /* 3, 4, 5. Generate bytes */
-    while( left != 0 )
-    {
+    while (left != 0) {
         size_t use_len = left > md_len ? md_len : left;
 
-        if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
+        if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) {
             goto exit;
-        if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
-                                            ctx->V, md_len ) ) != 0 )
+        }
+        if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
+                                          ctx->V, md_len)) != 0) {
             goto exit;
-        if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
+        }
+        if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) {
             goto exit;
+        }
 
-        memcpy( out, ctx->V, use_len );
+        memcpy(out, ctx->V, use_len);
         out += use_len;
         left -= use_len;
     }
 
     /* 6. Update */
-    if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
-                                              additional, add_len ) ) != 0 )
+    if ((ret = mbedtls_hmac_drbg_update(ctx,
+                                        additional, add_len)) != 0) {
         goto exit;
+    }
 
     /* 7. Update reseed counter */
     ctx->reseed_counter++;
 
 exit:
     /* 8. Done */
-    return( ret );
+    return ret;
 }
 
 /*
  * HMAC_DRBG random function
  */
-int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
+int mbedtls_hmac_drbg_random(void *p_rng, unsigned char *output, size_t out_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
 
 #if defined(MBEDTLS_THREADING_C)
-    if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
+        return ret;
+    }
 #endif
 
-    ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
+    ret = mbedtls_hmac_drbg_random_with_add(ctx, output, out_len, NULL, 0);
 
 #if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
-        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
+        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
+    }
 #endif
 
-    return( ret );
+    return ret;
 }
 
 /*
  *  This function resets HMAC_DRBG context to the state immediately
  *  after initial call of mbedtls_hmac_drbg_init().
  */
-void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
+void mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
 #if defined(MBEDTLS_THREADING_C)
     /* The mutex is initialized iff the md context is set up. */
-    if( ctx->md_ctx.md_info != NULL )
-        mbedtls_mutex_free( &ctx->mutex );
+    if (ctx->md_ctx.md_info != NULL) {
+        mbedtls_mutex_free(&ctx->mutex);
+    }
 #endif
-    mbedtls_md_free( &ctx->md_ctx );
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
+    mbedtls_md_free(&ctx->md_ctx);
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_hmac_drbg_context));
     ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
 }
 
 #if defined(MBEDTLS_FS_IO)
-int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
+int mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     FILE *f;
-    unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
+    unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];
 
-    if( ( f = fopen( path, "wb" ) ) == NULL )
-        return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
+    if ((f = fopen(path, "wb")) == NULL) {
+        return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
+    }
 
-    if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf(f, NULL);
+
+    if ((ret = mbedtls_hmac_drbg_random(ctx, buf, sizeof(buf))) != 0) {
         goto exit;
+    }
 
-    if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
-    {
+    if (fwrite(buf, 1, sizeof(buf), f) != sizeof(buf)) {
         ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
         goto exit;
     }
@@ -457,46 +460,50 @@
     ret = 0;
 
 exit:
-    fclose( f );
-    mbedtls_platform_zeroize( buf, sizeof( buf ) );
+    fclose(f);
+    mbedtls_platform_zeroize(buf, sizeof(buf));
 
-    return( ret );
+    return ret;
 }
 
-int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
+int mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)
 {
     int ret = 0;
     FILE *f = NULL;
     size_t n;
-    unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
+    unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];
     unsigned char c;
 
-    if( ( f = fopen( path, "rb" ) ) == NULL )
-        return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
+    if ((f = fopen(path, "rb")) == NULL) {
+        return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
+    }
 
-    n = fread( buf, 1, sizeof( buf ), f );
-    if( fread( &c, 1, 1, f ) != 0 )
-    {
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf(f, NULL);
+
+    n = fread(buf, 1, sizeof(buf), f);
+    if (fread(&c, 1, 1, f) != 0) {
         ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
         goto exit;
     }
-    if( n == 0 || ferror( f ) )
-    {
+    if (n == 0 || ferror(f)) {
         ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
         goto exit;
     }
-    fclose( f );
+    fclose(f);
     f = NULL;
 
-    ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
+    ret = mbedtls_hmac_drbg_update(ctx, buf, n);
 
 exit:
-    mbedtls_platform_zeroize( buf, sizeof( buf ) );
-    if( f != NULL )
-        fclose( f );
-    if( ret != 0 )
-        return( ret );
-    return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
+    mbedtls_platform_zeroize(buf, sizeof(buf));
+    if (f != NULL) {
+        fclose(f);
+    }
+    if (ret != 0) {
+        return ret;
+    }
+    return mbedtls_hmac_drbg_write_seed_file(ctx, path);
 }
 #endif /* MBEDTLS_FS_IO */
 
@@ -505,10 +512,10 @@
 
 #if !defined(MBEDTLS_SHA1_C)
 /* Dummy checkup routine */
-int mbedtls_hmac_drbg_self_test( int verbose )
+int mbedtls_hmac_drbg_self_test(int verbose)
 {
     (void) verbose;
-    return( 0 );
+    return 0;
 }
 #else
 
@@ -520,7 +527,8 @@
     0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
     0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
     0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
-    0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
+    0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4
+};
 static const unsigned char result_pr[OUTPUT_LEN] = {
     0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
     0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
@@ -528,14 +536,16 @@
     0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
     0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
     0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
-    0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
+    0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44
+};
 
 /* From a NIST PR=false test vector */
 static const unsigned char entropy_nopr[] = {
     0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
     0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
     0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
-    0xe9, 0x9d, 0xfe, 0xdf };
+    0xe9, 0x9d, 0xfe, 0xdf
+};
 static const unsigned char result_nopr[OUTPUT_LEN] = {
     0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
     0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
@@ -543,85 +553,91 @@
     0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
     0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
     0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
-    0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
+    0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7
+};
 
 /* "Entropy" from buffer */
 static size_t test_offset;
-static int hmac_drbg_self_test_entropy( void *data,
-                                        unsigned char *buf, size_t len )
+static int hmac_drbg_self_test_entropy(void *data,
+                                       unsigned char *buf, size_t len)
 {
     const unsigned char *p = data;
-    memcpy( buf, p + test_offset, len );
+    memcpy(buf, p + test_offset, len);
     test_offset += len;
-    return( 0 );
+    return 0;
 }
 
-#define CHK( c )    if( (c) != 0 )                          \
-                    {                                       \
-                        if( verbose != 0 )                  \
-                            mbedtls_printf( "failed\n" );  \
-                        return( 1 );                        \
-                    }
+#define CHK(c)    if ((c) != 0)                          \
+    {                                       \
+        if (verbose != 0)                  \
+        mbedtls_printf("failed\n");  \
+        return 1;                        \
+    }
 
 /*
  * Checkup routine for HMAC_DRBG with SHA-1
  */
-int mbedtls_hmac_drbg_self_test( int verbose )
+int mbedtls_hmac_drbg_self_test(int verbose)
 {
     mbedtls_hmac_drbg_context ctx;
     unsigned char buf[OUTPUT_LEN];
-    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
+    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
 
-    mbedtls_hmac_drbg_init( &ctx );
+    mbedtls_hmac_drbg_init(&ctx);
 
     /*
      * PR = True
      */
-    if( verbose != 0 )
-        mbedtls_printf( "  HMAC_DRBG (PR = True) : " );
+    if (verbose != 0) {
+        mbedtls_printf("  HMAC_DRBG (PR = True) : ");
+    }
 
     test_offset = 0;
-    CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
-                         hmac_drbg_self_test_entropy, (void *) entropy_pr,
-                         NULL, 0 ) );
-    mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
-    CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
-    CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
-    CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
-    mbedtls_hmac_drbg_free( &ctx );
+    CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,
+                               hmac_drbg_self_test_entropy, (void *) entropy_pr,
+                               NULL, 0));
+    mbedtls_hmac_drbg_set_prediction_resistance(&ctx, MBEDTLS_HMAC_DRBG_PR_ON);
+    CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
+    CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
+    CHK(memcmp(buf, result_pr, OUTPUT_LEN));
+    mbedtls_hmac_drbg_free(&ctx);
 
-    mbedtls_hmac_drbg_free( &ctx );
+    mbedtls_hmac_drbg_free(&ctx);
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
 
     /*
      * PR = False
      */
-    if( verbose != 0 )
-        mbedtls_printf( "  HMAC_DRBG (PR = False) : " );
+    if (verbose != 0) {
+        mbedtls_printf("  HMAC_DRBG (PR = False) : ");
+    }
 
-    mbedtls_hmac_drbg_init( &ctx );
+    mbedtls_hmac_drbg_init(&ctx);
 
     test_offset = 0;
-    CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
-                         hmac_drbg_self_test_entropy, (void *) entropy_nopr,
-                         NULL, 0 ) );
-    CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
-    CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
-    CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
-    CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
-    mbedtls_hmac_drbg_free( &ctx );
+    CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,
+                               hmac_drbg_self_test_entropy, (void *) entropy_nopr,
+                               NULL, 0));
+    CHK(mbedtls_hmac_drbg_reseed(&ctx, NULL, 0));
+    CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
+    CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
+    CHK(memcmp(buf, result_nopr, OUTPUT_LEN));
+    mbedtls_hmac_drbg_free(&ctx);
 
-    mbedtls_hmac_drbg_free( &ctx );
+    mbedtls_hmac_drbg_free(&ctx);
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_SHA1_C */
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/lib/libmbedtls/mbedtls/library/lmots.c b/lib/libmbedtls/mbedtls/library/lmots.c
new file mode 100644
index 0000000..4061edd
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/lmots.c
@@ -0,0 +1,825 @@
+/*
+ * The LM-OTS one-time public-key signature scheme
+ *
+ * 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.
+ */
+
+/*
+ *  The following sources were referenced in the design of this implementation
+ *  of the LM-OTS algorithm:
+ *
+ *  [1] IETF RFC8554
+ *      D. McGrew, M. Curcio, S.Fluhrer
+ *      https://datatracker.ietf.org/doc/html/rfc8554
+ *
+ *  [2] NIST Special Publication 800-208
+ *      David A. Cooper et. al.
+ *      https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_LMS_C)
+
+#include <string.h>
+
+#include "lmots.h"
+
+#include "mbedtls/lms.h"
+#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
+#include "mbedtls/psa_util.h"
+
+#include "psa/crypto.h"
+
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_lms_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+
+#define PUBLIC_KEY_TYPE_OFFSET     (0)
+#define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \
+                                    MBEDTLS_LMOTS_TYPE_LEN)
+#define PUBLIC_KEY_Q_LEAF_ID_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \
+                                     MBEDTLS_LMOTS_I_KEY_ID_LEN)
+#define PUBLIC_KEY_KEY_HASH_OFFSET (PUBLIC_KEY_Q_LEAF_ID_OFFSET + \
+                                    MBEDTLS_LMOTS_Q_LEAF_ID_LEN)
+
+/* We only support parameter sets that use 8-bit digits, as it does not require
+ * translation logic between digits and bytes */
+#define W_WINTERNITZ_PARAMETER (8u)
+#define CHECKSUM_LEN           (2)
+#define I_DIGIT_IDX_LEN        (2)
+#define J_HASH_IDX_LEN         (1)
+#define D_CONST_LEN            (2)
+
+#define DIGIT_MAX_VALUE        ((1u << W_WINTERNITZ_PARAMETER) - 1u)
+
+#define D_CONST_LEN            (2)
+static const unsigned char D_PUBLIC_CONSTANT_BYTES[D_CONST_LEN] = { 0x80, 0x80 };
+static const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = { 0x81, 0x81 };
+
+#if defined(MBEDTLS_TEST_HOOKS)
+int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *) = NULL;
+#endif /* defined(MBEDTLS_TEST_HOOKS) */
+
+void mbedtls_lms_unsigned_int_to_network_bytes(unsigned int val, size_t len,
+                                               unsigned char *bytes)
+{
+    size_t idx;
+
+    for (idx = 0; idx < len; idx++) {
+        bytes[idx] = (val >> ((len - 1 - idx) * 8)) & 0xFF;
+    }
+}
+
+unsigned int mbedtls_lms_network_bytes_to_unsigned_int(size_t len,
+                                                       const unsigned char *bytes)
+{
+    size_t idx;
+    unsigned int val = 0;
+
+    for (idx = 0; idx < len; idx++) {
+        val |= ((unsigned int) bytes[idx]) << (8 * (len - 1 - idx));
+    }
+
+    return val;
+}
+
+/* Calculate the checksum digits that are appended to the end of the LMOTS digit
+ * string. See NIST SP800-208 section 3.1 or RFC8554 Algorithm 2 for details of
+ * the checksum algorithm.
+ *
+ *  params              The LMOTS parameter set, I and q values which
+ *                      describe the key being used.
+ *
+ *  digest              The digit string to create the digest from. As
+ *                      this does not contain a checksum, it is the same
+ *                      size as a hash output.
+ */
+static unsigned short lmots_checksum_calculate(const mbedtls_lmots_parameters_t *params,
+                                               const unsigned char *digest)
+{
+    size_t idx;
+    unsigned sum = 0;
+
+    for (idx = 0; idx < MBEDTLS_LMOTS_N_HASH_LEN(params->type); idx++) {
+        sum += DIGIT_MAX_VALUE - digest[idx];
+    }
+
+    return sum;
+}
+
+/* Create the string of digest digits (in the base determined by the Winternitz
+ * parameter with the checksum appended to the end (Q || cksm(Q)). See NIST
+ * SP800-208 section 3.1 or RFC8554 Algorithm 3 step 5 (also used in Algorithm
+ * 4b step 3) for details.
+ *
+ *  params              The LMOTS parameter set, I and q values which
+ *                      describe the key being used.
+ *
+ *  msg                 The message that will be hashed to create the
+ *                      digest.
+ *
+ *  msg_size            The size of the message.
+ *
+ *  C_random_value      The random value that will be combined with the
+ *                      message digest. This is always the same size as a
+ *                      hash output for whichever hash algorithm is
+ *                      determined by the parameter set.
+ *
+ *  output              An output containing the digit string (+
+ *                      checksum) of length P digits (in the case of
+ *                      MBEDTLS_LMOTS_SHA256_N32_W8, this means it is of
+ *                      size P bytes).
+ */
+static int create_digit_array_with_checksum(const mbedtls_lmots_parameters_t *params,
+                                            const unsigned char *msg,
+                                            size_t msg_len,
+                                            const unsigned char *C_random_value,
+                                            unsigned char *out)
+{
+    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t output_hash_len;
+    unsigned short checksum;
+
+    status = psa_hash_setup(&op, PSA_ALG_SHA_256);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&op, params->I_key_identifier,
+                             MBEDTLS_LMOTS_I_KEY_ID_LEN);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&op, params->q_leaf_identifier,
+                             MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&op, D_MESSAGE_CONSTANT_BYTES, D_CONST_LEN);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&op, C_random_value,
+                             MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(params->type));
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&op, msg, msg_len);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_finish(&op, out,
+                             MBEDTLS_LMOTS_N_HASH_LEN(params->type),
+                             &output_hash_len);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    checksum = lmots_checksum_calculate(params, out);
+    mbedtls_lms_unsigned_int_to_network_bytes(checksum, CHECKSUM_LEN,
+                                              out + MBEDTLS_LMOTS_N_HASH_LEN(params->type));
+
+exit:
+    psa_hash_abort(&op);
+
+    return PSA_TO_MBEDTLS_ERR(status);
+}
+
+/* Hash each element of the string of digits (+ checksum), producing a hash
+ * output for each element. This is used in several places (by varying the
+ * hash_idx_min/max_values) in order to calculate a public key from a private
+ * key (RFC8554 Algorithm 1 step 4), in order to sign a message (RFC8554
+ * Algorithm 3 step 5), and to calculate a public key candidate from a
+ * signature and message (RFC8554 Algorithm 4b step 3).
+ *
+ *  params              The LMOTS parameter set, I and q values which
+ *                      describe the key being used.
+ *
+ *  x_digit_array       The array of digits (of size P, 34 in the case of
+ *                      MBEDTLS_LMOTS_SHA256_N32_W8).
+ *
+ *  hash_idx_min_values An array of the starting values of the j iterator
+ *                      for each of the members of the digit array. If
+ *                      this value in NULL, then all iterators will start
+ *                      at 0.
+ *
+ *  hash_idx_max_values An array of the upper bound values of the j
+ *                      iterator for each of the members of the digit
+ *                      array. If this value in NULL, then iterator is
+ *                      bounded to be less than 2^w - 1 (255 in the case
+ *                      of MBEDTLS_LMOTS_SHA256_N32_W8)
+ *
+ *  output              An array containing a hash output for each member
+ *                      of the digit string P. In the case of
+ *                      MBEDTLS_LMOTS_SHA256_N32_W8, this is of size 32 *
+ *                      34.
+ */
+static int hash_digit_array(const mbedtls_lmots_parameters_t *params,
+                            const unsigned char *x_digit_array,
+                            const unsigned char *hash_idx_min_values,
+                            const unsigned char *hash_idx_max_values,
+                            unsigned char *output)
+{
+    unsigned int i_digit_idx;
+    unsigned char i_digit_idx_bytes[I_DIGIT_IDX_LEN];
+    unsigned int j_hash_idx;
+    unsigned char j_hash_idx_bytes[J_HASH_IDX_LEN];
+    unsigned int j_hash_idx_min;
+    unsigned int j_hash_idx_max;
+    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t output_hash_len;
+    unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
+
+    for (i_digit_idx = 0;
+         i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type);
+         i_digit_idx++) {
+
+        memcpy(tmp_hash,
+               &x_digit_array[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)],
+               MBEDTLS_LMOTS_N_HASH_LEN(params->type));
+
+        j_hash_idx_min = hash_idx_min_values != NULL ?
+                         hash_idx_min_values[i_digit_idx] : 0;
+        j_hash_idx_max = hash_idx_max_values != NULL ?
+                         hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE;
+
+        for (j_hash_idx = j_hash_idx_min;
+             j_hash_idx < j_hash_idx_max;
+             j_hash_idx++) {
+            status = psa_hash_setup(&op, PSA_ALG_SHA_256);
+            if (status != PSA_SUCCESS) {
+                goto exit;
+            }
+
+            status = psa_hash_update(&op,
+                                     params->I_key_identifier,
+                                     MBEDTLS_LMOTS_I_KEY_ID_LEN);
+            if (status != PSA_SUCCESS) {
+                goto exit;
+            }
+
+            status = psa_hash_update(&op,
+                                     params->q_leaf_identifier,
+                                     MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
+            if (status != PSA_SUCCESS) {
+                goto exit;
+            }
+
+            mbedtls_lms_unsigned_int_to_network_bytes(i_digit_idx,
+                                                      I_DIGIT_IDX_LEN,
+                                                      i_digit_idx_bytes);
+            status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN);
+            if (status != PSA_SUCCESS) {
+                goto exit;
+            }
+
+            mbedtls_lms_unsigned_int_to_network_bytes(j_hash_idx,
+                                                      J_HASH_IDX_LEN,
+                                                      j_hash_idx_bytes);
+            status = psa_hash_update(&op, j_hash_idx_bytes, J_HASH_IDX_LEN);
+            if (status != PSA_SUCCESS) {
+                goto exit;
+            }
+
+            status = psa_hash_update(&op, tmp_hash,
+                                     MBEDTLS_LMOTS_N_HASH_LEN(params->type));
+            if (status != PSA_SUCCESS) {
+                goto exit;
+            }
+
+            status = psa_hash_finish(&op, tmp_hash, sizeof(tmp_hash),
+                                     &output_hash_len);
+            if (status != PSA_SUCCESS) {
+                goto exit;
+            }
+
+            psa_hash_abort(&op);
+        }
+
+        memcpy(&output[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)],
+               tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN(params->type));
+    }
+
+exit:
+    psa_hash_abort(&op);
+    mbedtls_platform_zeroize(tmp_hash, sizeof(tmp_hash));
+
+    return PSA_TO_MBEDTLS_ERR(status);
+}
+
+/* Combine the hashes of the digit array into a public key. This is used in
+ * in order to calculate a public key from a private key (RFC8554 Algorithm 1
+ * step 4), and to calculate a public key candidate from a signature and message
+ * (RFC8554 Algorithm 4b step 3).
+ *
+ *  params           The LMOTS parameter set, I and q values which describe
+ *                   the key being used.
+ *  y_hashed_digits  The array of hashes, one hash for each digit of the
+ *                   symbol array (which is of size P, 34 in the case of
+ *                   MBEDTLS_LMOTS_SHA256_N32_W8)
+ *
+ *  pub_key          The output public key (or candidate public key in
+ *                   case this is being run as part of signature
+ *                   verification), in the form of a hash output.
+ */
+static int public_key_from_hashed_digit_array(const mbedtls_lmots_parameters_t *params,
+                                              const unsigned char *y_hashed_digits,
+                                              unsigned char *pub_key)
+{
+    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t output_hash_len;
+
+    status = psa_hash_setup(&op, PSA_ALG_SHA_256);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&op,
+                             params->I_key_identifier,
+                             MBEDTLS_LMOTS_I_KEY_ID_LEN);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&op, params->q_leaf_identifier,
+                             MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&op, D_PUBLIC_CONSTANT_BYTES, D_CONST_LEN);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&op, y_hashed_digits,
+                             MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type) *
+                             MBEDTLS_LMOTS_N_HASH_LEN(params->type));
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_finish(&op, pub_key,
+                             MBEDTLS_LMOTS_N_HASH_LEN(params->type),
+                             &output_hash_len);
+    if (status != PSA_SUCCESS) {
+
+exit:
+        psa_hash_abort(&op);
+    }
+
+    return PSA_TO_MBEDTLS_ERR(status);
+}
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+int mbedtls_lms_error_from_psa(psa_status_t status)
+{
+    switch (status) {
+        case PSA_SUCCESS:
+            return 0;
+        case PSA_ERROR_HARDWARE_FAILURE:
+            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+        case PSA_ERROR_NOT_SUPPORTED:
+            return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
+        case PSA_ERROR_BUFFER_TOO_SMALL:
+            return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
+        case PSA_ERROR_INVALID_ARGUMENT:
+            return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+        default:
+            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
+    }
+}
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+
+void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx)
+{
+    memset(ctx, 0, sizeof(*ctx));
+}
+
+void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx)
+{
+    mbedtls_platform_zeroize(ctx, sizeof(*ctx));
+}
+
+int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx,
+                                    const unsigned char *key, size_t key_len)
+{
+    if (key_len < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    ctx->params.type =
+        mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMOTS_TYPE_LEN,
+                                                  key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
+
+    if (key_len != MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    memcpy(ctx->params.I_key_identifier,
+           key + PUBLIC_KEY_I_KEY_ID_OFFSET,
+           MBEDTLS_LMOTS_I_KEY_ID_LEN);
+
+    memcpy(ctx->params.q_leaf_identifier,
+           key + PUBLIC_KEY_Q_LEAF_ID_OFFSET,
+           MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
+
+    memcpy(ctx->public_key,
+           key + PUBLIC_KEY_KEY_HASH_OFFSET,
+           MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));
+
+    ctx->have_public_key = 1;
+
+    return 0;
+}
+
+int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx,
+                                    unsigned char *key, size_t key_size,
+                                    size_t *key_len)
+{
+    if (key_size < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) {
+        return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
+    }
+
+    if (!ctx->have_public_key) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    mbedtls_lms_unsigned_int_to_network_bytes(ctx->params.type,
+                                              MBEDTLS_LMOTS_TYPE_LEN,
+                                              key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
+
+    memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET,
+           ctx->params.I_key_identifier,
+           MBEDTLS_LMOTS_I_KEY_ID_LEN);
+
+    memcpy(key + PUBLIC_KEY_Q_LEAF_ID_OFFSET,
+           ctx->params.q_leaf_identifier,
+           MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
+
+    memcpy(key + PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key,
+           MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));
+
+    if (key_len != NULL) {
+        *key_len = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type);
+    }
+
+    return 0;
+}
+
+int mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params,
+                                                 const unsigned char  *msg,
+                                                 size_t msg_size,
+                                                 const unsigned char *sig,
+                                                 size_t sig_size,
+                                                 unsigned char *out,
+                                                 size_t out_size,
+                                                 size_t *out_len)
+{
+    unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX];
+    unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if (msg == NULL && msg_size != 0) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    if (sig_size != MBEDTLS_LMOTS_SIG_LEN(params->type) ||
+        out_size < MBEDTLS_LMOTS_N_HASH_LEN(params->type)) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    ret = create_digit_array_with_checksum(params, msg, msg_size,
+                                           sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET,
+                                           tmp_digit_array);
+    if (ret) {
+        return ret;
+    }
+
+    ret = hash_digit_array(params,
+                           sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(params->type),
+                           tmp_digit_array, NULL, (unsigned char *) y_hashed_digits);
+    if (ret) {
+        return ret;
+    }
+
+    ret = public_key_from_hashed_digit_array(params,
+                                             (unsigned char *) y_hashed_digits,
+                                             out);
+    if (ret) {
+        return ret;
+    }
+
+    if (out_len != NULL) {
+        *out_len = MBEDTLS_LMOTS_N_HASH_LEN(params->type);
+    }
+
+    return 0;
+}
+
+int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx,
+                         const unsigned char *msg, size_t msg_size,
+                         const unsigned char *sig, size_t sig_size)
+{
+    unsigned char Kc_public_key_candidate[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if (msg == NULL && msg_size != 0) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    if (!ctx->have_public_key) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    if (ctx->params.type != MBEDTLS_LMOTS_SHA256_N32_W8) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    if (sig_size < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) {
+        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
+    }
+
+    if (mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMOTS_TYPE_LEN,
+                                                  sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET) !=
+        MBEDTLS_LMOTS_SHA256_N32_W8) {
+        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
+    }
+
+    ret = mbedtls_lmots_calculate_public_key_candidate(&ctx->params,
+                                                       msg, msg_size, sig, sig_size,
+                                                       Kc_public_key_candidate,
+                                                       MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type),
+                                                       NULL);
+    if (ret) {
+        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
+    }
+
+    if (memcmp(&Kc_public_key_candidate, ctx->public_key,
+               sizeof(ctx->public_key))) {
+        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
+    }
+
+    return 0;
+}
+
+#if defined(MBEDTLS_LMS_PRIVATE)
+
+void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx)
+{
+    memset(ctx, 0, sizeof(*ctx));
+}
+
+void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx)
+{
+    mbedtls_platform_zeroize(ctx,
+                             sizeof(*ctx));
+}
+
+int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx,
+                                       mbedtls_lmots_algorithm_type_t type,
+                                       const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN],
+                                       uint32_t q_leaf_identifier,
+                                       const unsigned char *seed,
+                                       size_t seed_size)
+{
+    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t output_hash_len;
+    unsigned int i_digit_idx;
+    unsigned char i_digit_idx_bytes[2];
+    unsigned char const_bytes[1];
+
+    if (ctx->have_private_key) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    if (type != MBEDTLS_LMOTS_SHA256_N32_W8) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    ctx->params.type = type;
+
+    memcpy(ctx->params.I_key_identifier,
+           I_key_identifier,
+           sizeof(ctx->params.I_key_identifier));
+
+    mbedtls_lms_unsigned_int_to_network_bytes(q_leaf_identifier,
+                                              MBEDTLS_LMOTS_Q_LEAF_ID_LEN,
+                                              ctx->params.q_leaf_identifier);
+
+    mbedtls_lms_unsigned_int_to_network_bytes(0xFF, sizeof(const_bytes),
+                                              const_bytes);
+
+    for (i_digit_idx = 0;
+         i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type);
+         i_digit_idx++) {
+        status = psa_hash_setup(&op, PSA_ALG_SHA_256);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+
+        status = psa_hash_update(&op,
+                                 ctx->params.I_key_identifier,
+                                 sizeof(ctx->params.I_key_identifier));
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+
+        status = psa_hash_update(&op,
+                                 ctx->params.q_leaf_identifier,
+                                 MBEDTLS_LMOTS_Q_LEAF_ID_LEN);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+
+        mbedtls_lms_unsigned_int_to_network_bytes(i_digit_idx, I_DIGIT_IDX_LEN,
+                                                  i_digit_idx_bytes);
+        status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+
+        status = psa_hash_update(&op, const_bytes, sizeof(const_bytes));
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+
+        status = psa_hash_update(&op, seed, seed_size);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+
+        status = psa_hash_finish(&op,
+                                 ctx->private_key[i_digit_idx],
+                                 MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type),
+                                 &output_hash_len);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+
+        psa_hash_abort(&op);
+    }
+
+    ctx->have_private_key = 1;
+
+exit:
+    psa_hash_abort(&op);
+
+    return PSA_TO_MBEDTLS_ERR(status);
+}
+
+int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx,
+                                       const mbedtls_lmots_private_t *priv_ctx)
+{
+    unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    /* Check that a private key is loaded */
+    if (!priv_ctx->have_private_key) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    ret = hash_digit_array(&priv_ctx->params,
+                           (unsigned char *) priv_ctx->private_key, NULL,
+                           NULL, (unsigned char *) y_hashed_digits);
+    if (ret) {
+        goto exit;
+    }
+
+    ret = public_key_from_hashed_digit_array(&priv_ctx->params,
+                                             (unsigned char *) y_hashed_digits,
+                                             ctx->public_key);
+    if (ret) {
+        goto exit;
+    }
+
+    memcpy(&ctx->params, &priv_ctx->params,
+           sizeof(ctx->params));
+
+    ctx->have_public_key = 1;
+
+exit:
+    mbedtls_platform_zeroize(y_hashed_digits, sizeof(y_hashed_digits));
+
+    return ret;
+}
+
+int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng, const unsigned char *msg, size_t msg_size,
+                       unsigned char *sig, size_t sig_size, size_t *sig_len)
+{
+    unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX];
+    /* Create a temporary buffer to prepare the signature in. This allows us to
+     * finish creating a signature (ensuring the process doesn't fail), and then
+     * erase the private key **before** writing any data into the sig parameter
+     * buffer. If data were directly written into the sig buffer, it might leak
+     * a partial signature on failure, which effectively compromises the private
+     * key.
+     */
+    unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];
+    unsigned char tmp_c_random[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if (msg == NULL && msg_size != 0) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    if (sig_size < MBEDTLS_LMOTS_SIG_LEN(ctx->params.type)) {
+        return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
+    }
+
+    /* Check that a private key is loaded */
+    if (!ctx->have_private_key) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    ret = f_rng(p_rng, tmp_c_random,
+                MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));
+    if (ret) {
+        return ret;
+    }
+
+    ret = create_digit_array_with_checksum(&ctx->params,
+                                           msg, msg_size,
+                                           tmp_c_random,
+                                           tmp_digit_array);
+    if (ret) {
+        goto exit;
+    }
+
+    ret = hash_digit_array(&ctx->params, (unsigned char *) ctx->private_key,
+                           NULL, tmp_digit_array, (unsigned char *) tmp_sig);
+    if (ret) {
+        goto exit;
+    }
+
+    mbedtls_lms_unsigned_int_to_network_bytes(ctx->params.type,
+                                              MBEDTLS_LMOTS_TYPE_LEN,
+                                              sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
+
+    /* Test hook to check if sig is being written to before we invalidate the
+     * private key.
+     */
+#if defined(MBEDTLS_TEST_HOOKS)
+    if (mbedtls_lmots_sign_private_key_invalidated_hook != NULL) {
+        ret = (*mbedtls_lmots_sign_private_key_invalidated_hook)(sig);
+        if (ret != 0) {
+            return ret;
+        }
+    }
+#endif /* defined(MBEDTLS_TEST_HOOKS) */
+
+    /* We've got a valid signature now, so it's time to make sure the private
+     * key can't be reused.
+     */
+    ctx->have_private_key = 0;
+    mbedtls_platform_zeroize(ctx->private_key,
+                             sizeof(ctx->private_key));
+
+    memcpy(sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_c_random,
+           MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(ctx->params.type));
+
+    memcpy(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(ctx->params.type), tmp_sig,
+           MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type)
+           * MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type));
+
+    if (sig_len != NULL) {
+        *sig_len = MBEDTLS_LMOTS_SIG_LEN(ctx->params.type);
+    }
+
+    ret = 0;
+
+exit:
+    mbedtls_platform_zeroize(tmp_digit_array, sizeof(tmp_digit_array));
+    mbedtls_platform_zeroize(tmp_sig, sizeof(tmp_sig));
+
+    return ret;
+}
+
+#endif /* defined(MBEDTLS_LMS_PRIVATE) */
+#endif /* defined(MBEDTLS_LMS_C) */
diff --git a/lib/libmbedtls/mbedtls/library/lmots.h b/lib/libmbedtls/mbedtls/library/lmots.h
new file mode 100644
index 0000000..98d1941
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/lmots.h
@@ -0,0 +1,323 @@
+/**
+ * \file lmots.h
+ *
+ * \brief This file provides an API for the LM-OTS post-quantum-safe one-time
+ *        public-key signature scheme as defined in RFC8554 and NIST.SP.200-208.
+ *        This implementation currently only supports a single parameter set
+ *        MBEDTLS_LMOTS_SHA256_N32_W8 in order to reduce complexity.
+ */
+/*
+ *  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_LMOTS_H
+#define MBEDTLS_LMOTS_H
+
+#include "mbedtls/build_info.h"
+
+#include "psa/crypto.h"
+
+#include "mbedtls/lms.h"
+
+#include <stdint.h>
+#include <stddef.h>
+
+
+#define MBEDTLS_LMOTS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \
+                                            MBEDTLS_LMOTS_I_KEY_ID_LEN + \
+                                            MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \
+                                            MBEDTLS_LMOTS_N_HASH_LEN(type))
+
+#define MBEDTLS_LMOTS_SIG_TYPE_OFFSET       (0)
+#define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + \
+                                           MBEDTLS_LMOTS_TYPE_LEN)
+#define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(type) (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + \
+                                                  MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if defined(MBEDTLS_TEST_HOOKS)
+extern int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *);
+#endif /* defined(MBEDTLS_TEST_HOOKS) */
+
+/**
+ * \brief                    This function converts an unsigned int into a
+ *                           network-byte-order (big endian) string.
+ *
+ * \param val                The unsigned integer value
+ * \param len                The length of the string.
+ * \param bytes              The string to output into.
+ */
+void mbedtls_lms_unsigned_int_to_network_bytes(unsigned int val, size_t len,
+                                               unsigned char *bytes);
+
+/**
+ * \brief                    This function converts a network-byte-order
+ *                           (big endian) string into an unsigned integer.
+ *
+ * \param len                The length of the string.
+ * \param bytes              The string.
+ *
+ * \return                   The corresponding LMS error code.
+ */
+unsigned int mbedtls_lms_network_bytes_to_unsigned_int(size_t len,
+                                                       const unsigned char *bytes);
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+/**
+ * \brief                    This function converts a \ref psa_status_t to a
+ *                           low-level LMS error code.
+ *
+ * \param status             The psa_status_t to convert
+ *
+ * \return                   The corresponding LMS error code.
+ */
+int MBEDTLS_DEPRECATED mbedtls_lms_error_from_psa(psa_status_t status);
+#endif
+
+/**
+ * \brief                    This function initializes a public LMOTS context
+ *
+ * \param ctx                The uninitialized LMOTS context that will then be
+ *                           initialized.
+ */
+void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx);
+
+/**
+ * \brief                    This function uninitializes a public LMOTS context
+ *
+ * \param ctx                The initialized LMOTS context that will then be
+ *                           uninitialized.
+ */
+void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx);
+
+/**
+ * \brief                    This function imports an LMOTS public key into a
+ *                           LMOTS context.
+ *
+ * \note                     Before this function is called, the context must
+ *                           have been initialized.
+ *
+ * \note                     See IETF RFC8554 for details of the encoding of
+ *                           this public key.
+ *
+ * \param ctx                The initialized LMOTS context store the key in.
+ * \param key                The buffer from which the key will be read.
+ *                           #MBEDTLS_LMOTS_PUBLIC_KEY_LEN bytes will be read
+ *                           from this.
+ *
+ * \return         \c 0 on success.
+ * \return         A non-zero error code on failure.
+ */
+int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx,
+                                    const unsigned char *key, size_t key_size);
+
+/**
+ * \brief                    This function exports an LMOTS public key from a
+ *                           LMOTS context that already contains a public key.
+ *
+ * \note                     Before this function is called, the context must
+ *                           have been initialized and the context must contain
+ *                           a public key.
+ *
+ * \note                     See IETF RFC8554 for details of the encoding of
+ *                           this public key.
+ *
+ * \param ctx                The initialized LMOTS context that contains the
+ *                           public key.
+ * \param key                The buffer into which the key will be output. Must
+ *                           be at least #MBEDTLS_LMOTS_PUBLIC_KEY_LEN in size.
+ *
+ * \return         \c 0 on success.
+ * \return         A non-zero error code on failure.
+ */
+int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx,
+                                    unsigned char *key, size_t key_size,
+                                    size_t *key_len);
+
+/**
+ * \brief                    This function creates a candidate public key from
+ *                           an LMOTS signature. This can then be compared to
+ *                           the real public key to determine the validity of
+ *                           the signature.
+ *
+ * \note                     This function is exposed publicly to be used in LMS
+ *                           signature verification, it is expected that
+ *                           mbedtls_lmots_verify will be used for LMOTS
+ *                           signature verification.
+ *
+ * \param params             The LMOTS parameter set, q and I values as an
+ *                           mbedtls_lmots_parameters_t struct.
+ * \param msg                The buffer from which the message will be read.
+ * \param msg_size           The size of the message that will be read.
+ * \param sig                The buffer from which the signature will be read.
+ *                           #MBEDTLS_LMOTS_SIG_LEN bytes will be read from
+ *                           this.
+ * \param out                The buffer where the candidate public key will be
+ *                           stored. Must be at least #MBEDTLS_LMOTS_N_HASH_LEN
+ *                           bytes in size.
+ *
+ * \return         \c 0 on success.
+ * \return         A non-zero error code on failure.
+ */
+int mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params,
+                                                 const unsigned char *msg,
+                                                 size_t msg_size,
+                                                 const unsigned char *sig,
+                                                 size_t sig_size,
+                                                 unsigned char *out,
+                                                 size_t out_size,
+                                                 size_t *out_len);
+
+/**
+ * \brief                    This function verifies a LMOTS signature, using a
+ *                           LMOTS context that contains a public key.
+ *
+ * \warning                  This function is **not intended for use in
+ *                           production**, due to as-yet unsolved problems with
+ *                           handling stateful keys. The API for this function
+ *                           may change considerably in future versions.
+ *
+ * \note                     Before this function is called, the context must
+ *                           have been initialized and must contain a public key
+ *                           (either by import or calculation from a private
+ *                           key).
+ *
+ * \param ctx                The initialized LMOTS context from which the public
+ *                           key will be read.
+ * \param msg                The buffer from which the message will be read.
+ * \param msg_size           The size of the message that will be read.
+ * \param sig                The buf from which the signature will be read.
+ *                           #MBEDTLS_LMOTS_SIG_LEN bytes will be read from
+ *                           this.
+ *
+ * \return         \c 0 on successful verification.
+ * \return         A non-zero error code on failure.
+ */
+int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx,
+                         const unsigned char *msg,
+                         size_t msg_size, const unsigned char *sig,
+                         size_t sig_size);
+
+#if defined(MBEDTLS_LMS_PRIVATE)
+
+/**
+ * \brief                    This function initializes a private LMOTS context
+ *
+ * \param ctx                The uninitialized LMOTS context that will then be
+ *                           initialized.
+ */
+void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx);
+
+/**
+ * \brief                    This function uninitializes a private LMOTS context
+ *
+ * \param ctx                The initialized LMOTS context that will then be
+ *                           uninitialized.
+ */
+void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx);
+
+/**
+ * \brief                    This function calculates an LMOTS private key, and
+ *                           stores in into an LMOTS context.
+ *
+ * \warning                  This function is **not intended for use in
+ *                           production**, due to as-yet unsolved problems with
+ *                           handling stateful keys. The API for this function
+ *                           may change considerably in future versions.
+ *
+ * \note                     The seed must have at least 256 bits of entropy.
+ *
+ * \param ctx                The initialized LMOTS context to generate the key
+ *                           into.
+ * \param I_key_identifier   The key identifier of the key, as a 16-byte string.
+ * \param q_leaf_identifier  The leaf identifier of key. If this LMOTS key is
+ *                           not being used as part of an LMS key, this should
+ *                           be set to 0.
+ * \param seed               The seed used to deterministically generate the
+ *                           key.
+ * \param seed_size          The length of the seed.
+ *
+ * \return         \c 0 on success.
+ * \return         A non-zero error code on failure.
+ */
+int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx,
+                                       mbedtls_lmots_algorithm_type_t type,
+                                       const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN],
+                                       uint32_t q_leaf_identifier,
+                                       const unsigned char *seed,
+                                       size_t seed_size);
+
+/**
+ * \brief                    This function generates an LMOTS public key from a
+ *                           LMOTS context that already contains a private key.
+ *
+ * \note                     Before this function is called, the context must
+ *                           have been initialized and the context must contain
+ *                           a private key.
+ *
+ * \param ctx                The initialized LMOTS context to generate the key
+ *                           from and store it into.
+ *
+ * \return         \c 0 on success.
+ * \return         A non-zero error code on failure.
+ */
+int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx,
+                                       const mbedtls_lmots_private_t *priv_ctx);
+
+/**
+ * \brief                    This function creates a LMOTS signature, using a
+ *                           LMOTS context that contains a private key.
+ *
+ * \note                     Before this function is called, the context must
+ *                           have been initialized and must contain a private
+ *                           key.
+ *
+ * \note                     LMOTS private keys can only be used once, otherwise
+ *                           attackers may be able to create forged signatures.
+ *                           If the signing operation is successful, the private
+ *                           key in the context will be erased, and no further
+ *                           signing will be possible until another private key
+ *                           is loaded
+ *
+ * \param ctx                The initialized LMOTS context from which the
+ *                           private key will be read.
+ * \param f_rng              The RNG function to be used for signature
+ *                           generation.
+ * \param p_rng              The RNG context to be passed to f_rng
+ * \param msg                The buffer from which the message will be read.
+ * \param msg_size           The size of the message that will be read.
+ * \param sig                The buf into which the signature will be stored.
+ *                           Must be at least #MBEDTLS_LMOTS_SIG_LEN in size.
+ *
+ * \return         \c 0 on success.
+ * \return         A non-zero error code on failure.
+ */
+int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx,
+                       int (*f_rng)(void *, unsigned char *, size_t),
+                       void *p_rng, const unsigned char *msg, size_t msg_size,
+                       unsigned char *sig, size_t sig_size, size_t *sig_len);
+
+#endif /* defined(MBEDTLS_LMS_PRIVATE) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_LMOTS_H */
diff --git a/lib/libmbedtls/mbedtls/library/lms.c b/lib/libmbedtls/mbedtls/library/lms.c
new file mode 100644
index 0000000..acc3523
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/lms.c
@@ -0,0 +1,783 @@
+/*
+ *  The LMS stateful-hash public-key signature scheme
+ *
+ *  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.
+ */
+
+/*
+ *  The following sources were referenced in the design of this implementation
+ *  of the LMS algorithm:
+ *
+ *  [1] IETF RFC8554
+ *      D. McGrew, M. Curcio, S.Fluhrer
+ *      https://datatracker.ietf.org/doc/html/rfc8554
+ *
+ *  [2] NIST Special Publication 800-208
+ *      David A. Cooper et. al.
+ *      https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_LMS_C)
+
+#include <string.h>
+
+#include "lmots.h"
+
+#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
+#include "mbedtls/lms.h"
+#include "mbedtls/error.h"
+#include "mbedtls/platform_util.h"
+
+#include "mbedtls/platform.h"
+
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_lms_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+
+#define SIG_Q_LEAF_ID_OFFSET     (0)
+#define SIG_OTS_SIG_OFFSET       (SIG_Q_LEAF_ID_OFFSET + \
+                                  MBEDTLS_LMOTS_Q_LEAF_ID_LEN)
+#define SIG_TYPE_OFFSET(otstype) (SIG_OTS_SIG_OFFSET   + \
+                                  MBEDTLS_LMOTS_SIG_LEN(otstype))
+#define SIG_PATH_OFFSET(otstype) (SIG_TYPE_OFFSET(otstype) + \
+                                  MBEDTLS_LMS_TYPE_LEN)
+
+#define PUBLIC_KEY_TYPE_OFFSET      (0)
+#define PUBLIC_KEY_OTSTYPE_OFFSET   (PUBLIC_KEY_TYPE_OFFSET + \
+                                     MBEDTLS_LMS_TYPE_LEN)
+#define PUBLIC_KEY_I_KEY_ID_OFFSET  (PUBLIC_KEY_OTSTYPE_OFFSET  + \
+                                     MBEDTLS_LMOTS_TYPE_LEN)
+#define PUBLIC_KEY_ROOT_NODE_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \
+                                     MBEDTLS_LMOTS_I_KEY_ID_LEN)
+
+
+/* Currently only support H=10 */
+#define H_TREE_HEIGHT_MAX                  10
+#define MERKLE_TREE_NODE_AM(type)          ((size_t) 1 << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u))
+#define MERKLE_TREE_LEAF_NODE_AM(type)     ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type))
+#define MERKLE_TREE_INTERNAL_NODE_AM(type) ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type))
+
+#define D_CONST_LEN           (2)
+static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = { 0x82, 0x82 };
+static const unsigned char D_INTR_CONSTANT_BYTES[D_CONST_LEN] = { 0x83, 0x83 };
+
+
+/* Calculate the value of a leaf node of the Merkle tree (which is a hash of a
+ * public key and some other parameters like the leaf index). This function
+ * implements RFC8554 section 5.3, in the case where r >= 2^h.
+ *
+ *  params              The LMS parameter set, the underlying LMOTS
+ *                      parameter set, and I value which describe the key
+ *                      being used.
+ *
+ *  pub_key             The public key of the private whose index
+ *                      corresponds to the index of this leaf node. This
+ *                      is a hash output.
+ *
+ *  r_node_idx          The index of this node in the Merkle tree. Note
+ *                      that the root node of the Merkle tree is
+ *                      1-indexed.
+ *
+ *  out                 The output node value, which is a hash output.
+ */
+static int create_merkle_leaf_value(const mbedtls_lms_parameters_t *params,
+                                    unsigned char *pub_key,
+                                    unsigned int r_node_idx,
+                                    unsigned char *out)
+{
+    psa_hash_operation_t op;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t output_hash_len;
+    unsigned char r_node_idx_bytes[4];
+
+    op = psa_hash_operation_init();
+    status = psa_hash_setup(&op, PSA_ALG_SHA_256);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&op, params->I_key_identifier,
+                             MBEDTLS_LMOTS_I_KEY_ID_LEN);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    mbedtls_lms_unsigned_int_to_network_bytes(r_node_idx, 4, r_node_idx_bytes);
+    status = psa_hash_update(&op, r_node_idx_bytes, 4);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&op, D_LEAF_CONSTANT_BYTES, D_CONST_LEN);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&op, pub_key,
+                             MBEDTLS_LMOTS_N_HASH_LEN(params->otstype));
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type),
+                             &output_hash_len);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+exit:
+    psa_hash_abort(&op);
+
+    return PSA_TO_MBEDTLS_ERR(status);
+}
+
+/* Calculate the value of an internal node of the Merkle tree (which is a hash
+ * of a public key and some other parameters like the node index). This function
+ * implements RFC8554 section 5.3, in the case where r < 2^h.
+ *
+ *  params              The LMS parameter set, the underlying LMOTS
+ *                      parameter set, and I value which describe the key
+ *                      being used.
+ *
+ *  left_node           The value of the child of this node which is on
+ *                      the left-hand side. As with all nodes on the
+ *                      Merkle tree, this is a hash output.
+ *
+ *  right_node          The value of the child of this node which is on
+ *                      the right-hand side. As with all nodes on the
+ *                      Merkle tree, this is a hash output.
+ *
+ *  r_node_idx          The index of this node in the Merkle tree. Note
+ *                      that the root node of the Merkle tree is
+ *                      1-indexed.
+ *
+ *  out                 The output node value, which is a hash output.
+ */
+static int create_merkle_internal_value(const mbedtls_lms_parameters_t *params,
+                                        const unsigned char *left_node,
+                                        const unsigned char *right_node,
+                                        unsigned int r_node_idx,
+                                        unsigned char *out)
+{
+    psa_hash_operation_t op;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t output_hash_len;
+    unsigned char r_node_idx_bytes[4];
+
+    op = psa_hash_operation_init();
+    status = psa_hash_setup(&op, PSA_ALG_SHA_256);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&op, params->I_key_identifier,
+                             MBEDTLS_LMOTS_I_KEY_ID_LEN);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    mbedtls_lms_unsigned_int_to_network_bytes(r_node_idx, 4, r_node_idx_bytes);
+    status = psa_hash_update(&op, r_node_idx_bytes, 4);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&op, D_INTR_CONSTANT_BYTES, D_CONST_LEN);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&op, left_node,
+                             MBEDTLS_LMS_M_NODE_BYTES(params->type));
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&op, right_node,
+                             MBEDTLS_LMS_M_NODE_BYTES(params->type));
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type),
+                             &output_hash_len);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+exit:
+    psa_hash_abort(&op);
+
+    return PSA_TO_MBEDTLS_ERR(status);
+}
+
+void mbedtls_lms_public_init(mbedtls_lms_public_t *ctx)
+{
+    memset(ctx, 0, sizeof(*ctx));
+}
+
+void mbedtls_lms_public_free(mbedtls_lms_public_t *ctx)
+{
+    mbedtls_platform_zeroize(ctx, sizeof(*ctx));
+}
+
+int mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx,
+                                  const unsigned char *key, size_t key_size)
+{
+    mbedtls_lms_algorithm_type_t type;
+    mbedtls_lmots_algorithm_type_t otstype;
+
+    type = mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMS_TYPE_LEN,
+                                                     key + PUBLIC_KEY_TYPE_OFFSET);
+    if (type != MBEDTLS_LMS_SHA256_M32_H10) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+    ctx->params.type = type;
+
+    if (key_size != MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    otstype = mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMOTS_TYPE_LEN,
+                                                        key + PUBLIC_KEY_OTSTYPE_OFFSET);
+    if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+    ctx->params.otstype = otstype;
+
+    memcpy(ctx->params.I_key_identifier,
+           key + PUBLIC_KEY_I_KEY_ID_OFFSET,
+           MBEDTLS_LMOTS_I_KEY_ID_LEN);
+    memcpy(ctx->T_1_pub_key, key + PUBLIC_KEY_ROOT_NODE_OFFSET,
+           MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type));
+
+    ctx->have_public_key = 1;
+
+    return 0;
+}
+
+int mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx,
+                                  unsigned char *key,
+                                  size_t key_size, size_t *key_len)
+{
+    if (key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) {
+        return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
+    }
+
+    if (!ctx->have_public_key) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    mbedtls_lms_unsigned_int_to_network_bytes(
+        ctx->params.type,
+        MBEDTLS_LMS_TYPE_LEN, key + PUBLIC_KEY_TYPE_OFFSET);
+    mbedtls_lms_unsigned_int_to_network_bytes(ctx->params.otstype,
+                                              MBEDTLS_LMOTS_TYPE_LEN,
+                                              key + PUBLIC_KEY_OTSTYPE_OFFSET);
+    memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET,
+           ctx->params.I_key_identifier,
+           MBEDTLS_LMOTS_I_KEY_ID_LEN);
+    memcpy(key +PUBLIC_KEY_ROOT_NODE_OFFSET,
+           ctx->T_1_pub_key,
+           MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type));
+
+    if (key_len != NULL) {
+        *key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type);
+    }
+
+    return 0;
+}
+
+int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx,
+                       const unsigned char *msg, size_t msg_size,
+                       const unsigned char *sig, size_t sig_size)
+{
+    unsigned int q_leaf_identifier;
+    unsigned char Kc_candidate_ots_pub_key[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
+    unsigned char Tc_candidate_root_node[MBEDTLS_LMS_M_NODE_BYTES_MAX];
+    unsigned int height;
+    unsigned int curr_node_id;
+    unsigned int parent_node_id;
+    const unsigned char *left_node;
+    const unsigned char *right_node;
+    mbedtls_lmots_parameters_t ots_params;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if (!ctx->have_public_key) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    if (ctx->params.type
+        != MBEDTLS_LMS_SHA256_M32_H10) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    if (ctx->params.otstype
+        != MBEDTLS_LMOTS_SHA256_N32_W8) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    if (sig_size != MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) {
+        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
+    }
+
+    if (sig_size < SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) {
+        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
+    }
+
+    if (mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMOTS_TYPE_LEN,
+                                                  sig + SIG_OTS_SIG_OFFSET +
+                                                  MBEDTLS_LMOTS_SIG_TYPE_OFFSET)
+        != MBEDTLS_LMOTS_SHA256_N32_W8) {
+        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
+    }
+
+    if (sig_size < SIG_TYPE_OFFSET(ctx->params.otstype) + MBEDTLS_LMS_TYPE_LEN) {
+        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
+    }
+
+    if (mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMS_TYPE_LEN,
+                                                  sig + SIG_TYPE_OFFSET(ctx->params.otstype))
+        != MBEDTLS_LMS_SHA256_M32_H10) {
+        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
+    }
+
+
+    q_leaf_identifier = mbedtls_lms_network_bytes_to_unsigned_int(
+        MBEDTLS_LMOTS_Q_LEAF_ID_LEN, sig + SIG_Q_LEAF_ID_OFFSET);
+
+    if (q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) {
+        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
+    }
+
+    memcpy(ots_params.I_key_identifier,
+           ctx->params.I_key_identifier,
+           MBEDTLS_LMOTS_I_KEY_ID_LEN);
+    mbedtls_lms_unsigned_int_to_network_bytes(q_leaf_identifier,
+                                              MBEDTLS_LMOTS_Q_LEAF_ID_LEN,
+                                              ots_params.q_leaf_identifier);
+    ots_params.type = ctx->params.otstype;
+
+    ret = mbedtls_lmots_calculate_public_key_candidate(&ots_params,
+                                                       msg,
+                                                       msg_size,
+                                                       sig + SIG_OTS_SIG_OFFSET,
+                                                       MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype),
+                                                       Kc_candidate_ots_pub_key,
+                                                       sizeof(Kc_candidate_ots_pub_key),
+                                                       NULL);
+    if (ret != 0) {
+        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
+    }
+
+    create_merkle_leaf_value(
+        &ctx->params,
+        Kc_candidate_ots_pub_key,
+        MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier,
+        Tc_candidate_root_node);
+
+    curr_node_id = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) +
+                   q_leaf_identifier;
+
+    for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type);
+         height++) {
+        parent_node_id = curr_node_id / 2;
+
+        /* Left/right node ordering matters for the hash */
+        if (curr_node_id & 1) {
+            left_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) +
+                        height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
+            right_node = Tc_candidate_root_node;
+        } else {
+            left_node = Tc_candidate_root_node;
+            right_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) +
+                         height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
+        }
+
+        create_merkle_internal_value(&ctx->params, left_node, right_node,
+                                     parent_node_id, Tc_candidate_root_node);
+
+        curr_node_id /= 2;
+    }
+
+    if (memcmp(Tc_candidate_root_node, ctx->T_1_pub_key,
+               MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type))) {
+        return MBEDTLS_ERR_LMS_VERIFY_FAILED;
+    }
+
+    return 0;
+}
+
+#if defined(MBEDTLS_LMS_PRIVATE)
+
+/* Calculate a full Merkle tree based on a private key. This function
+ * implements RFC8554 section 5.3, and is used to generate a public key (as the
+ * public key is the root node of the Merkle tree).
+ *
+ *  ctx                 The LMS private context, containing a parameter
+ *                      set and private key material consisting of both
+ *                      public and private OTS.
+ *
+ *  tree                The output tree, which is 2^(H + 1) hash outputs.
+ *                      In the case of H=10 we have 2048 tree nodes (of
+ *                      which 1024 of them are leaf nodes). Note that
+ *                      because the Merkle tree root is 1-indexed, the 0
+ *                      index tree node is never used.
+ */
+static int calculate_merkle_tree(const mbedtls_lms_private_t *ctx,
+                                 unsigned char *tree)
+{
+    unsigned int priv_key_idx;
+    unsigned int r_node_idx;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    /* First create the leaf nodes, in ascending order */
+    for (priv_key_idx = 0;
+         priv_key_idx < MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type);
+         priv_key_idx++) {
+        r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + priv_key_idx;
+
+        ret = create_merkle_leaf_value(&ctx->params,
+                                       ctx->ots_public_keys[priv_key_idx].public_key,
+                                       r_node_idx,
+                                       &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES(
+                                                 ctx->params.type)]);
+        if (ret != 0) {
+            return ret;
+        }
+    }
+
+    /* Then the internal nodes, in reverse order so that we can guarantee the
+     * parent has been created */
+    for (r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) - 1;
+         r_node_idx > 0;
+         r_node_idx--) {
+        ret = create_merkle_internal_value(&ctx->params,
+                                           &tree[(r_node_idx * 2) *
+                                                 MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)],
+                                           &tree[(r_node_idx * 2 + 1) *
+                                                 MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)],
+                                           r_node_idx,
+                                           &tree[r_node_idx *
+                                                 MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)]);
+        if (ret != 0) {
+            return ret;
+        }
+    }
+
+    return 0;
+}
+
+/* Calculate a path from a leaf node of the Merkle tree to the root of the tree,
+ * and return the full path. This function implements RFC8554 section 5.4.1, as
+ * the Merkle path is the main component of an LMS signature.
+ *
+ *  ctx                 The LMS private context, containing a parameter
+ *                      set and private key material consisting of both
+ *                      public and private OTS.
+ *
+ *  leaf_node_id        Which leaf node to calculate the path from.
+ *
+ *  path                The output path, which is H hash outputs.
+ */
+static int get_merkle_path(mbedtls_lms_private_t *ctx,
+                           unsigned int leaf_node_id,
+                           unsigned char *path)
+{
+    const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
+    unsigned int curr_node_id = leaf_node_id;
+    unsigned int adjacent_node_id;
+    unsigned char *tree = NULL;
+    unsigned int height;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    tree = mbedtls_calloc(MERKLE_TREE_NODE_AM(ctx->params.type),
+                          node_bytes);
+    if (tree == NULL) {
+        return MBEDTLS_ERR_LMS_ALLOC_FAILED;
+    }
+
+    ret = calculate_merkle_tree(ctx, tree);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type);
+         height++) {
+        adjacent_node_id = curr_node_id ^ 1;
+
+        memcpy(&path[height * node_bytes],
+               &tree[adjacent_node_id * node_bytes], node_bytes);
+
+        curr_node_id >>= 1;
+    }
+
+    ret = 0;
+
+exit:
+    mbedtls_platform_zeroize(tree, node_bytes *
+                             MERKLE_TREE_NODE_AM(ctx->params.type));
+    mbedtls_free(tree);
+
+    return ret;
+}
+
+void mbedtls_lms_private_init(mbedtls_lms_private_t *ctx)
+{
+    memset(ctx, 0, sizeof(*ctx));
+}
+
+void mbedtls_lms_private_free(mbedtls_lms_private_t *ctx)
+{
+    unsigned int idx;
+
+    if (ctx->have_private_key) {
+        if (ctx->ots_private_keys != NULL) {
+            for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
+                mbedtls_lmots_private_free(&ctx->ots_private_keys[idx]);
+            }
+        }
+
+        if (ctx->ots_public_keys != NULL) {
+            for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
+                mbedtls_lmots_public_free(&ctx->ots_public_keys[idx]);
+            }
+        }
+
+        mbedtls_free(ctx->ots_private_keys);
+        mbedtls_free(ctx->ots_public_keys);
+    }
+
+    mbedtls_platform_zeroize(ctx, sizeof(*ctx));
+}
+
+
+int mbedtls_lms_generate_private_key(mbedtls_lms_private_t *ctx,
+                                     mbedtls_lms_algorithm_type_t type,
+                                     mbedtls_lmots_algorithm_type_t otstype,
+                                     int (*f_rng)(void *, unsigned char *, size_t),
+                                     void *p_rng, const unsigned char *seed,
+                                     size_t seed_size)
+{
+    unsigned int idx = 0;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if (type != MBEDTLS_LMS_SHA256_M32_H10) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    if (ctx->have_private_key) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    ctx->params.type = type;
+    ctx->params.otstype = otstype;
+    ctx->have_private_key = 1;
+
+    ret = f_rng(p_rng,
+                ctx->params.I_key_identifier,
+                MBEDTLS_LMOTS_I_KEY_ID_LEN);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    /* Requires a cast to size_t to avoid an implicit cast warning on certain
+     * platforms (particularly Windows) */
+    ctx->ots_private_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type),
+                                           sizeof(*ctx->ots_private_keys));
+    if (ctx->ots_private_keys == NULL) {
+        ret = MBEDTLS_ERR_LMS_ALLOC_FAILED;
+        goto exit;
+    }
+
+    /* Requires a cast to size_t to avoid an implicit cast warning on certain
+     * platforms (particularly Windows) */
+    ctx->ots_public_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type),
+                                          sizeof(*ctx->ots_public_keys));
+    if (ctx->ots_public_keys == NULL) {
+        ret = MBEDTLS_ERR_LMS_ALLOC_FAILED;
+        goto exit;
+    }
+
+    for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
+        mbedtls_lmots_private_init(&ctx->ots_private_keys[idx]);
+        mbedtls_lmots_public_init(&ctx->ots_public_keys[idx]);
+    }
+
+
+    for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) {
+        ret = mbedtls_lmots_generate_private_key(&ctx->ots_private_keys[idx],
+                                                 otstype,
+                                                 ctx->params.I_key_identifier,
+                                                 idx, seed, seed_size);
+        if (ret != 0) {
+            goto exit;
+        }
+
+        ret = mbedtls_lmots_calculate_public_key(&ctx->ots_public_keys[idx],
+                                                 &ctx->ots_private_keys[idx]);
+        if (ret != 0) {
+            goto exit;
+        }
+    }
+
+    ctx->q_next_usable_key = 0;
+
+exit:
+    if (ret != 0) {
+        mbedtls_lms_private_free(ctx);
+    }
+
+    return ret;
+}
+
+int mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx,
+                                     const mbedtls_lms_private_t *priv_ctx)
+{
+    const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(priv_ctx->params.type);
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *tree = NULL;
+
+    if (!priv_ctx->have_private_key) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    if (priv_ctx->params.type
+        != MBEDTLS_LMS_SHA256_M32_H10) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    if (priv_ctx->params.otstype
+        != MBEDTLS_LMOTS_SHA256_N32_W8) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    tree = mbedtls_calloc(MERKLE_TREE_NODE_AM(priv_ctx->params.type),
+                          node_bytes);
+    if (tree == NULL) {
+        return MBEDTLS_ERR_LMS_ALLOC_FAILED;
+    }
+
+    memcpy(&ctx->params, &priv_ctx->params,
+           sizeof(mbedtls_lmots_parameters_t));
+
+    ret = calculate_merkle_tree(priv_ctx, tree);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    /* Root node is always at position 1, due to 1-based indexing */
+    memcpy(ctx->T_1_pub_key, &tree[node_bytes], node_bytes);
+
+    ctx->have_public_key = 1;
+
+    ret = 0;
+
+exit:
+    mbedtls_platform_zeroize(tree, node_bytes *
+                             MERKLE_TREE_NODE_AM(priv_ctx->params.type));
+    mbedtls_free(tree);
+
+    return ret;
+}
+
+
+int mbedtls_lms_sign(mbedtls_lms_private_t *ctx,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng, const unsigned char *msg,
+                     unsigned int msg_size, unsigned char *sig, size_t sig_size,
+                     size_t *sig_len)
+{
+    uint32_t q_leaf_identifier;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if (!ctx->have_private_key) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    if (sig_size < MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) {
+        return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL;
+    }
+
+    if (ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    if (ctx->params.otstype
+        != MBEDTLS_LMOTS_SHA256_N32_W8) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    if (ctx->q_next_usable_key >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) {
+        return MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS;
+    }
+
+
+    q_leaf_identifier = ctx->q_next_usable_key;
+    /* This new value must _always_ be written back to the disk before the
+     * signature is returned.
+     */
+    ctx->q_next_usable_key += 1;
+
+    if (MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)
+        < SIG_OTS_SIG_OFFSET) {
+        return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
+    }
+
+    ret = mbedtls_lmots_sign(&ctx->ots_private_keys[q_leaf_identifier],
+                             f_rng,
+                             p_rng,
+                             msg,
+                             msg_size,
+                             sig + SIG_OTS_SIG_OFFSET,
+                             MBEDTLS_LMS_SIG_LEN(ctx->params.type,
+                                                 ctx->params.otstype) - SIG_OTS_SIG_OFFSET,
+                             NULL);
+    if (ret != 0) {
+        return ret;
+    }
+
+    mbedtls_lms_unsigned_int_to_network_bytes(ctx->params.type,
+                                              MBEDTLS_LMS_TYPE_LEN,
+                                              sig + SIG_TYPE_OFFSET(ctx->params.otstype));
+    mbedtls_lms_unsigned_int_to_network_bytes(q_leaf_identifier,
+                                              MBEDTLS_LMOTS_Q_LEAF_ID_LEN,
+                                              sig + SIG_Q_LEAF_ID_OFFSET);
+
+    ret = get_merkle_path(ctx,
+                          MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier,
+                          sig + SIG_PATH_OFFSET(ctx->params.otstype));
+    if (ret != 0) {
+        return ret;
+    }
+
+    if (sig_len != NULL) {
+        *sig_len = MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype);
+    }
+
+
+    return 0;
+}
+
+#endif /* defined(MBEDTLS_LMS_PRIVATE) */
+#endif /* defined(MBEDTLS_LMS_C) */
diff --git a/lib/libmbedtls/mbedtls/library/md.c b/lib/libmbedtls/mbedtls/library/md.c
index 341a9cf..89295de 100644
--- a/lib/libmbedtls/mbedtls/library/md.c
+++ b/lib/libmbedtls/mbedtls/library/md.c
@@ -23,54 +23,49 @@
 
 #include "common.h"
 
-#if defined(MBEDTLS_MD_C)
+/*
+ * Availability of functions in this module is controlled by two
+ * feature macros:
+ * - MBEDTLS_MD_C enables the whole module;
+ * - MBEDTLS_MD_LIGHT enables only functions for hashing and accessing
+ * most hash metadata (everything except string names); is it
+ * automatically set whenever MBEDTLS_MD_C is defined.
+ *
+ * In this file, functions from MD_LIGHT are at the top, MD_C at the end.
+ *
+ * In the future we may want to change the contract of some functions
+ * (behaviour with NULL arguments) depending on whether MD_C is defined or
+ * only MD_LIGHT. Also, the exact scope of MD_LIGHT might vary.
+ *
+ * For these reasons, we're keeping MD_LIGHT internal for now.
+ */
+#if defined(MBEDTLS_MD_LIGHT)
 
 #include "mbedtls/md.h"
-#include "mbedtls/md_internal.h"
+#include "md_wrap.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 
-#include "mbedtls/md2.h"
-#include "mbedtls/md4.h"
 #include "mbedtls/md5.h"
 #include "mbedtls/ripemd160.h"
 #include "mbedtls/sha1.h"
 #include "mbedtls/sha256.h"
 #include "mbedtls/sha512.h"
 
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free       free
+#if defined(MBEDTLS_MD_SOME_PSA)
+#include <psa/crypto.h>
+#include "psa_crypto_core.h"
 #endif
 
+#include "mbedtls/platform.h"
+
 #include <string.h>
 
 #if defined(MBEDTLS_FS_IO)
 #include <stdio.h>
 #endif
 
-#if defined(MBEDTLS_MD2_C)
-const mbedtls_md_info_t mbedtls_md2_info = {
-    "MD2",
-    MBEDTLS_MD_MD2,
-    16,
-    16,
-};
-#endif
-
-#if defined(MBEDTLS_MD4_C)
-const mbedtls_md_info_t mbedtls_md4_info = {
-    "MD4",
-    MBEDTLS_MD_MD4,
-    16,
-    64,
-};
-#endif
-
-#if defined(MBEDTLS_MD5_C)
+#if defined(MBEDTLS_MD_CAN_MD5)
 const mbedtls_md_info_t mbedtls_md5_info = {
     "MD5",
     MBEDTLS_MD_MD5,
@@ -79,7 +74,7 @@
 };
 #endif
 
-#if defined(MBEDTLS_RIPEMD160_C)
+#if defined(MBEDTLS_MD_CAN_RIPEMD160)
 const mbedtls_md_info_t mbedtls_ripemd160_info = {
     "RIPEMD160",
     MBEDTLS_MD_RIPEMD160,
@@ -88,7 +83,7 @@
 };
 #endif
 
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_MD_CAN_SHA1)
 const mbedtls_md_info_t mbedtls_sha1_info = {
     "SHA1",
     MBEDTLS_MD_SHA1,
@@ -97,14 +92,16 @@
 };
 #endif
 
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_MD_CAN_SHA224)
 const mbedtls_md_info_t mbedtls_sha224_info = {
     "SHA224",
     MBEDTLS_MD_SHA224,
     28,
     64,
 };
+#endif
 
+#if defined(MBEDTLS_MD_CAN_SHA256)
 const mbedtls_md_info_t mbedtls_sha256_info = {
     "SHA256",
     MBEDTLS_MD_SHA256,
@@ -113,8 +110,7 @@
 };
 #endif
 
-#if defined(MBEDTLS_SHA512_C)
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
+#if defined(MBEDTLS_MD_CAN_SHA384)
 const mbedtls_md_info_t mbedtls_sha384_info = {
     "SHA384",
     MBEDTLS_MD_SHA384,
@@ -123,6 +119,7 @@
 };
 #endif
 
+#if defined(MBEDTLS_MD_CAN_SHA512)
 const mbedtls_md_info_t mbedtls_sha512_info = {
     "SHA512",
     MBEDTLS_MD_SHA512,
@@ -131,535 +128,651 @@
 };
 #endif
 
-/*
- * Reminder: update profiles in x509_crt.c when adding a new hash!
- */
-static const int supported_digests[] = {
-
-#if defined(MBEDTLS_SHA512_C)
-        MBEDTLS_MD_SHA512,
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
-        MBEDTLS_MD_SHA384,
-#endif
-#endif
-
-#if defined(MBEDTLS_SHA256_C)
-        MBEDTLS_MD_SHA256,
-        MBEDTLS_MD_SHA224,
-#endif
-
-#if defined(MBEDTLS_SHA1_C)
-        MBEDTLS_MD_SHA1,
-#endif
-
-#if defined(MBEDTLS_RIPEMD160_C)
-        MBEDTLS_MD_RIPEMD160,
-#endif
-
-#if defined(MBEDTLS_MD5_C)
-        MBEDTLS_MD_MD5,
-#endif
-
-#if defined(MBEDTLS_MD4_C)
-        MBEDTLS_MD_MD4,
-#endif
-
-#if defined(MBEDTLS_MD2_C)
-        MBEDTLS_MD_MD2,
-#endif
-
-        MBEDTLS_MD_NONE
-};
-
-const int *mbedtls_md_list( void )
+const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type)
 {
-    return( supported_digests );
-}
-
-const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name )
-{
-    if( NULL == md_name )
-        return( NULL );
-
-    /* Get the appropriate digest information */
-#if defined(MBEDTLS_MD2_C)
-    if( !strcmp( "MD2", md_name ) )
-        return mbedtls_md_info_from_type( MBEDTLS_MD_MD2 );
-#endif
-#if defined(MBEDTLS_MD4_C)
-    if( !strcmp( "MD4", md_name ) )
-        return mbedtls_md_info_from_type( MBEDTLS_MD_MD4 );
-#endif
-#if defined(MBEDTLS_MD5_C)
-    if( !strcmp( "MD5", md_name ) )
-        return mbedtls_md_info_from_type( MBEDTLS_MD_MD5 );
-#endif
-#if defined(MBEDTLS_RIPEMD160_C)
-    if( !strcmp( "RIPEMD160", md_name ) )
-        return mbedtls_md_info_from_type( MBEDTLS_MD_RIPEMD160 );
-#endif
-#if defined(MBEDTLS_SHA1_C)
-    if( !strcmp( "SHA1", md_name ) || !strcmp( "SHA", md_name ) )
-        return mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
-#endif
-#if defined(MBEDTLS_SHA256_C)
-    if( !strcmp( "SHA224", md_name ) )
-        return mbedtls_md_info_from_type( MBEDTLS_MD_SHA224 );
-    if( !strcmp( "SHA256", md_name ) )
-        return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 );
-#endif
-#if defined(MBEDTLS_SHA512_C)
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
-    if( !strcmp( "SHA384", md_name ) )
-        return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 );
-#endif
-    if( !strcmp( "SHA512", md_name ) )
-        return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 );
-#endif
-    return( NULL );
-}
-
-const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type )
-{
-    switch( md_type )
-    {
-#if defined(MBEDTLS_MD2_C)
-        case MBEDTLS_MD_MD2:
-            return( &mbedtls_md2_info );
-#endif
-#if defined(MBEDTLS_MD4_C)
-        case MBEDTLS_MD_MD4:
-            return( &mbedtls_md4_info );
-#endif
-#if defined(MBEDTLS_MD5_C)
+    switch (md_type) {
+#if defined(MBEDTLS_MD_CAN_MD5)
         case MBEDTLS_MD_MD5:
-            return( &mbedtls_md5_info );
+            return &mbedtls_md5_info;
 #endif
-#if defined(MBEDTLS_RIPEMD160_C)
+#if defined(MBEDTLS_MD_CAN_RIPEMD160)
         case MBEDTLS_MD_RIPEMD160:
-            return( &mbedtls_ripemd160_info );
+            return &mbedtls_ripemd160_info;
 #endif
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_MD_CAN_SHA1)
         case MBEDTLS_MD_SHA1:
-            return( &mbedtls_sha1_info );
+            return &mbedtls_sha1_info;
 #endif
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_MD_CAN_SHA224)
         case MBEDTLS_MD_SHA224:
-            return( &mbedtls_sha224_info );
+            return &mbedtls_sha224_info;
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA256)
         case MBEDTLS_MD_SHA256:
-            return( &mbedtls_sha256_info );
+            return &mbedtls_sha256_info;
 #endif
-#if defined(MBEDTLS_SHA512_C)
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
+#if defined(MBEDTLS_MD_CAN_SHA384)
         case MBEDTLS_MD_SHA384:
-            return( &mbedtls_sha384_info );
+            return &mbedtls_sha384_info;
 #endif
+#if defined(MBEDTLS_MD_CAN_SHA512)
         case MBEDTLS_MD_SHA512:
-            return( &mbedtls_sha512_info );
+            return &mbedtls_sha512_info;
 #endif
         default:
-            return( NULL );
+            return NULL;
     }
 }
 
-void mbedtls_md_init( mbedtls_md_context_t *ctx )
+#if defined(MBEDTLS_MD_SOME_PSA)
+static psa_algorithm_t psa_alg_of_md(const mbedtls_md_info_t *info)
 {
-    memset( ctx, 0, sizeof( mbedtls_md_context_t ) );
+    switch (info->type) {
+#if defined(MBEDTLS_MD_MD5_VIA_PSA)
+        case MBEDTLS_MD_MD5:
+            return PSA_ALG_MD5;
+#endif
+#if defined(MBEDTLS_MD_RIPEMD160_VIA_PSA)
+        case MBEDTLS_MD_RIPEMD160:
+            return PSA_ALG_RIPEMD160;
+#endif
+#if defined(MBEDTLS_MD_SHA1_VIA_PSA)
+        case MBEDTLS_MD_SHA1:
+            return PSA_ALG_SHA_1;
+#endif
+#if defined(MBEDTLS_MD_SHA224_VIA_PSA)
+        case MBEDTLS_MD_SHA224:
+            return PSA_ALG_SHA_224;
+#endif
+#if defined(MBEDTLS_MD_SHA256_VIA_PSA)
+        case MBEDTLS_MD_SHA256:
+            return PSA_ALG_SHA_256;
+#endif
+#if defined(MBEDTLS_MD_SHA384_VIA_PSA)
+        case MBEDTLS_MD_SHA384:
+            return PSA_ALG_SHA_384;
+#endif
+#if defined(MBEDTLS_MD_SHA512_VIA_PSA)
+        case MBEDTLS_MD_SHA512:
+            return PSA_ALG_SHA_512;
+#endif
+        default:
+            return PSA_ALG_NONE;
+    }
 }
 
-void mbedtls_md_free( mbedtls_md_context_t *ctx )
+static int md_can_use_psa(const mbedtls_md_info_t *info)
 {
-    if( ctx == NULL || ctx->md_info == NULL )
-        return;
+    psa_algorithm_t alg = psa_alg_of_md(info);
+    if (alg == PSA_ALG_NONE) {
+        return 0;
+    }
 
-    if( ctx->md_ctx != NULL )
-    {
-        switch( ctx->md_info->type )
-        {
-#if defined(MBEDTLS_MD2_C)
-            case MBEDTLS_MD_MD2:
-                mbedtls_md2_free( ctx->md_ctx );
-                break;
+    return psa_can_do_hash(alg);
+}
+
+static int mbedtls_md_error_from_psa(psa_status_t status)
+{
+    switch (status) {
+        case PSA_SUCCESS:
+            return 0;
+        case PSA_ERROR_NOT_SUPPORTED:
+            return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
+        case PSA_ERROR_INSUFFICIENT_MEMORY:
+            return MBEDTLS_ERR_MD_ALLOC_FAILED;
+        default:
+            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+    }
+}
+#endif /* MBEDTLS_MD_SOME_PSA */
+
+void mbedtls_md_init(mbedtls_md_context_t *ctx)
+{
+    /* Note: this sets engine (if present) to MBEDTLS_MD_ENGINE_LEGACY */
+    memset(ctx, 0, sizeof(mbedtls_md_context_t));
+}
+
+void mbedtls_md_free(mbedtls_md_context_t *ctx)
+{
+    if (ctx == NULL || ctx->md_info == NULL) {
+        return;
+    }
+
+    if (ctx->md_ctx != NULL) {
+#if defined(MBEDTLS_MD_SOME_PSA)
+        if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) {
+            psa_hash_abort(ctx->md_ctx);
+        } else
 #endif
-#if defined(MBEDTLS_MD4_C)
-            case MBEDTLS_MD_MD4:
-                mbedtls_md4_free( ctx->md_ctx );
-                break;
-#endif
+        switch (ctx->md_info->type) {
 #if defined(MBEDTLS_MD5_C)
             case MBEDTLS_MD_MD5:
-                mbedtls_md5_free( ctx->md_ctx );
+                mbedtls_md5_free(ctx->md_ctx);
                 break;
 #endif
 #if defined(MBEDTLS_RIPEMD160_C)
             case MBEDTLS_MD_RIPEMD160:
-                mbedtls_ripemd160_free( ctx->md_ctx );
+                mbedtls_ripemd160_free(ctx->md_ctx);
                 break;
 #endif
 #if defined(MBEDTLS_SHA1_C)
             case MBEDTLS_MD_SHA1:
-                mbedtls_sha1_free( ctx->md_ctx );
+                mbedtls_sha1_free(ctx->md_ctx);
+                break;
+#endif
+#if defined(MBEDTLS_SHA224_C)
+            case MBEDTLS_MD_SHA224:
+                mbedtls_sha256_free(ctx->md_ctx);
                 break;
 #endif
 #if defined(MBEDTLS_SHA256_C)
-            case MBEDTLS_MD_SHA224:
             case MBEDTLS_MD_SHA256:
-                mbedtls_sha256_free( ctx->md_ctx );
+                mbedtls_sha256_free(ctx->md_ctx);
+                break;
+#endif
+#if defined(MBEDTLS_SHA384_C)
+            case MBEDTLS_MD_SHA384:
+                mbedtls_sha512_free(ctx->md_ctx);
                 break;
 #endif
 #if defined(MBEDTLS_SHA512_C)
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
-            case MBEDTLS_MD_SHA384:
-#endif
             case MBEDTLS_MD_SHA512:
-                mbedtls_sha512_free( ctx->md_ctx );
+                mbedtls_sha512_free(ctx->md_ctx);
                 break;
 #endif
             default:
                 /* Shouldn't happen */
                 break;
         }
-        mbedtls_free( ctx->md_ctx );
+        mbedtls_free(ctx->md_ctx);
     }
 
-    if( ctx->hmac_ctx != NULL )
-    {
-        mbedtls_platform_zeroize( ctx->hmac_ctx,
-                                  2 * ctx->md_info->block_size );
-        mbedtls_free( ctx->hmac_ctx );
+#if defined(MBEDTLS_MD_C)
+    if (ctx->hmac_ctx != NULL) {
+        mbedtls_platform_zeroize(ctx->hmac_ctx,
+                                 2 * ctx->md_info->block_size);
+        mbedtls_free(ctx->hmac_ctx);
     }
+#endif
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md_context_t ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md_context_t));
 }
 
-int mbedtls_md_clone( mbedtls_md_context_t *dst,
-                      const mbedtls_md_context_t *src )
+int mbedtls_md_clone(mbedtls_md_context_t *dst,
+                     const mbedtls_md_context_t *src)
 {
-    if( dst == NULL || dst->md_info == NULL ||
+    if (dst == NULL || dst->md_info == NULL ||
         src == NULL || src->md_info == NULL ||
-        dst->md_info != src->md_info )
-    {
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+        dst->md_info != src->md_info) {
+        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
     }
 
-    switch( src->md_info->type )
-    {
-#if defined(MBEDTLS_MD2_C)
-        case MBEDTLS_MD_MD2:
-            mbedtls_md2_clone( dst->md_ctx, src->md_ctx );
-            break;
+#if defined(MBEDTLS_MD_SOME_PSA)
+    if (src->engine != dst->engine) {
+        /* This can happen with src set to legacy because PSA wasn't ready
+         * yet, and dst to PSA because it became ready in the meantime.
+         * We currently don't support that case (we'd need to re-allocate
+         * md_ctx to the size of the appropriate MD context). */
+        return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
+    }
+
+    if (src->engine == MBEDTLS_MD_ENGINE_PSA) {
+        psa_status_t status = psa_hash_clone(src->md_ctx, dst->md_ctx);
+        return mbedtls_md_error_from_psa(status);
+    }
 #endif
-#if defined(MBEDTLS_MD4_C)
-        case MBEDTLS_MD_MD4:
-            mbedtls_md4_clone( dst->md_ctx, src->md_ctx );
-            break;
-#endif
+
+    switch (src->md_info->type) {
 #if defined(MBEDTLS_MD5_C)
         case MBEDTLS_MD_MD5:
-            mbedtls_md5_clone( dst->md_ctx, src->md_ctx );
+            mbedtls_md5_clone(dst->md_ctx, src->md_ctx);
             break;
 #endif
 #if defined(MBEDTLS_RIPEMD160_C)
         case MBEDTLS_MD_RIPEMD160:
-            mbedtls_ripemd160_clone( dst->md_ctx, src->md_ctx );
+            mbedtls_ripemd160_clone(dst->md_ctx, src->md_ctx);
             break;
 #endif
 #if defined(MBEDTLS_SHA1_C)
         case MBEDTLS_MD_SHA1:
-            mbedtls_sha1_clone( dst->md_ctx, src->md_ctx );
+            mbedtls_sha1_clone(dst->md_ctx, src->md_ctx);
+            break;
+#endif
+#if defined(MBEDTLS_SHA224_C)
+        case MBEDTLS_MD_SHA224:
+            mbedtls_sha256_clone(dst->md_ctx, src->md_ctx);
             break;
 #endif
 #if defined(MBEDTLS_SHA256_C)
-        case MBEDTLS_MD_SHA224:
         case MBEDTLS_MD_SHA256:
-            mbedtls_sha256_clone( dst->md_ctx, src->md_ctx );
+            mbedtls_sha256_clone(dst->md_ctx, src->md_ctx);
+            break;
+#endif
+#if defined(MBEDTLS_SHA384_C)
+        case MBEDTLS_MD_SHA384:
+            mbedtls_sha512_clone(dst->md_ctx, src->md_ctx);
             break;
 #endif
 #if defined(MBEDTLS_SHA512_C)
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
-        case MBEDTLS_MD_SHA384:
-#endif
         case MBEDTLS_MD_SHA512:
-            mbedtls_sha512_clone( dst->md_ctx, src->md_ctx );
+            mbedtls_sha512_clone(dst->md_ctx, src->md_ctx);
             break;
 #endif
         default:
-            return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+            return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
     }
 
-    if( dst->hmac_ctx != NULL && src->hmac_ctx != NULL )
-        memcpy( dst->hmac_ctx, src->hmac_ctx, 2 * src->md_info->block_size );
+    if (dst->hmac_ctx != NULL && src->hmac_ctx != NULL)
+        memcpy(dst->hmac_ctx, src->hmac_ctx, 2 * src->md_info->block_size);
 
-    return( 0 );
+    return 0;
 }
 
-#if ! defined(MBEDTLS_DEPRECATED_REMOVED)
-int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info )
-{
-    return mbedtls_md_setup( ctx, md_info, 1 );
-}
-#endif
-
-#define ALLOC( type )                                                   \
+#define ALLOC(type)                                                   \
     do {                                                                \
-        ctx->md_ctx = mbedtls_calloc( 1, sizeof( mbedtls_##type##_context ) ); \
-        if( ctx->md_ctx == NULL )                                       \
-            return( MBEDTLS_ERR_MD_ALLOC_FAILED );                      \
-        mbedtls_##type##_init( ctx->md_ctx );                           \
+        ctx->md_ctx = mbedtls_calloc(1, sizeof(mbedtls_##type##_context)); \
+        if (ctx->md_ctx == NULL)                                       \
+        return MBEDTLS_ERR_MD_ALLOC_FAILED;                      \
+        mbedtls_##type##_init(ctx->md_ctx);                           \
     }                                                                   \
-    while( 0 )
+    while (0)
 
-int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac )
+int mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac)
 {
-    if( md_info == NULL || ctx == NULL )
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    if (md_info == NULL || ctx == NULL) {
+        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
+    }
 
     ctx->md_info = md_info;
     ctx->md_ctx = NULL;
+#if defined(MBEDTLS_MD_C)
     ctx->hmac_ctx = NULL;
+#else
+    if (hmac != 0) {
+        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
+    }
+#endif
 
-    switch( md_info->type )
-    {
-#if defined(MBEDTLS_MD2_C)
-        case MBEDTLS_MD_MD2:
-            ALLOC( md2 );
-            break;
+#if defined(MBEDTLS_MD_SOME_PSA)
+    if (md_can_use_psa(ctx->md_info)) {
+        ctx->md_ctx = mbedtls_calloc(1, sizeof(psa_hash_operation_t));
+        if (ctx->md_ctx == NULL) {
+            return MBEDTLS_ERR_MD_ALLOC_FAILED;
+        }
+        ctx->engine = MBEDTLS_MD_ENGINE_PSA;
+    } else
 #endif
-#if defined(MBEDTLS_MD4_C)
-        case MBEDTLS_MD_MD4:
-            ALLOC( md4 );
-            break;
-#endif
+    switch (md_info->type) {
 #if defined(MBEDTLS_MD5_C)
         case MBEDTLS_MD_MD5:
-            ALLOC( md5 );
+            ALLOC(md5);
             break;
 #endif
 #if defined(MBEDTLS_RIPEMD160_C)
         case MBEDTLS_MD_RIPEMD160:
-            ALLOC( ripemd160 );
+            ALLOC(ripemd160);
             break;
 #endif
 #if defined(MBEDTLS_SHA1_C)
         case MBEDTLS_MD_SHA1:
-            ALLOC( sha1 );
+            ALLOC(sha1);
+            break;
+#endif
+#if defined(MBEDTLS_SHA224_C)
+        case MBEDTLS_MD_SHA224:
+            ALLOC(sha256);
             break;
 #endif
 #if defined(MBEDTLS_SHA256_C)
-        case MBEDTLS_MD_SHA224:
         case MBEDTLS_MD_SHA256:
-            ALLOC( sha256 );
+            ALLOC(sha256);
+            break;
+#endif
+#if defined(MBEDTLS_SHA384_C)
+        case MBEDTLS_MD_SHA384:
+            ALLOC(sha512);
             break;
 #endif
 #if defined(MBEDTLS_SHA512_C)
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
-        case MBEDTLS_MD_SHA384:
-#endif
         case MBEDTLS_MD_SHA512:
-            ALLOC( sha512 );
+            ALLOC(sha512);
             break;
 #endif
         default:
-            return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+            return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
     }
 
-    if( hmac != 0 )
-    {
-        ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size );
-        if( ctx->hmac_ctx == NULL )
-        {
-            mbedtls_md_free( ctx );
-            return( MBEDTLS_ERR_MD_ALLOC_FAILED );
+#if defined(MBEDTLS_MD_C)
+    if (hmac != 0) {
+        ctx->hmac_ctx = mbedtls_calloc(2, md_info->block_size);
+        if (ctx->hmac_ctx == NULL) {
+            mbedtls_md_free(ctx);
+            return MBEDTLS_ERR_MD_ALLOC_FAILED;
         }
     }
+#endif
 
-    return( 0 );
+    return 0;
 }
 #undef ALLOC
 
-int mbedtls_md_starts( mbedtls_md_context_t *ctx )
+int mbedtls_md_starts(mbedtls_md_context_t *ctx)
 {
-    if( ctx == NULL || ctx->md_info == NULL )
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    if (ctx == NULL || ctx->md_info == NULL) {
+        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
+    }
 
-    switch( ctx->md_info->type )
-    {
-#if defined(MBEDTLS_MD2_C)
-        case MBEDTLS_MD_MD2:
-            return( mbedtls_md2_starts_ret( ctx->md_ctx ) );
+#if defined(MBEDTLS_MD_SOME_PSA)
+    if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) {
+        psa_algorithm_t alg = psa_alg_of_md(ctx->md_info);
+        psa_hash_abort(ctx->md_ctx);
+        psa_status_t status = psa_hash_setup(ctx->md_ctx, alg);
+        return mbedtls_md_error_from_psa(status);
+    }
 #endif
-#if defined(MBEDTLS_MD4_C)
-        case MBEDTLS_MD_MD4:
-            return( mbedtls_md4_starts_ret( ctx->md_ctx ) );
-#endif
+
+    switch (ctx->md_info->type) {
 #if defined(MBEDTLS_MD5_C)
         case MBEDTLS_MD_MD5:
-            return( mbedtls_md5_starts_ret( ctx->md_ctx ) );
+            return mbedtls_md5_starts(ctx->md_ctx);
 #endif
 #if defined(MBEDTLS_RIPEMD160_C)
         case MBEDTLS_MD_RIPEMD160:
-            return( mbedtls_ripemd160_starts_ret( ctx->md_ctx ) );
+            return mbedtls_ripemd160_starts(ctx->md_ctx);
 #endif
 #if defined(MBEDTLS_SHA1_C)
         case MBEDTLS_MD_SHA1:
-            return( mbedtls_sha1_starts_ret( ctx->md_ctx ) );
+            return mbedtls_sha1_starts(ctx->md_ctx);
+#endif
+#if defined(MBEDTLS_SHA224_C)
+        case MBEDTLS_MD_SHA224:
+            return mbedtls_sha256_starts(ctx->md_ctx, 1);
 #endif
 #if defined(MBEDTLS_SHA256_C)
-        case MBEDTLS_MD_SHA224:
-            return( mbedtls_sha256_starts_ret( ctx->md_ctx, 1 ) );
         case MBEDTLS_MD_SHA256:
-            return( mbedtls_sha256_starts_ret( ctx->md_ctx, 0 ) );
+            return mbedtls_sha256_starts(ctx->md_ctx, 0);
+#endif
+#if defined(MBEDTLS_SHA384_C)
+        case MBEDTLS_MD_SHA384:
+            return mbedtls_sha512_starts(ctx->md_ctx, 1);
 #endif
 #if defined(MBEDTLS_SHA512_C)
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
-        case MBEDTLS_MD_SHA384:
-            return( mbedtls_sha512_starts_ret( ctx->md_ctx, 1 ) );
-#endif
         case MBEDTLS_MD_SHA512:
-            return( mbedtls_sha512_starts_ret( ctx->md_ctx, 0 ) );
+            return mbedtls_sha512_starts(ctx->md_ctx, 0);
 #endif
         default:
-            return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+            return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
     }
 }
 
-int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen )
+int mbedtls_md_update(mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen)
 {
-    if( ctx == NULL || ctx->md_info == NULL )
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    if (ctx == NULL || ctx->md_info == NULL) {
+        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
+    }
 
-    switch( ctx->md_info->type )
-    {
-#if defined(MBEDTLS_MD2_C)
-        case MBEDTLS_MD_MD2:
-            return( mbedtls_md2_update_ret( ctx->md_ctx, input, ilen ) );
+#if defined(MBEDTLS_MD_SOME_PSA)
+    if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) {
+        psa_status_t status = psa_hash_update(ctx->md_ctx, input, ilen);
+        return mbedtls_md_error_from_psa(status);
+    }
 #endif
-#if defined(MBEDTLS_MD4_C)
-        case MBEDTLS_MD_MD4:
-            return( mbedtls_md4_update_ret( ctx->md_ctx, input, ilen ) );
-#endif
+
+    switch (ctx->md_info->type) {
 #if defined(MBEDTLS_MD5_C)
         case MBEDTLS_MD_MD5:
-            return( mbedtls_md5_update_ret( ctx->md_ctx, input, ilen ) );
+            return mbedtls_md5_update(ctx->md_ctx, input, ilen);
 #endif
 #if defined(MBEDTLS_RIPEMD160_C)
         case MBEDTLS_MD_RIPEMD160:
-            return( mbedtls_ripemd160_update_ret( ctx->md_ctx, input, ilen ) );
+            return mbedtls_ripemd160_update(ctx->md_ctx, input, ilen);
 #endif
 #if defined(MBEDTLS_SHA1_C)
         case MBEDTLS_MD_SHA1:
-            return( mbedtls_sha1_update_ret( ctx->md_ctx, input, ilen ) );
+            return mbedtls_sha1_update(ctx->md_ctx, input, ilen);
+#endif
+#if defined(MBEDTLS_SHA224_C)
+        case MBEDTLS_MD_SHA224:
+            return mbedtls_sha256_update(ctx->md_ctx, input, ilen);
 #endif
 #if defined(MBEDTLS_SHA256_C)
-        case MBEDTLS_MD_SHA224:
         case MBEDTLS_MD_SHA256:
-            return( mbedtls_sha256_update_ret( ctx->md_ctx, input, ilen ) );
+            return mbedtls_sha256_update(ctx->md_ctx, input, ilen);
+#endif
+#if defined(MBEDTLS_SHA384_C)
+        case MBEDTLS_MD_SHA384:
+            return mbedtls_sha512_update(ctx->md_ctx, input, ilen);
 #endif
 #if defined(MBEDTLS_SHA512_C)
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
-        case MBEDTLS_MD_SHA384:
-#endif
         case MBEDTLS_MD_SHA512:
-            return( mbedtls_sha512_update_ret( ctx->md_ctx, input, ilen ) );
+            return mbedtls_sha512_update(ctx->md_ctx, input, ilen);
 #endif
         default:
-            return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+            return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
     }
 }
 
-int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output )
+int mbedtls_md_finish(mbedtls_md_context_t *ctx, unsigned char *output)
 {
-    if( ctx == NULL || ctx->md_info == NULL )
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    if (ctx == NULL || ctx->md_info == NULL) {
+        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
+    }
 
-    switch( ctx->md_info->type )
-    {
-#if defined(MBEDTLS_MD2_C)
-        case MBEDTLS_MD_MD2:
-            return( mbedtls_md2_finish_ret( ctx->md_ctx, output ) );
+#if defined(MBEDTLS_MD_SOME_PSA)
+    if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) {
+        size_t size = ctx->md_info->size;
+        psa_status_t status = psa_hash_finish(ctx->md_ctx,
+                                              output, size, &size);
+        return mbedtls_md_error_from_psa(status);
+    }
 #endif
-#if defined(MBEDTLS_MD4_C)
-        case MBEDTLS_MD_MD4:
-            return( mbedtls_md4_finish_ret( ctx->md_ctx, output ) );
-#endif
+
+    switch (ctx->md_info->type) {
 #if defined(MBEDTLS_MD5_C)
         case MBEDTLS_MD_MD5:
-            return( mbedtls_md5_finish_ret( ctx->md_ctx, output ) );
+            return mbedtls_md5_finish(ctx->md_ctx, output);
 #endif
 #if defined(MBEDTLS_RIPEMD160_C)
         case MBEDTLS_MD_RIPEMD160:
-            return( mbedtls_ripemd160_finish_ret( ctx->md_ctx, output ) );
+            return mbedtls_ripemd160_finish(ctx->md_ctx, output);
 #endif
 #if defined(MBEDTLS_SHA1_C)
         case MBEDTLS_MD_SHA1:
-            return( mbedtls_sha1_finish_ret( ctx->md_ctx, output ) );
+            return mbedtls_sha1_finish(ctx->md_ctx, output);
+#endif
+#if defined(MBEDTLS_SHA224_C)
+        case MBEDTLS_MD_SHA224:
+            return mbedtls_sha256_finish(ctx->md_ctx, output);
 #endif
 #if defined(MBEDTLS_SHA256_C)
-        case MBEDTLS_MD_SHA224:
         case MBEDTLS_MD_SHA256:
-            return( mbedtls_sha256_finish_ret( ctx->md_ctx, output ) );
+            return mbedtls_sha256_finish(ctx->md_ctx, output);
+#endif
+#if defined(MBEDTLS_SHA384_C)
+        case MBEDTLS_MD_SHA384:
+            return mbedtls_sha512_finish(ctx->md_ctx, output);
 #endif
 #if defined(MBEDTLS_SHA512_C)
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
-        case MBEDTLS_MD_SHA384:
-#endif
         case MBEDTLS_MD_SHA512:
-            return( mbedtls_sha512_finish_ret( ctx->md_ctx, output ) );
+            return mbedtls_sha512_finish(ctx->md_ctx, output);
 #endif
         default:
-            return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+            return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
     }
 }
 
-int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen,
-            unsigned char *output )
+int mbedtls_md(const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen,
+               unsigned char *output)
 {
-    if( md_info == NULL )
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    if (md_info == NULL) {
+        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
+    }
 
-    switch( md_info->type )
-    {
-#if defined(MBEDTLS_MD2_C)
-        case MBEDTLS_MD_MD2:
-            return( mbedtls_md2_ret( input, ilen, output ) );
+#if defined(MBEDTLS_MD_SOME_PSA)
+    if (md_can_use_psa(md_info)) {
+        size_t size = md_info->size;
+        psa_status_t status = psa_hash_compute(psa_alg_of_md(md_info),
+                                               input, ilen,
+                                               output, size, &size);
+        return mbedtls_md_error_from_psa(status);
+    }
 #endif
-#if defined(MBEDTLS_MD4_C)
-        case MBEDTLS_MD_MD4:
-            return( mbedtls_md4_ret( input, ilen, output ) );
-#endif
+
+    switch (md_info->type) {
 #if defined(MBEDTLS_MD5_C)
         case MBEDTLS_MD_MD5:
-            return( mbedtls_md5_ret( input, ilen, output ) );
+            return mbedtls_md5(input, ilen, output);
 #endif
 #if defined(MBEDTLS_RIPEMD160_C)
         case MBEDTLS_MD_RIPEMD160:
-            return( mbedtls_ripemd160_ret( input, ilen, output ) );
+            return mbedtls_ripemd160(input, ilen, output);
 #endif
 #if defined(MBEDTLS_SHA1_C)
         case MBEDTLS_MD_SHA1:
-            return( mbedtls_sha1_ret( input, ilen, output ) );
+            return mbedtls_sha1(input, ilen, output);
+#endif
+#if defined(MBEDTLS_SHA224_C)
+        case MBEDTLS_MD_SHA224:
+            return mbedtls_sha256(input, ilen, output, 1);
 #endif
 #if defined(MBEDTLS_SHA256_C)
-        case MBEDTLS_MD_SHA224:
-            return( mbedtls_sha256_ret( input, ilen, output, 1 ) );
         case MBEDTLS_MD_SHA256:
-            return( mbedtls_sha256_ret( input, ilen, output, 0 ) );
+            return mbedtls_sha256(input, ilen, output, 0);
+#endif
+#if defined(MBEDTLS_SHA384_C)
+        case MBEDTLS_MD_SHA384:
+            return mbedtls_sha512(input, ilen, output, 1);
 #endif
 #if defined(MBEDTLS_SHA512_C)
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
-        case MBEDTLS_MD_SHA384:
-            return( mbedtls_sha512_ret( input, ilen, output, 1 ) );
-#endif
         case MBEDTLS_MD_SHA512:
-            return( mbedtls_sha512_ret( input, ilen, output, 0 ) );
+            return mbedtls_sha512(input, ilen, output, 0);
 #endif
         default:
-            return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+            return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
     }
 }
 
+unsigned char mbedtls_md_get_size(const mbedtls_md_info_t *md_info)
+{
+    if (md_info == NULL) {
+        return 0;
+    }
+
+    return md_info->size;
+}
+
+mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info)
+{
+    if (md_info == NULL) {
+        return MBEDTLS_MD_NONE;
+    }
+
+    return md_info->type;
+}
+
+/************************************************************************
+ * Functions above this separator are part of MBEDTLS_MD_LIGHT,         *
+ * functions below are only available when MBEDTLS_MD_C is set.         *
+ ************************************************************************/
+#if defined(MBEDTLS_MD_C)
+
+/*
+ * Reminder: update profiles in x509_crt.c when adding a new hash!
+ */
+static const int supported_digests[] = {
+
+#if defined(MBEDTLS_MD_CAN_SHA512)
+    MBEDTLS_MD_SHA512,
+#endif
+
+#if defined(MBEDTLS_MD_CAN_SHA384)
+    MBEDTLS_MD_SHA384,
+#endif
+
+#if defined(MBEDTLS_MD_CAN_SHA256)
+    MBEDTLS_MD_SHA256,
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA224)
+    MBEDTLS_MD_SHA224,
+#endif
+
+#if defined(MBEDTLS_MD_CAN_SHA1)
+    MBEDTLS_MD_SHA1,
+#endif
+
+#if defined(MBEDTLS_MD_CAN_RIPEMD160)
+    MBEDTLS_MD_RIPEMD160,
+#endif
+
+#if defined(MBEDTLS_MD_CAN_MD5)
+    MBEDTLS_MD_MD5,
+#endif
+
+    MBEDTLS_MD_NONE
+};
+
+const int *mbedtls_md_list(void)
+{
+    return supported_digests;
+}
+
+const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name)
+{
+    if (NULL == md_name) {
+        return NULL;
+    }
+
+    /* Get the appropriate digest information */
+#if defined(MBEDTLS_MD_CAN_MD5)
+    if (!strcmp("MD5", md_name)) {
+        return mbedtls_md_info_from_type(MBEDTLS_MD_MD5);
+    }
+#endif
+#if defined(MBEDTLS_MD_CAN_RIPEMD160)
+    if (!strcmp("RIPEMD160", md_name)) {
+        return mbedtls_md_info_from_type(MBEDTLS_MD_RIPEMD160);
+    }
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA1)
+    if (!strcmp("SHA1", md_name) || !strcmp("SHA", md_name)) {
+        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
+    }
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA224)
+    if (!strcmp("SHA224", md_name)) {
+        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA224);
+    }
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA256)
+    if (!strcmp("SHA256", md_name)) {
+        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
+    }
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA384)
+    if (!strcmp("SHA384", md_name)) {
+        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
+    }
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA512)
+    if (!strcmp("SHA512", md_name)) {
+        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
+    }
+#endif
+    return NULL;
+}
+
+const mbedtls_md_info_t *mbedtls_md_info_from_ctx(
+    const mbedtls_md_context_t *ctx)
+{
+    if (ctx == NULL) {
+        return NULL;
+    }
+
+    return ctx->MBEDTLS_PRIVATE(md_info);
+}
+
 #if defined(MBEDTLS_FS_IO)
-int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output )
+int mbedtls_md_file(const mbedtls_md_info_t *md_info, const char *path, unsigned char *output)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     FILE *f;
@@ -667,56 +780,68 @@
     mbedtls_md_context_t ctx;
     unsigned char buf[1024];
 
-    if( md_info == NULL )
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    if (md_info == NULL) {
+        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
+    }
 
-    if( ( f = fopen( path, "rb" ) ) == NULL )
-        return( MBEDTLS_ERR_MD_FILE_IO_ERROR );
+    if ((f = fopen(path, "rb")) == NULL) {
+        return MBEDTLS_ERR_MD_FILE_IO_ERROR;
+    }
 
-    mbedtls_md_init( &ctx );
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf(f, NULL);
 
-    if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 )
+    mbedtls_md_init(&ctx);
+
+    if ((ret = mbedtls_md_setup(&ctx, md_info, 0)) != 0) {
         goto cleanup;
+    }
 
-    if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 )
+    if ((ret = mbedtls_md_starts(&ctx)) != 0) {
         goto cleanup;
+    }
 
-    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
-        if( ( ret = mbedtls_md_update( &ctx, buf, n ) ) != 0 )
+    while ((n = fread(buf, 1, sizeof(buf), f)) > 0) {
+        if ((ret = mbedtls_md_update(&ctx, buf, n)) != 0) {
             goto cleanup;
+        }
+    }
 
-    if( ferror( f ) != 0 )
+    if (ferror(f) != 0) {
         ret = MBEDTLS_ERR_MD_FILE_IO_ERROR;
-    else
-        ret = mbedtls_md_finish( &ctx, output );
+    } else {
+        ret = mbedtls_md_finish(&ctx, output);
+    }
 
 cleanup:
-    mbedtls_platform_zeroize( buf, sizeof( buf ) );
-    fclose( f );
-    mbedtls_md_free( &ctx );
+    mbedtls_platform_zeroize(buf, sizeof(buf));
+    fclose(f);
+    mbedtls_md_free(&ctx);
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_FS_IO */
 
-int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen )
+int mbedtls_md_hmac_starts(mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen)
 {
     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 );
+    if (ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL) {
+        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
+    }
 
-    if( keylen > (size_t) ctx->md_info->block_size )
-    {
-        if( ( ret = mbedtls_md_starts( ctx ) ) != 0 )
+    if (keylen > (size_t) ctx->md_info->block_size) {
+        if ((ret = mbedtls_md_starts(ctx)) != 0) {
             goto cleanup;
-        if( ( ret = mbedtls_md_update( ctx, key, keylen ) ) != 0 )
+        }
+        if ((ret = mbedtls_md_update(ctx, key, keylen)) != 0) {
             goto cleanup;
-        if( ( ret = mbedtls_md_finish( ctx, sum ) ) != 0 )
+        }
+        if ((ret = mbedtls_md_finish(ctx, sum)) != 0) {
             goto cleanup;
+        }
 
         keylen = ctx->md_info->size;
         key = sum;
@@ -725,169 +850,124 @@
     ipad = (unsigned char *) ctx->hmac_ctx;
     opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size;
 
-    memset( ipad, 0x36, ctx->md_info->block_size );
-    memset( opad, 0x5C, ctx->md_info->block_size );
+    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;
+    }
+    if ((ret = mbedtls_md_update(ctx, ipad,
+                                 ctx->md_info->block_size)) != 0) {
+        goto cleanup;
     }
 
-    if( ( ret = mbedtls_md_starts( ctx ) ) != 0 )
-        goto cleanup;
-    if( ( ret = mbedtls_md_update( ctx, ipad,
-                                   ctx->md_info->block_size ) ) != 0 )
-        goto cleanup;
-
 cleanup:
-    mbedtls_platform_zeroize( sum, sizeof( sum ) );
+    mbedtls_platform_zeroize(sum, sizeof(sum));
 
-    return( ret );
+    return ret;
 }
 
-int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen )
+int mbedtls_md_hmac_update(mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen)
 {
-    if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    if (ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL) {
+        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
+    }
 
-    return( mbedtls_md_update( ctx, input, ilen ) );
+    return mbedtls_md_update(ctx, input, ilen);
 }
 
-int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output )
+int mbedtls_md_hmac_finish(mbedtls_md_context_t *ctx, unsigned char *output)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char tmp[MBEDTLS_MD_MAX_SIZE];
     unsigned char *opad;
 
-    if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    if (ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL) {
+        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
+    }
 
     opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size;
 
-    if( ( ret = mbedtls_md_finish( ctx, tmp ) ) != 0 )
-        return( ret );
-    if( ( ret = mbedtls_md_starts( ctx ) ) != 0 )
-        return( ret );
-    if( ( ret = mbedtls_md_update( ctx, opad,
-                                   ctx->md_info->block_size ) ) != 0 )
-        return( ret );
-    if( ( ret = mbedtls_md_update( ctx, tmp,
-                                   ctx->md_info->size ) ) != 0 )
-        return( ret );
-    return( mbedtls_md_finish( ctx, output ) );
+    if ((ret = mbedtls_md_finish(ctx, tmp)) != 0) {
+        return ret;
+    }
+    if ((ret = mbedtls_md_starts(ctx)) != 0) {
+        return ret;
+    }
+    if ((ret = mbedtls_md_update(ctx, opad,
+                                 ctx->md_info->block_size)) != 0) {
+        return ret;
+    }
+    if ((ret = mbedtls_md_update(ctx, tmp,
+                                 ctx->md_info->size)) != 0) {
+        return ret;
+    }
+    return mbedtls_md_finish(ctx, output);
 }
 
-int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx )
+int mbedtls_md_hmac_reset(mbedtls_md_context_t *ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *ipad;
 
-    if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    if (ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL) {
+        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
+    }
 
     ipad = (unsigned char *) ctx->hmac_ctx;
 
-    if( ( ret = mbedtls_md_starts( ctx ) ) != 0 )
-        return( ret );
-    return( mbedtls_md_update( ctx, ipad, ctx->md_info->block_size ) );
+    if ((ret = mbedtls_md_starts(ctx)) != 0) {
+        return ret;
+    }
+    return mbedtls_md_update(ctx, ipad, ctx->md_info->block_size);
 }
 
-int mbedtls_md_hmac( const mbedtls_md_info_t *md_info,
-                     const unsigned char *key, size_t keylen,
-                     const unsigned char *input, size_t ilen,
-                     unsigned char *output )
+int mbedtls_md_hmac(const mbedtls_md_info_t *md_info,
+                    const unsigned char *key, size_t keylen,
+                    const unsigned char *input, size_t ilen,
+                    unsigned char *output)
 {
     mbedtls_md_context_t ctx;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( md_info == NULL )
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    if (md_info == NULL) {
+        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
+    }
 
-    mbedtls_md_init( &ctx );
+    mbedtls_md_init(&ctx);
 
-    if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 )
+    if ((ret = mbedtls_md_setup(&ctx, md_info, 1)) != 0) {
         goto cleanup;
+    }
 
-    if( ( ret = mbedtls_md_hmac_starts( &ctx, key, keylen ) ) != 0 )
+    if ((ret = mbedtls_md_hmac_starts(&ctx, key, keylen)) != 0) {
         goto cleanup;
-    if( ( ret = mbedtls_md_hmac_update( &ctx, input, ilen ) ) != 0 )
+    }
+    if ((ret = mbedtls_md_hmac_update(&ctx, input, ilen)) != 0) {
         goto cleanup;
-    if( ( ret = mbedtls_md_hmac_finish( &ctx, output ) ) != 0 )
+    }
+    if ((ret = mbedtls_md_hmac_finish(&ctx, output)) != 0) {
         goto cleanup;
+    }
 
 cleanup:
-    mbedtls_md_free( &ctx );
+    mbedtls_md_free(&ctx);
 
-    return( ret );
+    return ret;
 }
 
-int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data )
+const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info)
 {
-    if( ctx == NULL || ctx->md_info == NULL )
-        return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
-
-    switch( ctx->md_info->type )
-    {
-#if defined(MBEDTLS_MD2_C)
-        case MBEDTLS_MD_MD2:
-            return( mbedtls_internal_md2_process( ctx->md_ctx ) );
-#endif
-#if defined(MBEDTLS_MD4_C)
-        case MBEDTLS_MD_MD4:
-            return( mbedtls_internal_md4_process( ctx->md_ctx, data ) );
-#endif
-#if defined(MBEDTLS_MD5_C)
-        case MBEDTLS_MD_MD5:
-            return( mbedtls_internal_md5_process( ctx->md_ctx, data ) );
-#endif
-#if defined(MBEDTLS_RIPEMD160_C)
-        case MBEDTLS_MD_RIPEMD160:
-            return( mbedtls_internal_ripemd160_process( ctx->md_ctx, data ) );
-#endif
-#if defined(MBEDTLS_SHA1_C)
-        case MBEDTLS_MD_SHA1:
-            return( mbedtls_internal_sha1_process( ctx->md_ctx, data ) );
-#endif
-#if defined(MBEDTLS_SHA256_C)
-        case MBEDTLS_MD_SHA224:
-        case MBEDTLS_MD_SHA256:
-            return( mbedtls_internal_sha256_process( ctx->md_ctx, data ) );
-#endif
-#if defined(MBEDTLS_SHA512_C)
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
-        case MBEDTLS_MD_SHA384:
-#endif
-        case MBEDTLS_MD_SHA512:
-            return( mbedtls_internal_sha512_process( ctx->md_ctx, data ) );
-#endif
-        default:
-            return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+    if (md_info == NULL) {
+        return NULL;
     }
-}
-
-unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info )
-{
-    if( md_info == NULL )
-        return( 0 );
-
-    return md_info->size;
-}
-
-mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info )
-{
-    if( md_info == NULL )
-        return( MBEDTLS_MD_NONE );
-
-    return md_info->type;
-}
-
-const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info )
-{
-    if( md_info == NULL )
-        return( NULL );
 
     return md_info->name;
 }
 
 #endif /* MBEDTLS_MD_C */
+
+#endif /* MBEDTLS_MD_LIGHT */
diff --git a/lib/libmbedtls/mbedtls/library/md2.c b/lib/libmbedtls/mbedtls/library/md2.c
deleted file mode 100644
index 7264e30..0000000
--- a/lib/libmbedtls/mbedtls/library/md2.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- *  RFC 1115/1319 compliant MD2 implementation
- *
- *  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.
- */
-/*
- *  The MD2 algorithm was designed by Ron Rivest in 1989.
- *
- *  http://www.ietf.org/rfc/rfc1115.txt
- *  http://www.ietf.org/rfc/rfc1319.txt
- */
-
-#include "common.h"
-
-#if defined(MBEDTLS_MD2_C)
-
-#include "mbedtls/md2.h"
-#include "mbedtls/platform_util.h"
-#include "mbedtls/error.h"
-
-#include <string.h>
-
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
-
-#if !defined(MBEDTLS_MD2_ALT)
-
-static const unsigned char PI_SUBST[256] =
-{
-    0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36,
-    0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3,
-    0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C,
-    0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
-    0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E,
-    0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E,
-    0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2,
-    0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
-    0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E,
-    0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3,
-    0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56,
-    0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
-    0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D,
-    0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65,
-    0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0,
-    0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
-    0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C,
-    0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E,
-    0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81,
-    0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
-    0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88,
-    0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE,
-    0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58,
-    0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
-    0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99,
-    0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
-};
-
-void mbedtls_md2_init( mbedtls_md2_context *ctx )
-{
-    memset( ctx, 0, sizeof( mbedtls_md2_context ) );
-}
-
-void mbedtls_md2_free( mbedtls_md2_context *ctx )
-{
-    if( ctx == NULL )
-        return;
-
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md2_context ) );
-}
-
-void mbedtls_md2_clone( mbedtls_md2_context *dst,
-                        const mbedtls_md2_context *src )
-{
-    *dst = *src;
-}
-
-/*
- * MD2 context setup
- */
-int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx )
-{
-    memset( ctx->cksum, 0, 16 );
-    memset( ctx->state, 0, 46 );
-    memset( ctx->buffer, 0, 16 );
-    ctx->left = 0;
-
-    return( 0 );
-}
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_md2_starts( mbedtls_md2_context *ctx )
-{
-    mbedtls_md2_starts_ret( ctx );
-}
-#endif
-
-#if !defined(MBEDTLS_MD2_PROCESS_ALT)
-int mbedtls_internal_md2_process( mbedtls_md2_context *ctx )
-{
-    int i, j;
-    unsigned char t = 0;
-
-    for( i = 0; i < 16; i++ )
-    {
-        ctx->state[i + 16] = ctx->buffer[i];
-        ctx->state[i + 32] =
-            (unsigned char)( ctx->buffer[i] ^ ctx->state[i]);
-    }
-
-    for( i = 0; i < 18; i++ )
-    {
-        for( j = 0; j < 48; j++ )
-        {
-            ctx->state[j] = (unsigned char)
-               ( ctx->state[j] ^ PI_SUBST[t] );
-            t  = ctx->state[j];
-        }
-
-        t = (unsigned char)( t + i );
-    }
-
-    t = ctx->cksum[15];
-
-    for( i = 0; i < 16; i++ )
-    {
-        ctx->cksum[i] = (unsigned char)
-           ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] );
-        t  = ctx->cksum[i];
-    }
-
-    /* Zeroise variables to clear sensitive data from memory. */
-    mbedtls_platform_zeroize( &t, sizeof( t ) );
-
-    return( 0 );
-}
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_md2_process( mbedtls_md2_context *ctx )
-{
-    mbedtls_internal_md2_process( ctx );
-}
-#endif
-#endif /* !MBEDTLS_MD2_PROCESS_ALT */
-
-/*
- * MD2 process buffer
- */
-int mbedtls_md2_update_ret( mbedtls_md2_context *ctx,
-                            const unsigned char *input,
-                            size_t ilen )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t fill;
-
-    while( ilen > 0 )
-    {
-        if( ilen > 16 - ctx->left )
-            fill = 16 - ctx->left;
-        else
-            fill = ilen;
-
-        memcpy( ctx->buffer + ctx->left, input, fill );
-
-        ctx->left += fill;
-        input += fill;
-        ilen  -= fill;
-
-        if( ctx->left == 16 )
-        {
-            ctx->left = 0;
-            if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 )
-                return( ret );
-        }
-    }
-
-    return( 0 );
-}
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_md2_update( mbedtls_md2_context *ctx,
-                         const unsigned char *input,
-                         size_t ilen )
-{
-    mbedtls_md2_update_ret( ctx, input, ilen );
-}
-#endif
-
-/*
- * MD2 final digest
- */
-int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx,
-                            unsigned char output[16] )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t i;
-    unsigned char x;
-
-    x = (unsigned char)( 16 - ctx->left );
-
-    for( i = ctx->left; i < 16; i++ )
-        ctx->buffer[i] = x;
-
-    if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 )
-        return( ret );
-
-    memcpy( ctx->buffer, ctx->cksum, 16 );
-    if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 )
-        return( ret );
-
-    memcpy( output, ctx->state, 16 );
-
-    return( 0 );
-}
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_md2_finish( mbedtls_md2_context *ctx,
-                         unsigned char output[16] )
-{
-    mbedtls_md2_finish_ret( ctx, output );
-}
-#endif
-
-#endif /* !MBEDTLS_MD2_ALT */
-
-/*
- * output = MD2( input buffer )
- */
-int mbedtls_md2_ret( const unsigned char *input,
-                     size_t ilen,
-                     unsigned char output[16] )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_md2_context ctx;
-
-    mbedtls_md2_init( &ctx );
-
-    if( ( ret = mbedtls_md2_starts_ret( &ctx ) ) != 0 )
-        goto exit;
-
-    if( ( ret = mbedtls_md2_update_ret( &ctx, input, ilen ) ) != 0 )
-        goto exit;
-
-    if( ( ret = mbedtls_md2_finish_ret( &ctx, output ) ) != 0 )
-        goto exit;
-
-exit:
-    mbedtls_md2_free( &ctx );
-
-    return( ret );
-}
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_md2( const unsigned char *input,
-                  size_t ilen,
-                  unsigned char output[16] )
-{
-    mbedtls_md2_ret( input, ilen, output );
-}
-#endif
-
-#if defined(MBEDTLS_SELF_TEST)
-
-/*
- * RFC 1319 test vectors
- */
-static const unsigned char md2_test_str[7][81] =
-{
-    { "" },
-    { "a" },
-    { "abc" },
-    { "message digest" },
-    { "abcdefghijklmnopqrstuvwxyz" },
-    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
-    { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
-};
-
-static const size_t md2_test_strlen[7] =
-{
-    0, 1, 3, 14, 26, 62, 80
-};
-
-static const unsigned char md2_test_sum[7][16] =
-{
-    { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D,
-      0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 },
-    { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72,
-      0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 },
-    { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B,
-      0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB },
-    { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B,
-      0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 },
-    { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB,
-      0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B },
-    { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39,
-      0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD },
-    { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D,
-      0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 }
-};
-
-/*
- * Checkup routine
- */
-int mbedtls_md2_self_test( int verbose )
-{
-    int i, ret = 0;
-    unsigned char md2sum[16];
-
-    for( i = 0; i < 7; i++ )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "  MD2 test #%d: ", i + 1 );
-
-        ret = mbedtls_md2_ret( md2_test_str[i], md2_test_strlen[i], md2sum );
-        if( ret != 0 )
-            goto fail;
-
-        if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 )
-        {
-            ret = 1;
-            goto fail;
-        }
-
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
-    }
-
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
-
-    return( 0 );
-
-fail:
-    if( verbose != 0 )
-        mbedtls_printf( "failed\n" );
-
-    return( ret );
-}
-
-#endif /* MBEDTLS_SELF_TEST */
-
-#endif /* MBEDTLS_MD2_C */
diff --git a/lib/libmbedtls/mbedtls/library/md4.c b/lib/libmbedtls/mbedtls/library/md4.c
deleted file mode 100644
index eaa679a..0000000
--- a/lib/libmbedtls/mbedtls/library/md4.c
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- *  RFC 1186/1320 compliant MD4 implementation
- *
- *  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.
- */
-/*
- *  The MD4 algorithm was designed by Ron Rivest in 1990.
- *
- *  http://www.ietf.org/rfc/rfc1186.txt
- *  http://www.ietf.org/rfc/rfc1320.txt
- */
-
-#include "common.h"
-
-#if defined(MBEDTLS_MD4_C)
-
-#include "mbedtls/md4.h"
-#include "mbedtls/platform_util.h"
-#include "mbedtls/error.h"
-
-#include <string.h>
-
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
-
-#if !defined(MBEDTLS_MD4_ALT)
-
-void mbedtls_md4_init( mbedtls_md4_context *ctx )
-{
-    memset( ctx, 0, sizeof( mbedtls_md4_context ) );
-}
-
-void mbedtls_md4_free( mbedtls_md4_context *ctx )
-{
-    if( ctx == NULL )
-        return;
-
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) );
-}
-
-void mbedtls_md4_clone( mbedtls_md4_context *dst,
-                        const mbedtls_md4_context *src )
-{
-    *dst = *src;
-}
-
-/*
- * MD4 context setup
- */
-int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx )
-{
-    ctx->total[0] = 0;
-    ctx->total[1] = 0;
-
-    ctx->state[0] = 0x67452301;
-    ctx->state[1] = 0xEFCDAB89;
-    ctx->state[2] = 0x98BADCFE;
-    ctx->state[3] = 0x10325476;
-
-    return( 0 );
-}
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_md4_starts( mbedtls_md4_context *ctx )
-{
-    mbedtls_md4_starts_ret( ctx );
-}
-#endif
-
-#if !defined(MBEDTLS_MD4_PROCESS_ALT)
-int mbedtls_internal_md4_process( mbedtls_md4_context *ctx,
-                                  const unsigned char data[64] )
-{
-    struct
-    {
-        uint32_t X[16], A, B, C, D;
-    } local;
-
-    local.X[ 0] = MBEDTLS_GET_UINT32_LE( data,  0 );
-    local.X[ 1] = MBEDTLS_GET_UINT32_LE( data,  4 );
-    local.X[ 2] = MBEDTLS_GET_UINT32_LE( data,  8 );
-    local.X[ 3] = MBEDTLS_GET_UINT32_LE( data, 12 );
-    local.X[ 4] = MBEDTLS_GET_UINT32_LE( data, 16 );
-    local.X[ 5] = MBEDTLS_GET_UINT32_LE( data, 20 );
-    local.X[ 6] = MBEDTLS_GET_UINT32_LE( data, 24 );
-    local.X[ 7] = MBEDTLS_GET_UINT32_LE( data, 28 );
-    local.X[ 8] = MBEDTLS_GET_UINT32_LE( data, 32 );
-    local.X[ 9] = MBEDTLS_GET_UINT32_LE( data, 36 );
-    local.X[10] = MBEDTLS_GET_UINT32_LE( data, 40 );
-    local.X[11] = MBEDTLS_GET_UINT32_LE( data, 44 );
-    local.X[12] = MBEDTLS_GET_UINT32_LE( data, 48 );
-    local.X[13] = MBEDTLS_GET_UINT32_LE( data, 52 );
-    local.X[14] = MBEDTLS_GET_UINT32_LE( data, 56 );
-    local.X[15] = MBEDTLS_GET_UINT32_LE( data, 60 );
-
-#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
-
-    local.A = ctx->state[0];
-    local.B = ctx->state[1];
-    local.C = ctx->state[2];
-    local.D = ctx->state[3];
-
-#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
-#define P(a,b,c,d,x,s)                           \
-    do                                           \
-    {                                            \
-        (a) += F((b),(c),(d)) + (x);             \
-        (a) = S((a),(s));                        \
-    } while( 0 )
-
-
-    P( local.A, local.B, local.C, local.D, local.X[ 0],  3 );
-    P( local.D, local.A, local.B, local.C, local.X[ 1],  7 );
-    P( local.C, local.D, local.A, local.B, local.X[ 2], 11 );
-    P( local.B, local.C, local.D, local.A, local.X[ 3], 19 );
-    P( local.A, local.B, local.C, local.D, local.X[ 4],  3 );
-    P( local.D, local.A, local.B, local.C, local.X[ 5],  7 );
-    P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
-    P( local.B, local.C, local.D, local.A, local.X[ 7], 19 );
-    P( local.A, local.B, local.C, local.D, local.X[ 8],  3 );
-    P( local.D, local.A, local.B, local.C, local.X[ 9],  7 );
-    P( local.C, local.D, local.A, local.B, local.X[10], 11 );
-    P( local.B, local.C, local.D, local.A, local.X[11], 19 );
-    P( local.A, local.B, local.C, local.D, local.X[12],  3 );
-    P( local.D, local.A, local.B, local.C, local.X[13],  7 );
-    P( local.C, local.D, local.A, local.B, local.X[14], 11 );
-    P( local.B, local.C, local.D, local.A, local.X[15], 19 );
-
-#undef P
-#undef F
-
-#define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
-#define P(a,b,c,d,x,s)                          \
-    do                                          \
-    {                                           \
-        (a) += F((b),(c),(d)) + (x) + 0x5A827999;       \
-        (a) = S((a),(s));                               \
-    } while( 0 )
-
-    P( local.A, local.B, local.C, local.D, local.X[ 0],  3 );
-    P( local.D, local.A, local.B, local.C, local.X[ 4],  5 );
-    P( local.C, local.D, local.A, local.B, local.X[ 8],  9 );
-    P( local.B, local.C, local.D, local.A, local.X[12], 13 );
-    P( local.A, local.B, local.C, local.D, local.X[ 1],  3 );
-    P( local.D, local.A, local.B, local.C, local.X[ 5],  5 );
-    P( local.C, local.D, local.A, local.B, local.X[ 9],  9 );
-    P( local.B, local.C, local.D, local.A, local.X[13], 13 );
-    P( local.A, local.B, local.C, local.D, local.X[ 2],  3 );
-    P( local.D, local.A, local.B, local.C, local.X[ 6],  5 );
-    P( local.C, local.D, local.A, local.B, local.X[10],  9 );
-    P( local.B, local.C, local.D, local.A, local.X[14], 13 );
-    P( local.A, local.B, local.C, local.D, local.X[ 3],  3 );
-    P( local.D, local.A, local.B, local.C, local.X[ 7],  5 );
-    P( local.C, local.D, local.A, local.B, local.X[11],  9 );
-    P( local.B, local.C, local.D, local.A, local.X[15], 13 );
-
-#undef P
-#undef F
-
-#define F(x,y,z) ((x) ^ (y) ^ (z))
-#define P(a,b,c,d,x,s)                                  \
-    do                                                  \
-    {                                                   \
-        (a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1;       \
-        (a) = S((a),(s));                               \
-    } while( 0 )
-
-    P( local.A, local.B, local.C, local.D, local.X[ 0],  3 );
-    P( local.D, local.A, local.B, local.C, local.X[ 8],  9 );
-    P( local.C, local.D, local.A, local.B, local.X[ 4], 11 );
-    P( local.B, local.C, local.D, local.A, local.X[12], 15 );
-    P( local.A, local.B, local.C, local.D, local.X[ 2],  3 );
-    P( local.D, local.A, local.B, local.C, local.X[10],  9 );
-    P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
-    P( local.B, local.C, local.D, local.A, local.X[14], 15 );
-    P( local.A, local.B, local.C, local.D, local.X[ 1],  3 );
-    P( local.D, local.A, local.B, local.C, local.X[ 9],  9 );
-    P( local.C, local.D, local.A, local.B, local.X[ 5], 11 );
-    P( local.B, local.C, local.D, local.A, local.X[13], 15 );
-    P( local.A, local.B, local.C, local.D, local.X[ 3],  3 );
-    P( local.D, local.A, local.B, local.C, local.X[11],  9 );
-    P( local.C, local.D, local.A, local.B, local.X[ 7], 11 );
-    P( local.B, local.C, local.D, local.A, local.X[15], 15 );
-
-#undef F
-#undef P
-
-    ctx->state[0] += local.A;
-    ctx->state[1] += local.B;
-    ctx->state[2] += local.C;
-    ctx->state[3] += local.D;
-
-    /* Zeroise variables to clear sensitive data from memory. */
-    mbedtls_platform_zeroize( &local, sizeof( local ) );
-
-    return( 0 );
-}
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_md4_process( mbedtls_md4_context *ctx,
-                          const unsigned char data[64] )
-{
-    mbedtls_internal_md4_process( ctx, data );
-}
-#endif
-#endif /* !MBEDTLS_MD4_PROCESS_ALT */
-
-/*
- * MD4 process buffer
- */
-int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
-                            const unsigned char *input,
-                            size_t ilen )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t fill;
-    uint32_t left;
-
-    if( ilen == 0 )
-        return( 0 );
-
-    left = ctx->total[0] & 0x3F;
-    fill = 64 - left;
-
-    ctx->total[0] += (uint32_t) ilen;
-    ctx->total[0] &= 0xFFFFFFFF;
-
-    if( ctx->total[0] < (uint32_t) ilen )
-        ctx->total[1]++;
-
-    if( left && ilen >= fill )
-    {
-        memcpy( (void *) (ctx->buffer + left),
-                (void *) input, fill );
-
-        if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 )
-            return( ret );
-
-        input += fill;
-        ilen  -= fill;
-        left = 0;
-    }
-
-    while( ilen >= 64 )
-    {
-        if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 )
-            return( ret );
-
-        input += 64;
-        ilen  -= 64;
-    }
-
-    if( ilen > 0 )
-    {
-        memcpy( (void *) (ctx->buffer + left),
-                (void *) input, ilen );
-    }
-
-    return( 0 );
-}
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_md4_update( mbedtls_md4_context *ctx,
-                         const unsigned char *input,
-                         size_t ilen )
-{
-    mbedtls_md4_update_ret( ctx, input, ilen );
-}
-#endif
-
-static const unsigned char md4_padding[64] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/*
- * MD4 final digest
- */
-int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
-                            unsigned char output[16] )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    uint32_t last, padn;
-    uint32_t high, low;
-    unsigned char msglen[8];
-
-    high = ( ctx->total[0] >> 29 )
-         | ( ctx->total[1] <<  3 );
-    low  = ( ctx->total[0] <<  3 );
-
-    MBEDTLS_PUT_UINT32_LE( low,  msglen, 0 );
-    MBEDTLS_PUT_UINT32_LE( high, msglen, 4 );
-
-    last = ctx->total[0] & 0x3F;
-    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
-
-    ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
-    if( ret != 0 )
-        return( ret );
-
-    if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
-        return( ret );
-
-
-    MBEDTLS_PUT_UINT32_LE( ctx->state[0], output,  0 );
-    MBEDTLS_PUT_UINT32_LE( ctx->state[1], output,  4 );
-    MBEDTLS_PUT_UINT32_LE( ctx->state[2], output,  8 );
-    MBEDTLS_PUT_UINT32_LE( ctx->state[3], output, 12 );
-
-    return( 0 );
-}
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_md4_finish( mbedtls_md4_context *ctx,
-                         unsigned char output[16] )
-{
-    mbedtls_md4_finish_ret( ctx, output );
-}
-#endif
-
-#endif /* !MBEDTLS_MD4_ALT */
-
-/*
- * output = MD4( input buffer )
- */
-int mbedtls_md4_ret( const unsigned char *input,
-                     size_t ilen,
-                     unsigned char output[16] )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_md4_context ctx;
-
-    mbedtls_md4_init( &ctx );
-
-    if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 )
-        goto exit;
-
-    if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 )
-        goto exit;
-
-    if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 )
-        goto exit;
-
-exit:
-    mbedtls_md4_free( &ctx );
-
-    return( ret );
-}
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_md4( const unsigned char *input,
-                  size_t ilen,
-                  unsigned char output[16] )
-{
-    mbedtls_md4_ret( input, ilen, output );
-}
-#endif
-
-#if defined(MBEDTLS_SELF_TEST)
-
-/*
- * RFC 1320 test vectors
- */
-static const unsigned char md4_test_str[7][81] =
-{
-    { "" },
-    { "a" },
-    { "abc" },
-    { "message digest" },
-    { "abcdefghijklmnopqrstuvwxyz" },
-    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
-    { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
-};
-
-static const size_t md4_test_strlen[7] =
-{
-    0, 1, 3, 14, 26, 62, 80
-};
-
-static const unsigned char md4_test_sum[7][16] =
-{
-    { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
-      0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
-    { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
-      0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
-    { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
-      0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
-    { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
-      0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
-    { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
-      0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
-    { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
-      0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
-    { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
-      0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
-};
-
-/*
- * Checkup routine
- */
-int mbedtls_md4_self_test( int verbose )
-{
-    int i, ret = 0;
-    unsigned char md4sum[16];
-
-    for( i = 0; i < 7; i++ )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "  MD4 test #%d: ", i + 1 );
-
-        ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
-        if( ret != 0 )
-            goto fail;
-
-        if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
-        {
-            ret = 1;
-            goto fail;
-        }
-
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
-    }
-
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
-
-    return( 0 );
-
-fail:
-    if( verbose != 0 )
-        mbedtls_printf( "failed\n" );
-
-    return( ret );
-}
-
-#endif /* MBEDTLS_SELF_TEST */
-
-#endif /* MBEDTLS_MD4_C */
diff --git a/lib/libmbedtls/mbedtls/library/md5.c b/lib/libmbedtls/mbedtls/library/md5.c
index 4b53fcf..138a320 100644
--- a/lib/libmbedtls/mbedtls/library/md5.c
+++ b/lib/libmbedtls/mbedtls/library/md5.c
@@ -32,32 +32,26 @@
 
 #include <string.h>
 
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
 
 #if !defined(MBEDTLS_MD5_ALT)
 
-void mbedtls_md5_init( mbedtls_md5_context *ctx )
+void mbedtls_md5_init(mbedtls_md5_context *ctx)
 {
-    memset( ctx, 0, sizeof( mbedtls_md5_context ) );
+    memset(ctx, 0, sizeof(mbedtls_md5_context));
 }
 
-void mbedtls_md5_free( mbedtls_md5_context *ctx )
+void mbedtls_md5_free(mbedtls_md5_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md5_context ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md5_context));
 }
 
-void mbedtls_md5_clone( mbedtls_md5_context *dst,
-                        const mbedtls_md5_context *src )
+void mbedtls_md5_clone(mbedtls_md5_context *dst,
+                       const mbedtls_md5_context *src)
 {
     *dst = *src;
 }
@@ -65,7 +59,7 @@
 /*
  * MD5 context setup
  */
-int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx )
+int mbedtls_md5_starts(mbedtls_md5_context *ctx)
 {
     ctx->total[0] = 0;
     ctx->total[1] = 0;
@@ -75,138 +69,130 @@
     ctx->state[2] = 0x98BADCFE;
     ctx->state[3] = 0x10325476;
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_md5_starts( mbedtls_md5_context *ctx )
-{
-    mbedtls_md5_starts_ret( ctx );
-}
-#endif
-
 #if !defined(MBEDTLS_MD5_PROCESS_ALT)
-int mbedtls_internal_md5_process( mbedtls_md5_context *ctx,
-                                  const unsigned char data[64] )
+int mbedtls_internal_md5_process(mbedtls_md5_context *ctx,
+                                 const unsigned char data[64])
 {
-    struct
-    {
+    struct {
         uint32_t X[16], A, B, C, D;
     } local;
 
-    local.X[ 0] = MBEDTLS_GET_UINT32_LE( data,  0 );
-    local.X[ 1] = MBEDTLS_GET_UINT32_LE( data,  4 );
-    local.X[ 2] = MBEDTLS_GET_UINT32_LE( data,  8 );
-    local.X[ 3] = MBEDTLS_GET_UINT32_LE( data, 12 );
-    local.X[ 4] = MBEDTLS_GET_UINT32_LE( data, 16 );
-    local.X[ 5] = MBEDTLS_GET_UINT32_LE( data, 20 );
-    local.X[ 6] = MBEDTLS_GET_UINT32_LE( data, 24 );
-    local.X[ 7] = MBEDTLS_GET_UINT32_LE( data, 28 );
-    local.X[ 8] = MBEDTLS_GET_UINT32_LE( data, 32 );
-    local.X[ 9] = MBEDTLS_GET_UINT32_LE( data, 36 );
-    local.X[10] = MBEDTLS_GET_UINT32_LE( data, 40 );
-    local.X[11] = MBEDTLS_GET_UINT32_LE( data, 44 );
-    local.X[12] = MBEDTLS_GET_UINT32_LE( data, 48 );
-    local.X[13] = MBEDTLS_GET_UINT32_LE( data, 52 );
-    local.X[14] = MBEDTLS_GET_UINT32_LE( data, 56 );
-    local.X[15] = MBEDTLS_GET_UINT32_LE( data, 60 );
+    local.X[0] = MBEDTLS_GET_UINT32_LE(data,  0);
+    local.X[1] = MBEDTLS_GET_UINT32_LE(data,  4);
+    local.X[2] = MBEDTLS_GET_UINT32_LE(data,  8);
+    local.X[3] = MBEDTLS_GET_UINT32_LE(data, 12);
+    local.X[4] = MBEDTLS_GET_UINT32_LE(data, 16);
+    local.X[5] = MBEDTLS_GET_UINT32_LE(data, 20);
+    local.X[6] = MBEDTLS_GET_UINT32_LE(data, 24);
+    local.X[7] = MBEDTLS_GET_UINT32_LE(data, 28);
+    local.X[8] = MBEDTLS_GET_UINT32_LE(data, 32);
+    local.X[9] = MBEDTLS_GET_UINT32_LE(data, 36);
+    local.X[10] = MBEDTLS_GET_UINT32_LE(data, 40);
+    local.X[11] = MBEDTLS_GET_UINT32_LE(data, 44);
+    local.X[12] = MBEDTLS_GET_UINT32_LE(data, 48);
+    local.X[13] = MBEDTLS_GET_UINT32_LE(data, 52);
+    local.X[14] = MBEDTLS_GET_UINT32_LE(data, 56);
+    local.X[15] = MBEDTLS_GET_UINT32_LE(data, 60);
 
-#define S(x,n)                                                          \
-    ( ( (x) << (n) ) | ( ( (x) & 0xFFFFFFFF) >> ( 32 - (n) ) ) )
+#define S(x, n)                                                          \
+    (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
 
-#define P(a,b,c,d,k,s,t)                                                \
+#define P(a, b, c, d, k, s, t)                                                \
     do                                                                  \
     {                                                                   \
-        (a) += F((b),(c),(d)) + local.X[(k)] + (t);                     \
-        (a) = S((a),(s)) + (b);                                         \
-    } while( 0 )
+        (a) += F((b), (c), (d)) + local.X[(k)] + (t);                     \
+        (a) = S((a), (s)) + (b);                                         \
+    } while (0)
 
     local.A = ctx->state[0];
     local.B = ctx->state[1];
     local.C = ctx->state[2];
     local.D = ctx->state[3];
 
-#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
 
-    P( local.A, local.B, local.C, local.D,  0,  7, 0xD76AA478 );
-    P( local.D, local.A, local.B, local.C,  1, 12, 0xE8C7B756 );
-    P( local.C, local.D, local.A, local.B,  2, 17, 0x242070DB );
-    P( local.B, local.C, local.D, local.A,  3, 22, 0xC1BDCEEE );
-    P( local.A, local.B, local.C, local.D,  4,  7, 0xF57C0FAF );
-    P( local.D, local.A, local.B, local.C,  5, 12, 0x4787C62A );
-    P( local.C, local.D, local.A, local.B,  6, 17, 0xA8304613 );
-    P( local.B, local.C, local.D, local.A,  7, 22, 0xFD469501 );
-    P( local.A, local.B, local.C, local.D,  8,  7, 0x698098D8 );
-    P( local.D, local.A, local.B, local.C,  9, 12, 0x8B44F7AF );
-    P( local.C, local.D, local.A, local.B, 10, 17, 0xFFFF5BB1 );
-    P( local.B, local.C, local.D, local.A, 11, 22, 0x895CD7BE );
-    P( local.A, local.B, local.C, local.D, 12,  7, 0x6B901122 );
-    P( local.D, local.A, local.B, local.C, 13, 12, 0xFD987193 );
-    P( local.C, local.D, local.A, local.B, 14, 17, 0xA679438E );
-    P( local.B, local.C, local.D, local.A, 15, 22, 0x49B40821 );
+    P(local.A, local.B, local.C, local.D,  0,  7, 0xD76AA478);
+    P(local.D, local.A, local.B, local.C,  1, 12, 0xE8C7B756);
+    P(local.C, local.D, local.A, local.B,  2, 17, 0x242070DB);
+    P(local.B, local.C, local.D, local.A,  3, 22, 0xC1BDCEEE);
+    P(local.A, local.B, local.C, local.D,  4,  7, 0xF57C0FAF);
+    P(local.D, local.A, local.B, local.C,  5, 12, 0x4787C62A);
+    P(local.C, local.D, local.A, local.B,  6, 17, 0xA8304613);
+    P(local.B, local.C, local.D, local.A,  7, 22, 0xFD469501);
+    P(local.A, local.B, local.C, local.D,  8,  7, 0x698098D8);
+    P(local.D, local.A, local.B, local.C,  9, 12, 0x8B44F7AF);
+    P(local.C, local.D, local.A, local.B, 10, 17, 0xFFFF5BB1);
+    P(local.B, local.C, local.D, local.A, 11, 22, 0x895CD7BE);
+    P(local.A, local.B, local.C, local.D, 12,  7, 0x6B901122);
+    P(local.D, local.A, local.B, local.C, 13, 12, 0xFD987193);
+    P(local.C, local.D, local.A, local.B, 14, 17, 0xA679438E);
+    P(local.B, local.C, local.D, local.A, 15, 22, 0x49B40821);
 
 #undef F
 
-#define F(x,y,z) ((y) ^ ((z) & ((x) ^ (y))))
+#define F(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
 
-    P( local.A, local.B, local.C, local.D,  1,  5, 0xF61E2562 );
-    P( local.D, local.A, local.B, local.C,  6,  9, 0xC040B340 );
-    P( local.C, local.D, local.A, local.B, 11, 14, 0x265E5A51 );
-    P( local.B, local.C, local.D, local.A,  0, 20, 0xE9B6C7AA );
-    P( local.A, local.B, local.C, local.D,  5,  5, 0xD62F105D );
-    P( local.D, local.A, local.B, local.C, 10,  9, 0x02441453 );
-    P( local.C, local.D, local.A, local.B, 15, 14, 0xD8A1E681 );
-    P( local.B, local.C, local.D, local.A,  4, 20, 0xE7D3FBC8 );
-    P( local.A, local.B, local.C, local.D,  9,  5, 0x21E1CDE6 );
-    P( local.D, local.A, local.B, local.C, 14,  9, 0xC33707D6 );
-    P( local.C, local.D, local.A, local.B,  3, 14, 0xF4D50D87 );
-    P( local.B, local.C, local.D, local.A,  8, 20, 0x455A14ED );
-    P( local.A, local.B, local.C, local.D, 13,  5, 0xA9E3E905 );
-    P( local.D, local.A, local.B, local.C,  2,  9, 0xFCEFA3F8 );
-    P( local.C, local.D, local.A, local.B,  7, 14, 0x676F02D9 );
-    P( local.B, local.C, local.D, local.A, 12, 20, 0x8D2A4C8A );
+    P(local.A, local.B, local.C, local.D,  1,  5, 0xF61E2562);
+    P(local.D, local.A, local.B, local.C,  6,  9, 0xC040B340);
+    P(local.C, local.D, local.A, local.B, 11, 14, 0x265E5A51);
+    P(local.B, local.C, local.D, local.A,  0, 20, 0xE9B6C7AA);
+    P(local.A, local.B, local.C, local.D,  5,  5, 0xD62F105D);
+    P(local.D, local.A, local.B, local.C, 10,  9, 0x02441453);
+    P(local.C, local.D, local.A, local.B, 15, 14, 0xD8A1E681);
+    P(local.B, local.C, local.D, local.A,  4, 20, 0xE7D3FBC8);
+    P(local.A, local.B, local.C, local.D,  9,  5, 0x21E1CDE6);
+    P(local.D, local.A, local.B, local.C, 14,  9, 0xC33707D6);
+    P(local.C, local.D, local.A, local.B,  3, 14, 0xF4D50D87);
+    P(local.B, local.C, local.D, local.A,  8, 20, 0x455A14ED);
+    P(local.A, local.B, local.C, local.D, 13,  5, 0xA9E3E905);
+    P(local.D, local.A, local.B, local.C,  2,  9, 0xFCEFA3F8);
+    P(local.C, local.D, local.A, local.B,  7, 14, 0x676F02D9);
+    P(local.B, local.C, local.D, local.A, 12, 20, 0x8D2A4C8A);
 
 #undef F
 
-#define F(x,y,z) ((x) ^ (y) ^ (z))
+#define F(x, y, z) ((x) ^ (y) ^ (z))
 
-    P( local.A, local.B, local.C, local.D,  5,  4, 0xFFFA3942 );
-    P( local.D, local.A, local.B, local.C,  8, 11, 0x8771F681 );
-    P( local.C, local.D, local.A, local.B, 11, 16, 0x6D9D6122 );
-    P( local.B, local.C, local.D, local.A, 14, 23, 0xFDE5380C );
-    P( local.A, local.B, local.C, local.D,  1,  4, 0xA4BEEA44 );
-    P( local.D, local.A, local.B, local.C,  4, 11, 0x4BDECFA9 );
-    P( local.C, local.D, local.A, local.B,  7, 16, 0xF6BB4B60 );
-    P( local.B, local.C, local.D, local.A, 10, 23, 0xBEBFBC70 );
-    P( local.A, local.B, local.C, local.D, 13,  4, 0x289B7EC6 );
-    P( local.D, local.A, local.B, local.C,  0, 11, 0xEAA127FA );
-    P( local.C, local.D, local.A, local.B,  3, 16, 0xD4EF3085 );
-    P( local.B, local.C, local.D, local.A,  6, 23, 0x04881D05 );
-    P( local.A, local.B, local.C, local.D,  9,  4, 0xD9D4D039 );
-    P( local.D, local.A, local.B, local.C, 12, 11, 0xE6DB99E5 );
-    P( local.C, local.D, local.A, local.B, 15, 16, 0x1FA27CF8 );
-    P( local.B, local.C, local.D, local.A,  2, 23, 0xC4AC5665 );
+    P(local.A, local.B, local.C, local.D,  5,  4, 0xFFFA3942);
+    P(local.D, local.A, local.B, local.C,  8, 11, 0x8771F681);
+    P(local.C, local.D, local.A, local.B, 11, 16, 0x6D9D6122);
+    P(local.B, local.C, local.D, local.A, 14, 23, 0xFDE5380C);
+    P(local.A, local.B, local.C, local.D,  1,  4, 0xA4BEEA44);
+    P(local.D, local.A, local.B, local.C,  4, 11, 0x4BDECFA9);
+    P(local.C, local.D, local.A, local.B,  7, 16, 0xF6BB4B60);
+    P(local.B, local.C, local.D, local.A, 10, 23, 0xBEBFBC70);
+    P(local.A, local.B, local.C, local.D, 13,  4, 0x289B7EC6);
+    P(local.D, local.A, local.B, local.C,  0, 11, 0xEAA127FA);
+    P(local.C, local.D, local.A, local.B,  3, 16, 0xD4EF3085);
+    P(local.B, local.C, local.D, local.A,  6, 23, 0x04881D05);
+    P(local.A, local.B, local.C, local.D,  9,  4, 0xD9D4D039);
+    P(local.D, local.A, local.B, local.C, 12, 11, 0xE6DB99E5);
+    P(local.C, local.D, local.A, local.B, 15, 16, 0x1FA27CF8);
+    P(local.B, local.C, local.D, local.A,  2, 23, 0xC4AC5665);
 
 #undef F
 
-#define F(x,y,z) ((y) ^ ((x) | ~(z)))
+#define F(x, y, z) ((y) ^ ((x) | ~(z)))
 
-    P( local.A, local.B, local.C, local.D,  0,  6, 0xF4292244 );
-    P( local.D, local.A, local.B, local.C,  7, 10, 0x432AFF97 );
-    P( local.C, local.D, local.A, local.B, 14, 15, 0xAB9423A7 );
-    P( local.B, local.C, local.D, local.A,  5, 21, 0xFC93A039 );
-    P( local.A, local.B, local.C, local.D, 12,  6, 0x655B59C3 );
-    P( local.D, local.A, local.B, local.C,  3, 10, 0x8F0CCC92 );
-    P( local.C, local.D, local.A, local.B, 10, 15, 0xFFEFF47D );
-    P( local.B, local.C, local.D, local.A,  1, 21, 0x85845DD1 );
-    P( local.A, local.B, local.C, local.D,  8,  6, 0x6FA87E4F );
-    P( local.D, local.A, local.B, local.C, 15, 10, 0xFE2CE6E0 );
-    P( local.C, local.D, local.A, local.B,  6, 15, 0xA3014314 );
-    P( local.B, local.C, local.D, local.A, 13, 21, 0x4E0811A1 );
-    P( local.A, local.B, local.C, local.D,  4,  6, 0xF7537E82 );
-    P( local.D, local.A, local.B, local.C, 11, 10, 0xBD3AF235 );
-    P( local.C, local.D, local.A, local.B,  2, 15, 0x2AD7D2BB );
-    P( local.B, local.C, local.D, local.A,  9, 21, 0xEB86D391 );
+    P(local.A, local.B, local.C, local.D,  0,  6, 0xF4292244);
+    P(local.D, local.A, local.B, local.C,  7, 10, 0x432AFF97);
+    P(local.C, local.D, local.A, local.B, 14, 15, 0xAB9423A7);
+    P(local.B, local.C, local.D, local.A,  5, 21, 0xFC93A039);
+    P(local.A, local.B, local.C, local.D, 12,  6, 0x655B59C3);
+    P(local.D, local.A, local.B, local.C,  3, 10, 0x8F0CCC92);
+    P(local.C, local.D, local.A, local.B, 10, 15, 0xFFEFF47D);
+    P(local.B, local.C, local.D, local.A,  1, 21, 0x85845DD1);
+    P(local.A, local.B, local.C, local.D,  8,  6, 0x6FA87E4F);
+    P(local.D, local.A, local.B, local.C, 15, 10, 0xFE2CE6E0);
+    P(local.C, local.D, local.A, local.B,  6, 15, 0xA3014314);
+    P(local.B, local.C, local.D, local.A, 13, 21, 0x4E0811A1);
+    P(local.A, local.B, local.C, local.D,  4,  6, 0xF7537E82);
+    P(local.D, local.A, local.B, local.C, 11, 10, 0xBD3AF235);
+    P(local.C, local.D, local.A, local.B,  2, 15, 0x2AD7D2BB);
+    P(local.B, local.C, local.D, local.A,  9, 21, 0xEB86D391);
 
 #undef F
 
@@ -216,33 +202,27 @@
     ctx->state[3] += local.D;
 
     /* Zeroise variables to clear sensitive data from memory. */
-    mbedtls_platform_zeroize( &local, sizeof( local ) );
+    mbedtls_platform_zeroize(&local, sizeof(local));
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_md5_process( mbedtls_md5_context *ctx,
-                          const unsigned char data[64] )
-{
-    mbedtls_internal_md5_process( ctx, data );
-}
-#endif
 #endif /* !MBEDTLS_MD5_PROCESS_ALT */
 
 /*
  * MD5 process buffer
  */
-int mbedtls_md5_update_ret( mbedtls_md5_context *ctx,
-                            const unsigned char *input,
-                            size_t ilen )
+int mbedtls_md5_update(mbedtls_md5_context *ctx,
+                       const unsigned char *input,
+                       size_t ilen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t fill;
     uint32_t left;
 
-    if( ilen == 0 )
-        return( 0 );
+    if (ilen == 0) {
+        return 0;
+    }
 
     left = ctx->total[0] & 0x3F;
     fill = 64 - left;
@@ -250,51 +230,42 @@
     ctx->total[0] += (uint32_t) ilen;
     ctx->total[0] &= 0xFFFFFFFF;
 
-    if( ctx->total[0] < (uint32_t) ilen )
+    if (ctx->total[0] < (uint32_t) ilen) {
         ctx->total[1]++;
+    }
 
-    if( left && ilen >= fill )
-    {
-        memcpy( (void *) (ctx->buffer + left), input, fill );
-        if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
-            return( ret );
+    if (left && ilen >= fill) {
+        memcpy((void *) (ctx->buffer + left), input, fill);
+        if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) {
+            return ret;
+        }
 
         input += fill;
         ilen  -= fill;
         left = 0;
     }
 
-    while( ilen >= 64 )
-    {
-        if( ( ret = mbedtls_internal_md5_process( ctx, input ) ) != 0 )
-            return( ret );
+    while (ilen >= 64) {
+        if ((ret = mbedtls_internal_md5_process(ctx, input)) != 0) {
+            return ret;
+        }
 
         input += 64;
         ilen  -= 64;
     }
 
-    if( ilen > 0 )
-    {
-        memcpy( (void *) (ctx->buffer + left), input, ilen );
+    if (ilen > 0) {
+        memcpy((void *) (ctx->buffer + left), input, ilen);
     }
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_md5_update( mbedtls_md5_context *ctx,
-                         const unsigned char *input,
-                         size_t ilen )
-{
-    mbedtls_md5_update_ret( ctx, input, ilen );
-}
-#endif
-
 /*
  * MD5 final digest
  */
-int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx,
-                            unsigned char output[16] )
+int mbedtls_md5_finish(mbedtls_md5_context *ctx,
+                       unsigned char output[16])
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     uint32_t used;
@@ -307,92 +278,77 @@
 
     ctx->buffer[used++] = 0x80;
 
-    if( used <= 56 )
-    {
+    if (used <= 56) {
         /* Enough room for padding + length in current block */
-        memset( ctx->buffer + used, 0, 56 - used );
-    }
-    else
-    {
+        memset(ctx->buffer + used, 0, 56 - used);
+    } else {
         /* We'll need an extra block */
-        memset( ctx->buffer + used, 0, 64 - used );
+        memset(ctx->buffer + used, 0, 64 - used);
 
-        if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
-            return( ret );
+        if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) {
+            return ret;
+        }
 
-        memset( ctx->buffer, 0, 56 );
+        memset(ctx->buffer, 0, 56);
     }
 
     /*
      * Add message length
      */
-    high = ( ctx->total[0] >> 29 )
-         | ( ctx->total[1] <<  3 );
-    low  = ( ctx->total[0] <<  3 );
+    high = (ctx->total[0] >> 29)
+           | (ctx->total[1] <<  3);
+    low  = (ctx->total[0] <<  3);
 
-    MBEDTLS_PUT_UINT32_LE( low,  ctx->buffer, 56 );
-    MBEDTLS_PUT_UINT32_LE( high, ctx->buffer, 60 );
+    MBEDTLS_PUT_UINT32_LE(low,  ctx->buffer, 56);
+    MBEDTLS_PUT_UINT32_LE(high, ctx->buffer, 60);
 
-    if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) {
+        return ret;
+    }
 
     /*
      * Output final state
      */
-    MBEDTLS_PUT_UINT32_LE( ctx->state[0], output,  0 );
-    MBEDTLS_PUT_UINT32_LE( ctx->state[1], output,  4 );
-    MBEDTLS_PUT_UINT32_LE( ctx->state[2], output,  8 );
-    MBEDTLS_PUT_UINT32_LE( ctx->state[3], output, 12 );
+    MBEDTLS_PUT_UINT32_LE(ctx->state[0], output,  0);
+    MBEDTLS_PUT_UINT32_LE(ctx->state[1], output,  4);
+    MBEDTLS_PUT_UINT32_LE(ctx->state[2], output,  8);
+    MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12);
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_md5_finish( mbedtls_md5_context *ctx,
-                         unsigned char output[16] )
-{
-    mbedtls_md5_finish_ret( ctx, output );
-}
-#endif
-
 #endif /* !MBEDTLS_MD5_ALT */
 
 /*
  * output = MD5( input buffer )
  */
-int mbedtls_md5_ret( const unsigned char *input,
-                     size_t ilen,
-                     unsigned char output[16] )
+int mbedtls_md5(const unsigned char *input,
+                size_t ilen,
+                unsigned char output[16])
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_md5_context ctx;
 
-    mbedtls_md5_init( &ctx );
+    mbedtls_md5_init(&ctx);
 
-    if( ( ret = mbedtls_md5_starts_ret( &ctx ) ) != 0 )
+    if ((ret = mbedtls_md5_starts(&ctx)) != 0) {
         goto exit;
+    }
 
-    if( ( ret = mbedtls_md5_update_ret( &ctx, input, ilen ) ) != 0 )
+    if ((ret = mbedtls_md5_update(&ctx, input, ilen)) != 0) {
         goto exit;
+    }
 
-    if( ( ret = mbedtls_md5_finish_ret( &ctx, output ) ) != 0 )
+    if ((ret = mbedtls_md5_finish(&ctx, output)) != 0) {
         goto exit;
+    }
 
 exit:
-    mbedtls_md5_free( &ctx );
+    mbedtls_md5_free(&ctx);
 
-    return( ret );
+    return ret;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_md5( const unsigned char *input,
-                  size_t ilen,
-                  unsigned char output[16] )
-{
-    mbedtls_md5_ret( input, ilen, output );
-}
-#endif
-
 #if defined(MBEDTLS_SELF_TEST)
 /*
  * RFC 1321 test vectors
@@ -434,40 +390,43 @@
 /*
  * Checkup routine
  */
-int mbedtls_md5_self_test( int verbose )
+int mbedtls_md5_self_test(int verbose)
 {
     int i, ret = 0;
     unsigned char md5sum[16];
 
-    for( i = 0; i < 7; i++ )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "  MD5 test #%d: ", i + 1 );
+    for (i = 0; i < 7; i++) {
+        if (verbose != 0) {
+            mbedtls_printf("  MD5 test #%d: ", i + 1);
+        }
 
-        ret = mbedtls_md5_ret( md5_test_buf[i], md5_test_buflen[i], md5sum );
-        if( ret != 0 )
+        ret = mbedtls_md5(md5_test_buf[i], md5_test_buflen[i], md5sum);
+        if (ret != 0) {
             goto fail;
+        }
 
-        if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
-        {
+        if (memcmp(md5sum, md5_test_sum[i], 16) != 0) {
             ret = 1;
             goto fail;
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
-    return( 0 );
+    return 0;
 
 fail:
-    if( verbose != 0 )
-        mbedtls_printf( "failed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("failed\n");
+    }
 
-    return( ret );
+    return ret;
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/lib/libmbedtls/mbedtls/library/md_wrap.h b/lib/libmbedtls/mbedtls/library/md_wrap.h
new file mode 100644
index 0000000..cd539b5
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/md_wrap.h
@@ -0,0 +1,81 @@
+/**
+ * \file md_wrap.h
+ *
+ * \brief Message digest wrappers.
+ *
+ * \warning This in an internal header. Do not include directly.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ */
+/*
+ *  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_MD_WRAP_H
+#define MBEDTLS_MD_WRAP_H
+
+#include "mbedtls/build_info.h"
+
+#include "mbedtls/md.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Message digest information.
+ * Allows message digest functions to be called in a generic way.
+ */
+struct mbedtls_md_info_t {
+    /** Name of the message digest */
+    const char *name;
+
+    /** Digest identifier */
+    mbedtls_md_type_t type;
+
+    /** Output length of the digest function in bytes */
+    unsigned char size;
+
+    /** Block length of the digest function in bytes */
+    unsigned char block_size;
+};
+
+#if defined(MBEDTLS_MD5_C)
+extern const mbedtls_md_info_t mbedtls_md5_info;
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+extern const mbedtls_md_info_t mbedtls_ripemd160_info;
+#endif
+#if defined(MBEDTLS_SHA1_C)
+extern const mbedtls_md_info_t mbedtls_sha1_info;
+#endif
+#if defined(MBEDTLS_SHA224_C)
+extern const mbedtls_md_info_t mbedtls_sha224_info;
+#endif
+#if defined(MBEDTLS_SHA256_C)
+extern const mbedtls_md_info_t mbedtls_sha256_info;
+#endif
+#if defined(MBEDTLS_SHA384_C)
+extern const mbedtls_md_info_t mbedtls_sha384_info;
+#endif
+#if defined(MBEDTLS_SHA512_C)
+extern const mbedtls_md_info_t mbedtls_sha512_info;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_MD_WRAP_H */
diff --git a/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c b/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c
index cc62324..e5052ce 100644
--- a/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c
+++ b/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c
@@ -42,8 +42,7 @@
 #define MAX_BT 20
 
 typedef struct _memory_header memory_header;
-struct _memory_header
-{
+struct _memory_header {
     size_t          magic1;
     size_t          size;
     size_t          alloc;
@@ -58,8 +57,7 @@
     size_t          magic2;
 };
 
-typedef struct
-{
+typedef struct {
     unsigned char   *buf;
     size_t          len;
     memory_header   *first;
@@ -82,146 +80,135 @@
 static buffer_alloc_ctx heap;
 
 #if defined(MBEDTLS_MEMORY_DEBUG)
-static void debug_header( memory_header *hdr )
+static void debug_header(memory_header *hdr)
 {
 #if defined(MBEDTLS_MEMORY_BACKTRACE)
     size_t i;
 #endif
 
-    mbedtls_fprintf( stderr, "HDR:  PTR(%10zu), PREV(%10zu), NEXT(%10zu), "
-                              "ALLOC(%zu), SIZE(%10zu)\n",
-                      (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next,
-                      hdr->alloc, hdr->size );
-    mbedtls_fprintf( stderr, "      FPREV(%10zu), FNEXT(%10zu)\n",
-                      (size_t) hdr->prev_free, (size_t) hdr->next_free );
+    mbedtls_fprintf(stderr, "HDR:  PTR(%10zu), PREV(%10zu), NEXT(%10zu), "
+                            "ALLOC(%zu), SIZE(%10zu)\n",
+                    (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next,
+                    hdr->alloc, hdr->size);
+    mbedtls_fprintf(stderr, "      FPREV(%10zu), FNEXT(%10zu)\n",
+                    (size_t) hdr->prev_free, (size_t) hdr->next_free);
 
 #if defined(MBEDTLS_MEMORY_BACKTRACE)
-    mbedtls_fprintf( stderr, "TRACE: \n" );
-    for( i = 0; i < hdr->trace_count; i++ )
-        mbedtls_fprintf( stderr, "%s\n", hdr->trace[i] );
-    mbedtls_fprintf( stderr, "\n" );
+    mbedtls_fprintf(stderr, "TRACE: \n");
+    for (i = 0; i < hdr->trace_count; i++) {
+        mbedtls_fprintf(stderr, "%s\n", hdr->trace[i]);
+    }
+    mbedtls_fprintf(stderr, "\n");
 #endif
 }
 
-static void debug_chain( void )
+static void debug_chain(void)
 {
     memory_header *cur = heap.first;
 
-    mbedtls_fprintf( stderr, "\nBlock list\n" );
-    while( cur != NULL )
-    {
-        debug_header( cur );
+    mbedtls_fprintf(stderr, "\nBlock list\n");
+    while (cur != NULL) {
+        debug_header(cur);
         cur = cur->next;
     }
 
-    mbedtls_fprintf( stderr, "Free list\n" );
+    mbedtls_fprintf(stderr, "Free list\n");
     cur = heap.first_free;
 
-    while( cur != NULL )
-    {
-        debug_header( cur );
+    while (cur != NULL) {
+        debug_header(cur);
         cur = cur->next_free;
     }
 }
 #endif /* MBEDTLS_MEMORY_DEBUG */
 
-static int verify_header( memory_header *hdr )
+static int verify_header(memory_header *hdr)
 {
-    if( hdr->magic1 != MAGIC1 )
-    {
+    if (hdr->magic1 != MAGIC1) {
 #if defined(MBEDTLS_MEMORY_DEBUG)
-        mbedtls_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" );
+        mbedtls_fprintf(stderr, "FATAL: MAGIC1 mismatch\n");
 #endif
-        return( 1 );
+        return 1;
     }
 
-    if( hdr->magic2 != MAGIC2 )
-    {
+    if (hdr->magic2 != MAGIC2) {
 #if defined(MBEDTLS_MEMORY_DEBUG)
-        mbedtls_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" );
+        mbedtls_fprintf(stderr, "FATAL: MAGIC2 mismatch\n");
 #endif
-        return( 1 );
+        return 1;
     }
 
-    if( hdr->alloc > 1 )
-    {
+    if (hdr->alloc > 1) {
 #if defined(MBEDTLS_MEMORY_DEBUG)
-        mbedtls_fprintf( stderr, "FATAL: alloc has illegal value\n" );
+        mbedtls_fprintf(stderr, "FATAL: alloc has illegal value\n");
 #endif
-        return( 1 );
+        return 1;
     }
 
-    if( hdr->prev != NULL && hdr->prev == hdr->next )
-    {
+    if (hdr->prev != NULL && hdr->prev == hdr->next) {
 #if defined(MBEDTLS_MEMORY_DEBUG)
-        mbedtls_fprintf( stderr, "FATAL: prev == next\n" );
+        mbedtls_fprintf(stderr, "FATAL: prev == next\n");
 #endif
-        return( 1 );
+        return 1;
     }
 
-    if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free )
-    {
+    if (hdr->prev_free != NULL && hdr->prev_free == hdr->next_free) {
 #if defined(MBEDTLS_MEMORY_DEBUG)
-        mbedtls_fprintf( stderr, "FATAL: prev_free == next_free\n" );
+        mbedtls_fprintf(stderr, "FATAL: prev_free == next_free\n");
 #endif
-        return( 1 );
+        return 1;
     }
 
-    return( 0 );
+    return 0;
 }
 
-static int verify_chain( void )
+static int verify_chain(void)
 {
     memory_header *prv = heap.first, *cur;
 
-    if( prv == NULL || verify_header( prv ) != 0 )
-    {
+    if (prv == NULL || verify_header(prv) != 0) {
 #if defined(MBEDTLS_MEMORY_DEBUG)
-        mbedtls_fprintf( stderr, "FATAL: verification of first header "
-                                  "failed\n" );
+        mbedtls_fprintf(stderr, "FATAL: verification of first header "
+                                "failed\n");
 #endif
-        return( 1 );
+        return 1;
     }
 
-    if( heap.first->prev != NULL )
-    {
+    if (heap.first->prev != NULL) {
 #if defined(MBEDTLS_MEMORY_DEBUG)
-        mbedtls_fprintf( stderr, "FATAL: verification failed: "
-                                  "first->prev != NULL\n" );
+        mbedtls_fprintf(stderr, "FATAL: verification failed: "
+                                "first->prev != NULL\n");
 #endif
-        return( 1 );
+        return 1;
     }
 
     cur = heap.first->next;
 
-    while( cur != NULL )
-    {
-        if( verify_header( cur ) != 0 )
-        {
+    while (cur != NULL) {
+        if (verify_header(cur) != 0) {
 #if defined(MBEDTLS_MEMORY_DEBUG)
-            mbedtls_fprintf( stderr, "FATAL: verification of header "
-                                      "failed\n" );
+            mbedtls_fprintf(stderr, "FATAL: verification of header "
+                                    "failed\n");
 #endif
-            return( 1 );
+            return 1;
         }
 
-        if( cur->prev != prv )
-        {
+        if (cur->prev != prv) {
 #if defined(MBEDTLS_MEMORY_DEBUG)
-            mbedtls_fprintf( stderr, "FATAL: verification failed: "
-                                      "cur->prev != prv\n" );
+            mbedtls_fprintf(stderr, "FATAL: verification failed: "
+                                    "cur->prev != prv\n");
 #endif
-            return( 1 );
+            return 1;
         }
 
         prv = cur;
         cur = cur->next;
     }
 
-    return( 0 );
+    return 0;
 }
 
-static void *buffer_alloc_calloc( size_t n, size_t size )
+static void *buffer_alloc_calloc(size_t n, size_t size)
 {
     memory_header *new, *cur = heap.first_free;
     unsigned char *p;
@@ -232,42 +219,43 @@
     size_t trace_cnt;
 #endif
 
-    if( heap.buf == NULL || heap.first == NULL )
-        return( NULL );
+    if (heap.buf == NULL || heap.first == NULL) {
+        return NULL;
+    }
 
     original_len = len = n * size;
 
-    if( n == 0 || size == 0 || len / n != size )
-        return( NULL );
-    else if( len > (size_t)-MBEDTLS_MEMORY_ALIGN_MULTIPLE )
-        return( NULL );
+    if (n == 0 || size == 0 || len / n != size) {
+        return NULL;
+    } else if (len > (size_t) -MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
+        return NULL;
+    }
 
-    if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE )
-    {
+    if (len % MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
         len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
         len += MBEDTLS_MEMORY_ALIGN_MULTIPLE;
     }
 
     // Find block that fits
     //
-    while( cur != NULL )
-    {
-        if( cur->size >= len )
+    while (cur != NULL) {
+        if (cur->size >= len) {
             break;
+        }
 
         cur = cur->next_free;
     }
 
-    if( cur == NULL )
-        return( NULL );
+    if (cur == NULL) {
+        return NULL;
+    }
 
-    if( cur->alloc != 0 )
-    {
+    if (cur->alloc != 0) {
 #if defined(MBEDTLS_MEMORY_DEBUG)
-        mbedtls_fprintf( stderr, "FATAL: block in free_list but allocated "
-                                  "data\n" );
+        mbedtls_fprintf(stderr, "FATAL: block in free_list but allocated "
+                                "data\n");
 #endif
-        mbedtls_exit( 1 );
+        mbedtls_exit(1);
     }
 
 #if defined(MBEDTLS_MEMORY_DEBUG)
@@ -276,45 +264,48 @@
 
     // Found location, split block if > memory_header + 4 room left
     //
-    if( cur->size - len < sizeof(memory_header) +
-                          MBEDTLS_MEMORY_ALIGN_MULTIPLE )
-    {
+    if (cur->size - len < sizeof(memory_header) +
+        MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
         cur->alloc = 1;
 
         // Remove from free_list
         //
-        if( cur->prev_free != NULL )
+        if (cur->prev_free != NULL) {
             cur->prev_free->next_free = cur->next_free;
-        else
+        } else {
             heap.first_free = cur->next_free;
+        }
 
-        if( cur->next_free != NULL )
+        if (cur->next_free != NULL) {
             cur->next_free->prev_free = cur->prev_free;
+        }
 
         cur->prev_free = NULL;
         cur->next_free = NULL;
 
 #if defined(MBEDTLS_MEMORY_DEBUG)
         heap.total_used += cur->size;
-        if( heap.total_used > heap.maximum_used )
+        if (heap.total_used > heap.maximum_used) {
             heap.maximum_used = heap.total_used;
+        }
 #endif
 #if defined(MBEDTLS_MEMORY_BACKTRACE)
-        trace_cnt = backtrace( trace_buffer, MAX_BT );
-        cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
+        trace_cnt = backtrace(trace_buffer, MAX_BT);
+        cur->trace = backtrace_symbols(trace_buffer, trace_cnt);
         cur->trace_count = trace_cnt;
 #endif
 
-        if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
-            mbedtls_exit( 1 );
+        if ((heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC) && verify_chain() != 0) {
+            mbedtls_exit(1);
+        }
 
-        ret = (unsigned char *) cur + sizeof( memory_header );
-        memset( ret, 0, original_len );
+        ret = (unsigned char *) cur + sizeof(memory_header);
+        memset(ret, 0, original_len);
 
-        return( ret );
+        return ret;
     }
 
-    p = ( (unsigned char *) cur ) + sizeof(memory_header) + len;
+    p = ((unsigned char *) cur) + sizeof(memory_header) + len;
     new = (memory_header *) p;
 
     new->size = cur->size - len - sizeof(memory_header);
@@ -328,20 +319,23 @@
     new->magic1 = MAGIC1;
     new->magic2 = MAGIC2;
 
-    if( new->next != NULL )
+    if (new->next != NULL) {
         new->next->prev = new;
+    }
 
     // Replace cur with new in free_list
     //
     new->prev_free = cur->prev_free;
     new->next_free = cur->next_free;
-    if( new->prev_free != NULL )
+    if (new->prev_free != NULL) {
         new->prev_free->next_free = new;
-    else
+    } else {
         heap.first_free = new;
+    }
 
-    if( new->next_free != NULL )
+    if (new->next_free != NULL) {
         new->next_free->prev_free = new;
+    }
 
     cur->alloc = 1;
     cur->size = len;
@@ -351,57 +345,60 @@
 
 #if defined(MBEDTLS_MEMORY_DEBUG)
     heap.header_count++;
-    if( heap.header_count > heap.maximum_header_count )
+    if (heap.header_count > heap.maximum_header_count) {
         heap.maximum_header_count = heap.header_count;
+    }
     heap.total_used += cur->size;
-    if( heap.total_used > heap.maximum_used )
+    if (heap.total_used > heap.maximum_used) {
         heap.maximum_used = heap.total_used;
+    }
 #endif
 #if defined(MBEDTLS_MEMORY_BACKTRACE)
-    trace_cnt = backtrace( trace_buffer, MAX_BT );
-    cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
+    trace_cnt = backtrace(trace_buffer, MAX_BT);
+    cur->trace = backtrace_symbols(trace_buffer, trace_cnt);
     cur->trace_count = trace_cnt;
 #endif
 
-    if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
-        mbedtls_exit( 1 );
+    if ((heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC) && verify_chain() != 0) {
+        mbedtls_exit(1);
+    }
 
-    ret = (unsigned char *) cur + sizeof( memory_header );
-    memset( ret, 0, original_len );
+    ret = (unsigned char *) cur + sizeof(memory_header);
+    memset(ret, 0, original_len);
 
-    return( ret );
+    return ret;
 }
 
-static void buffer_alloc_free( void *ptr )
+static void buffer_alloc_free(void *ptr)
 {
     memory_header *hdr, *old = NULL;
     unsigned char *p = (unsigned char *) ptr;
 
-    if( ptr == NULL || heap.buf == NULL || heap.first == NULL )
+    if (ptr == NULL || heap.buf == NULL || heap.first == NULL) {
         return;
+    }
 
-    if( p < heap.buf || p >= heap.buf + heap.len )
-    {
+    if (p < heap.buf || p >= heap.buf + heap.len) {
 #if defined(MBEDTLS_MEMORY_DEBUG)
-        mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed "
-                                  "space\n" );
+        mbedtls_fprintf(stderr, "FATAL: mbedtls_free() outside of managed "
+                                "space\n");
 #endif
-        mbedtls_exit( 1 );
+        mbedtls_exit(1);
     }
 
     p -= sizeof(memory_header);
     hdr = (memory_header *) p;
 
-    if( verify_header( hdr ) != 0 )
-        mbedtls_exit( 1 );
+    if (verify_header(hdr) != 0) {
+        mbedtls_exit(1);
+    }
 
-    if( hdr->alloc != 1 )
-    {
+    if (hdr->alloc != 1) {
 #if defined(MBEDTLS_MEMORY_DEBUG)
-        mbedtls_fprintf( stderr, "FATAL: mbedtls_free() on unallocated "
-                                  "data\n" );
+        mbedtls_fprintf(stderr, "FATAL: mbedtls_free() on unallocated "
+                                "data\n");
 #endif
-        mbedtls_exit( 1 );
+        mbedtls_exit(1);
     }
 
     hdr->alloc = 0;
@@ -412,15 +409,14 @@
 #endif
 
 #if defined(MBEDTLS_MEMORY_BACKTRACE)
-    free( hdr->trace );
+    free(hdr->trace);
     hdr->trace = NULL;
     hdr->trace_count = 0;
 #endif
 
     // Regroup with block before
     //
-    if( hdr->prev != NULL && hdr->prev->alloc == 0 )
-    {
+    if (hdr->prev != NULL && hdr->prev->alloc == 0) {
 #if defined(MBEDTLS_MEMORY_DEBUG)
         heap.header_count--;
 #endif
@@ -429,16 +425,16 @@
         old = hdr;
         hdr = hdr->prev;
 
-        if( hdr->next != NULL )
+        if (hdr->next != NULL) {
             hdr->next->prev = hdr;
+        }
 
-        memset( old, 0, sizeof(memory_header) );
+        memset(old, 0, sizeof(memory_header));
     }
 
     // Regroup with block after
     //
-    if( hdr->next != NULL && hdr->next->alloc == 0 )
-    {
+    if (hdr->next != NULL && hdr->next->alloc == 0) {
 #if defined(MBEDTLS_MEMORY_DEBUG)
         heap.header_count--;
 #endif
@@ -446,95 +442,103 @@
         old = hdr->next;
         hdr->next = hdr->next->next;
 
-        if( hdr->prev_free != NULL || hdr->next_free != NULL )
-        {
-            if( hdr->prev_free != NULL )
+        if (hdr->prev_free != NULL || hdr->next_free != NULL) {
+            if (hdr->prev_free != NULL) {
                 hdr->prev_free->next_free = hdr->next_free;
-            else
+            } else {
                 heap.first_free = hdr->next_free;
+            }
 
-            if( hdr->next_free != NULL )
+            if (hdr->next_free != NULL) {
                 hdr->next_free->prev_free = hdr->prev_free;
+            }
         }
 
         hdr->prev_free = old->prev_free;
         hdr->next_free = old->next_free;
 
-        if( hdr->prev_free != NULL )
+        if (hdr->prev_free != NULL) {
             hdr->prev_free->next_free = hdr;
-        else
+        } else {
             heap.first_free = hdr;
+        }
 
-        if( hdr->next_free != NULL )
+        if (hdr->next_free != NULL) {
             hdr->next_free->prev_free = hdr;
+        }
 
-        if( hdr->next != NULL )
+        if (hdr->next != NULL) {
             hdr->next->prev = hdr;
+        }
 
-        memset( old, 0, sizeof(memory_header) );
+        memset(old, 0, sizeof(memory_header));
     }
 
     // Prepend to free_list if we have not merged
     // (Does not have to stay in same order as prev / next list)
     //
-    if( old == NULL )
-    {
+    if (old == NULL) {
         hdr->next_free = heap.first_free;
-        if( heap.first_free != NULL )
+        if (heap.first_free != NULL) {
             heap.first_free->prev_free = hdr;
+        }
         heap.first_free = hdr;
     }
 
-    if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_FREE ) && verify_chain() != 0 )
-        mbedtls_exit( 1 );
+    if ((heap.verify & MBEDTLS_MEMORY_VERIFY_FREE) && verify_chain() != 0) {
+        mbedtls_exit(1);
+    }
 }
 
-void mbedtls_memory_buffer_set_verify( int verify )
+void mbedtls_memory_buffer_set_verify(int verify)
 {
     heap.verify = verify;
 }
 
-int mbedtls_memory_buffer_alloc_verify( void )
+int mbedtls_memory_buffer_alloc_verify(void)
 {
     return verify_chain();
 }
 
 #if defined(MBEDTLS_MEMORY_DEBUG)
-void mbedtls_memory_buffer_alloc_status( void )
+void mbedtls_memory_buffer_alloc_status(void)
 {
-    mbedtls_fprintf( stderr,
-                      "Current use: %zu blocks / %zu bytes, max: %zu blocks / "
-                      "%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n",
-                      heap.header_count, heap.total_used,
-                      heap.maximum_header_count, heap.maximum_used,
-                      heap.maximum_header_count * sizeof( memory_header )
-                      + heap.maximum_used,
-                      heap.alloc_count, heap.free_count );
+    mbedtls_fprintf(stderr,
+                    "Current use: %zu blocks / %zu bytes, max: %zu blocks / "
+                    "%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n",
+                    heap.header_count, heap.total_used,
+                    heap.maximum_header_count, heap.maximum_used,
+                    heap.maximum_header_count * sizeof(memory_header)
+                    + heap.maximum_used,
+                    heap.alloc_count, heap.free_count);
 
-    if( heap.first->next == NULL )
-    {
-        mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" );
-    }
-    else
-    {
-        mbedtls_fprintf( stderr, "Memory currently allocated:\n" );
+    if (heap.first->next == NULL) {
+        mbedtls_fprintf(stderr, "All memory de-allocated in stack buffer\n");
+    } else {
+        mbedtls_fprintf(stderr, "Memory currently allocated:\n");
         debug_chain();
     }
 }
 
-void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks )
+void mbedtls_memory_buffer_alloc_count_get(size_t *alloc_count, size_t *free_count)
+{
+    *alloc_count = heap.alloc_count;
+    *free_count = heap.free_count;
+}
+
+void mbedtls_memory_buffer_alloc_max_get(size_t *max_used, size_t *max_blocks)
 {
     *max_used   = heap.maximum_used;
     *max_blocks = heap.maximum_header_count;
 }
 
-void mbedtls_memory_buffer_alloc_max_reset( void )
+void mbedtls_memory_buffer_alloc_max_reset(void)
 {
     heap.maximum_used = 0;
     heap.maximum_header_count = 0;
 }
 
-void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks )
+void mbedtls_memory_buffer_alloc_cur_get(size_t *cur_used, size_t *cur_blocks)
 {
     *cur_used   = heap.total_used;
     *cur_blocks = heap.header_count;
@@ -542,202 +546,211 @@
 #endif /* MBEDTLS_MEMORY_DEBUG */
 
 #if defined(MBEDTLS_THREADING_C)
-static void *buffer_alloc_calloc_mutexed( size_t n, size_t size )
+static void *buffer_alloc_calloc_mutexed(size_t n, size_t size)
 {
     void *buf;
-    if( mbedtls_mutex_lock( &heap.mutex ) != 0 )
-        return( NULL );
-    buf = buffer_alloc_calloc( n, size );
-    if( mbedtls_mutex_unlock( &heap.mutex ) )
-        return( NULL );
-    return( buf );
+    if (mbedtls_mutex_lock(&heap.mutex) != 0) {
+        return NULL;
+    }
+    buf = buffer_alloc_calloc(n, size);
+    if (mbedtls_mutex_unlock(&heap.mutex)) {
+        return NULL;
+    }
+    return buf;
 }
 
-static void buffer_alloc_free_mutexed( void *ptr )
+static void buffer_alloc_free_mutexed(void *ptr)
 {
     /* We have no good option here, but corrupting the heap seems
      * worse than losing memory. */
-    if( mbedtls_mutex_lock( &heap.mutex ) )
+    if (mbedtls_mutex_lock(&heap.mutex)) {
         return;
-    buffer_alloc_free( ptr );
-    (void) mbedtls_mutex_unlock( &heap.mutex );
+    }
+    buffer_alloc_free(ptr);
+    (void) mbedtls_mutex_unlock(&heap.mutex);
 }
 #endif /* MBEDTLS_THREADING_C */
 
-void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len )
+void mbedtls_memory_buffer_alloc_init(unsigned char *buf, size_t len)
 {
-    memset( &heap, 0, sizeof( buffer_alloc_ctx ) );
+    memset(&heap, 0, sizeof(buffer_alloc_ctx));
 
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_init( &heap.mutex );
-    mbedtls_platform_set_calloc_free( buffer_alloc_calloc_mutexed,
-                              buffer_alloc_free_mutexed );
+    mbedtls_mutex_init(&heap.mutex);
+    mbedtls_platform_set_calloc_free(buffer_alloc_calloc_mutexed,
+                                     buffer_alloc_free_mutexed);
 #else
-    mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free );
+    mbedtls_platform_set_calloc_free(buffer_alloc_calloc, buffer_alloc_free);
 #endif
 
-    if( len < sizeof( memory_header ) + MBEDTLS_MEMORY_ALIGN_MULTIPLE )
+    if (len < sizeof(memory_header) + MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
         return;
-    else if( (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE )
-    {
+    } else if ((size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
         /* Adjust len first since buf is used in the computation */
         len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE
-             - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
+               - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
         buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE
-             - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
+               - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
     }
 
-    memset( buf, 0, len );
+    memset(buf, 0, len);
 
     heap.buf = buf;
     heap.len = len;
 
-    heap.first = (memory_header *)buf;
-    heap.first->size = len - sizeof( memory_header );
+    heap.first = (memory_header *) buf;
+    heap.first->size = len - sizeof(memory_header);
     heap.first->magic1 = MAGIC1;
     heap.first->magic2 = MAGIC2;
     heap.first_free = heap.first;
 }
 
-void mbedtls_memory_buffer_alloc_free( void )
+void mbedtls_memory_buffer_alloc_free(void)
 {
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_free( &heap.mutex );
+    mbedtls_mutex_free(&heap.mutex);
 #endif
-    mbedtls_platform_zeroize( &heap, sizeof(buffer_alloc_ctx) );
+    mbedtls_platform_zeroize(&heap, sizeof(buffer_alloc_ctx));
 }
 
 #if defined(MBEDTLS_SELF_TEST)
-static int check_pointer( void *p )
+static int check_pointer(void *p)
 {
-    if( p == NULL )
-        return( -1 );
+    if (p == NULL) {
+        return -1;
+    }
 
-    if( (size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0 )
-        return( -1 );
+    if ((size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0) {
+        return -1;
+    }
 
-    return( 0 );
+    return 0;
 }
 
-static int check_all_free( void )
+static int check_all_free(void)
 {
-    if(
+    if (
 #if defined(MBEDTLS_MEMORY_DEBUG)
         heap.total_used != 0 ||
 #endif
         heap.first != heap.first_free ||
-        (void *) heap.first != (void *) heap.buf )
-    {
-        return( -1 );
+        (void *) heap.first != (void *) heap.buf) {
+        return -1;
     }
 
-    return( 0 );
+    return 0;
 }
 
-#define TEST_ASSERT( condition )            \
-    if( ! (condition) )                     \
+#define TEST_ASSERT(condition)            \
+    if (!(condition))                     \
     {                                       \
-        if( verbose != 0 )                  \
-            mbedtls_printf( "failed\n" );  \
+        if (verbose != 0)                  \
+        mbedtls_printf("failed\n");  \
                                             \
         ret = 1;                            \
         goto cleanup;                       \
     }
 
-int mbedtls_memory_buffer_alloc_self_test( int verbose )
+int mbedtls_memory_buffer_alloc_self_test(int verbose)
 {
     unsigned char buf[1024];
     unsigned char *p, *q, *r, *end;
     int ret = 0;
 
-    if( verbose != 0 )
-        mbedtls_printf( "  MBA test #1 (basic alloc-free cycle): " );
+    if (verbose != 0) {
+        mbedtls_printf("  MBA test #1 (basic alloc-free cycle): ");
+    }
 
-    mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
+    mbedtls_memory_buffer_alloc_init(buf, sizeof(buf));
 
-    p = mbedtls_calloc( 1, 1 );
-    q = mbedtls_calloc( 1, 128 );
-    r = mbedtls_calloc( 1, 16 );
+    p = mbedtls_calloc(1, 1);
+    q = mbedtls_calloc(1, 128);
+    r = mbedtls_calloc(1, 16);
 
-    TEST_ASSERT( check_pointer( p ) == 0 &&
-                 check_pointer( q ) == 0 &&
-                 check_pointer( r ) == 0 );
+    TEST_ASSERT(check_pointer(p) == 0 &&
+                check_pointer(q) == 0 &&
+                check_pointer(r) == 0);
 
-    mbedtls_free( r );
-    mbedtls_free( q );
-    mbedtls_free( p );
+    mbedtls_free(r);
+    mbedtls_free(q);
+    mbedtls_free(p);
 
-    TEST_ASSERT( check_all_free( ) == 0 );
+    TEST_ASSERT(check_all_free() == 0);
 
     /* Memorize end to compare with the next test */
     end = heap.buf + heap.len;
 
-    mbedtls_memory_buffer_alloc_free( );
+    mbedtls_memory_buffer_alloc_free();
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
 
-    if( verbose != 0 )
-        mbedtls_printf( "  MBA test #2 (buf not aligned): " );
+    if (verbose != 0) {
+        mbedtls_printf("  MBA test #2 (buf not aligned): ");
+    }
 
-    mbedtls_memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 );
+    mbedtls_memory_buffer_alloc_init(buf + 1, sizeof(buf) - 1);
 
-    TEST_ASSERT( heap.buf + heap.len == end );
+    TEST_ASSERT(heap.buf + heap.len == end);
 
-    p = mbedtls_calloc( 1, 1 );
-    q = mbedtls_calloc( 1, 128 );
-    r = mbedtls_calloc( 1, 16 );
+    p = mbedtls_calloc(1, 1);
+    q = mbedtls_calloc(1, 128);
+    r = mbedtls_calloc(1, 16);
 
-    TEST_ASSERT( check_pointer( p ) == 0 &&
-                 check_pointer( q ) == 0 &&
-                 check_pointer( r ) == 0 );
+    TEST_ASSERT(check_pointer(p) == 0 &&
+                check_pointer(q) == 0 &&
+                check_pointer(r) == 0);
 
-    mbedtls_free( r );
-    mbedtls_free( q );
-    mbedtls_free( p );
+    mbedtls_free(r);
+    mbedtls_free(q);
+    mbedtls_free(p);
 
-    TEST_ASSERT( check_all_free( ) == 0 );
+    TEST_ASSERT(check_all_free() == 0);
 
-    mbedtls_memory_buffer_alloc_free( );
+    mbedtls_memory_buffer_alloc_free();
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
 
-    if( verbose != 0 )
-        mbedtls_printf( "  MBA test #3 (full): " );
+    if (verbose != 0) {
+        mbedtls_printf("  MBA test #3 (full): ");
+    }
 
-    mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
+    mbedtls_memory_buffer_alloc_init(buf, sizeof(buf));
 
-    p = mbedtls_calloc( 1, sizeof( buf ) - sizeof( memory_header ) );
+    p = mbedtls_calloc(1, sizeof(buf) - sizeof(memory_header));
 
-    TEST_ASSERT( check_pointer( p ) == 0 );
-    TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL );
+    TEST_ASSERT(check_pointer(p) == 0);
+    TEST_ASSERT(mbedtls_calloc(1, 1) == NULL);
 
-    mbedtls_free( p );
+    mbedtls_free(p);
 
-    p = mbedtls_calloc( 1, sizeof( buf ) - 2 * sizeof( memory_header ) - 16 );
-    q = mbedtls_calloc( 1, 16 );
+    p = mbedtls_calloc(1, sizeof(buf) - 2 * sizeof(memory_header) - 16);
+    q = mbedtls_calloc(1, 16);
 
-    TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 );
-    TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL );
+    TEST_ASSERT(check_pointer(p) == 0 && check_pointer(q) == 0);
+    TEST_ASSERT(mbedtls_calloc(1, 1) == NULL);
 
-    mbedtls_free( q );
+    mbedtls_free(q);
 
-    TEST_ASSERT( mbedtls_calloc( 1, 17 ) == NULL );
+    TEST_ASSERT(mbedtls_calloc(1, 17) == NULL);
 
-    mbedtls_free( p );
+    mbedtls_free(p);
 
-    TEST_ASSERT( check_all_free( ) == 0 );
+    TEST_ASSERT(check_all_free() == 0);
 
-    mbedtls_memory_buffer_alloc_free( );
+    mbedtls_memory_buffer_alloc_free();
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
 
 cleanup:
-    mbedtls_memory_buffer_alloc_free( );
+    mbedtls_memory_buffer_alloc_free();
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_SELF_TEST */
 
diff --git a/lib/libmbedtls/mbedtls/library/net_sockets.c b/lib/libmbedtls/mbedtls/library/net_sockets.c
index 8c765e1..e63d08b 100644
--- a/lib/libmbedtls/mbedtls/library/net_sockets.c
+++ b/lib/libmbedtls/mbedtls/library/net_sockets.c
@@ -18,7 +18,7 @@
  */
 
 /* Enable definition of getaddrinfo() even when compiling with -std=c99. Must
- * be set before config.h, which pulls in glibc's features.h indirectly.
+ * be set before mbedtls_config.h, which pulls in glibc's features.h indirectly.
  * Harmless on other platforms. */
 #ifndef _POSIX_C_SOURCE
 #define _POSIX_C_SOURCE 200112L
@@ -34,14 +34,10 @@
 #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
     !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
     !defined(__HAIKU__) && !defined(__midipix__)
-#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h"
+#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in mbedtls_config.h"
 #endif
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#endif
 
 #include "mbedtls/net_sockets.h"
 #include "mbedtls/error.h"
@@ -51,7 +47,7 @@
 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
     !defined(EFI32)
 
-#define IS_EINTR( ret ) ( ( ret ) == WSAEINTR )
+#define IS_EINTR(ret) ((ret) == WSAEINTR)
 
 #if !defined(_WIN32_WINNT)
 /* Enables getaddrinfo() & Co */
@@ -74,8 +70,8 @@
 #endif
 #endif /* _MSC_VER */
 
-#define read(fd,buf,len)        recv( fd, (char*)( buf ), (int)( len ), 0 )
-#define write(fd,buf,len)       send( fd, (char*)( buf ), (int)( len ), 0 )
+#define read(fd, buf, len)        recv(fd, (char *) (buf), (int) (len), 0)
+#define write(fd, buf, len)       send(fd, (char *) (buf), (int) (len), 0)
 #define close(fd)               closesocket(fd)
 
 static int wsa_init_done = 0;
@@ -93,7 +89,7 @@
 #include <netdb.h>
 #include <errno.h>
 
-#define IS_EINTR( ret ) ( ( ret ) == EINTR )
+#define IS_EINTR(ret) ((ret) == EINTR)
 
 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
 
@@ -116,25 +112,25 @@
 /*
  * Prepare for using the sockets interface
  */
-static int net_prepare( void )
+static int net_prepare(void)
 {
-#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
     !defined(EFI32)
     WSADATA wsaData;
 
-    if( wsa_init_done == 0 )
-    {
-        if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
-            return( MBEDTLS_ERR_NET_SOCKET_FAILED );
+    if (wsa_init_done == 0) {
+        if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
+            return MBEDTLS_ERR_NET_SOCKET_FAILED;
+        }
 
         wsa_init_done = 1;
     }
 #else
 #if !defined(EFIX64) && !defined(EFI32)
-    signal( SIGPIPE, SIG_IGN );
+    signal(SIGPIPE, SIG_IGN);
 #endif
 #endif
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -142,10 +138,11 @@
  * If for_select != 0, check whether the file descriptor is within the range
  * allowed for fd_set used for the FD_xxx macros and the select() function.
  */
-static int check_fd( int fd, int for_select )
+static int check_fd(int fd, int for_select)
 {
-    if( fd < 0 )
-        return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+    if (fd < 0) {
+        return MBEDTLS_ERR_NET_INVALID_CONTEXT;
+    }
 
 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
     !defined(EFI32)
@@ -155,17 +152,18 @@
      * that are strictly less than FD_SETSIZE. This is a limitation of the
      * fd_set type. Error out early, because attempting to call FD_SET on a
      * large file descriptor is a buffer overflow on typical platforms. */
-    if( for_select && fd >= FD_SETSIZE )
-        return( MBEDTLS_ERR_NET_POLL_FAILED );
+    if (for_select && fd >= FD_SETSIZE) {
+        return MBEDTLS_ERR_NET_POLL_FAILED;
+    }
 #endif
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Initialize a context
  */
-void mbedtls_net_init( mbedtls_net_context *ctx )
+void mbedtls_net_init(mbedtls_net_context *ctx)
 {
     ctx->fd = -1;
 }
@@ -173,107 +171,103 @@
 /*
  * Initiate a TCP connection with host:port and the given protocol
  */
-int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host,
-                         const char *port, int proto )
+int mbedtls_net_connect(mbedtls_net_context *ctx, const char *host,
+                        const char *port, int proto)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     struct addrinfo hints, *addr_list, *cur;
 
-    if( ( ret = net_prepare() ) != 0 )
-        return( ret );
+    if ((ret = net_prepare()) != 0) {
+        return ret;
+    }
 
     /* Do name resolution with both IPv6 and IPv4 */
-    memset( &hints, 0, sizeof( hints ) );
+    memset(&hints, 0, sizeof(hints));
     hints.ai_family = AF_UNSPEC;
     hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
     hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
 
-    if( getaddrinfo( host, port, &hints, &addr_list ) != 0 )
-        return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
+    if (getaddrinfo(host, port, &hints, &addr_list) != 0) {
+        return MBEDTLS_ERR_NET_UNKNOWN_HOST;
+    }
 
     /* Try the sockaddrs until a connection succeeds */
     ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
-    for( cur = addr_list; cur != NULL; cur = cur->ai_next )
-    {
-        ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
-                            cur->ai_protocol );
-        if( ctx->fd < 0 )
-        {
+    for (cur = addr_list; cur != NULL; cur = cur->ai_next) {
+        ctx->fd = (int) socket(cur->ai_family, cur->ai_socktype,
+                               cur->ai_protocol);
+        if (ctx->fd < 0) {
             ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
             continue;
         }
 
-        if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 )
-        {
+        if (connect(ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen) == 0) {
             ret = 0;
             break;
         }
 
-        close( ctx->fd );
+        close(ctx->fd);
         ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
     }
 
-    freeaddrinfo( addr_list );
+    freeaddrinfo(addr_list);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Create a listening socket on bind_ip:port
  */
-int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto )
+int mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto)
 {
     int n, ret;
     struct addrinfo hints, *addr_list, *cur;
 
-    if( ( ret = net_prepare() ) != 0 )
-        return( ret );
+    if ((ret = net_prepare()) != 0) {
+        return ret;
+    }
 
     /* Bind to IPv6 and/or IPv4, but only in the desired protocol */
-    memset( &hints, 0, sizeof( hints ) );
+    memset(&hints, 0, sizeof(hints));
     hints.ai_family = AF_UNSPEC;
     hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
     hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
-    if( bind_ip == NULL )
+    if (bind_ip == NULL) {
         hints.ai_flags = AI_PASSIVE;
+    }
 
-    if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 )
-        return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
+    if (getaddrinfo(bind_ip, port, &hints, &addr_list) != 0) {
+        return MBEDTLS_ERR_NET_UNKNOWN_HOST;
+    }
 
     /* Try the sockaddrs until a binding succeeds */
     ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
-    for( cur = addr_list; cur != NULL; cur = cur->ai_next )
-    {
-        ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
-                            cur->ai_protocol );
-        if( ctx->fd < 0 )
-        {
+    for (cur = addr_list; cur != NULL; cur = cur->ai_next) {
+        ctx->fd = (int) socket(cur->ai_family, cur->ai_socktype,
+                               cur->ai_protocol);
+        if (ctx->fd < 0) {
             ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
             continue;
         }
 
         n = 1;
-        if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR,
-                        (const char *) &n, sizeof( n ) ) != 0 )
-        {
-            close( ctx->fd );
+        if (setsockopt(ctx->fd, SOL_SOCKET, SO_REUSEADDR,
+                       (const char *) &n, sizeof(n)) != 0) {
+            close(ctx->fd);
             ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
             continue;
         }
 
-        if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 )
-        {
-            close( ctx->fd );
+        if (bind(ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen) != 0) {
+            close(ctx->fd);
             ret = MBEDTLS_ERR_NET_BIND_FAILED;
             continue;
         }
 
         /* Listen only makes sense for TCP */
-        if( proto == MBEDTLS_NET_PROTO_TCP )
-        {
-            if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 )
-            {
-                close( ctx->fd );
+        if (proto == MBEDTLS_NET_PROTO_TCP) {
+            if (listen(ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG) != 0) {
+                close(ctx->fd);
                 ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
                 continue;
             }
@@ -284,22 +278,22 @@
         break;
     }
 
-    freeaddrinfo( addr_list );
+    freeaddrinfo(addr_list);
 
-    return( ret );
+    return ret;
 
 }
 
-#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
     !defined(EFI32)
 /*
  * Check if the requested operation would be blocking on a non-blocking socket
  * and thus 'failed' with a negative return value.
  */
-static int net_would_block( const mbedtls_net_context *ctx )
+static int net_would_block(const mbedtls_net_context *ctx)
 {
     ((void) ctx);
-    return( WSAGetLastError() == WSAEWOULDBLOCK );
+    return WSAGetLastError() == WSAEWOULDBLOCK;
 }
 #else
 /*
@@ -308,39 +302,37 @@
  *
  * Note: on a blocking socket this function always returns 0!
  */
-static int net_would_block( const mbedtls_net_context *ctx )
+static int net_would_block(const mbedtls_net_context *ctx)
 {
     int err = errno;
 
     /*
      * Never return 'WOULD BLOCK' on a blocking socket
      */
-    if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK )
-    {
+    if ((fcntl(ctx->fd, F_GETFL) & O_NONBLOCK) != O_NONBLOCK) {
         errno = err;
-        return( 0 );
+        return 0;
     }
 
-    switch( errno = err )
-    {
+    switch (errno = err) {
 #if defined EAGAIN
         case EAGAIN:
 #endif
 #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
         case EWOULDBLOCK:
 #endif
-            return( 1 );
+    return 1;
     }
-    return( 0 );
+    return 0;
 }
 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
 
 /*
  * Accept a connection from a remote client
  */
-int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
-                        mbedtls_net_context *client_ctx,
-                        void *client_ip, size_t buf_size, size_t *ip_len )
+int mbedtls_net_accept(mbedtls_net_context *bind_ctx,
+                       mbedtls_net_context *client_ctx,
+                       void *client_ip, size_t buf_size, size_t *ip_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     int type;
@@ -350,132 +342,123 @@
 #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) ||  \
     defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) || \
     defined(socklen_t) || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L)
-    socklen_t n = (socklen_t) sizeof( client_addr );
-    socklen_t type_len = (socklen_t) sizeof( type );
+    socklen_t n = (socklen_t) sizeof(client_addr);
+    socklen_t type_len = (socklen_t) sizeof(type);
 #else
-    int n = (int) sizeof( client_addr );
-    int type_len = (int) sizeof( type );
+    int n = (int) sizeof(client_addr);
+    int type_len = (int) sizeof(type);
 #endif
 
     /* Is this a TCP or UDP socket? */
-    if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE,
-                    (void *) &type, &type_len ) != 0 ||
-        ( type != SOCK_STREAM && type != SOCK_DGRAM ) )
-    {
-        return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
+    if (getsockopt(bind_ctx->fd, SOL_SOCKET, SO_TYPE,
+                   (void *) &type, &type_len) != 0 ||
+        (type != SOCK_STREAM && type != SOCK_DGRAM)) {
+        return MBEDTLS_ERR_NET_ACCEPT_FAILED;
     }
 
-    if( type == SOCK_STREAM )
-    {
+    if (type == SOCK_STREAM) {
         /* TCP: actual accept() */
-        ret = client_ctx->fd = (int) accept( bind_ctx->fd,
-                                             (struct sockaddr *) &client_addr, &n );
-    }
-    else
-    {
+        ret = client_ctx->fd = (int) accept(bind_ctx->fd,
+                                            (struct sockaddr *) &client_addr, &n);
+    } else {
         /* UDP: wait for a message, but keep it in the queue */
         char buf[1] = { 0 };
 
-        ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
-                        (struct sockaddr *) &client_addr, &n );
+        ret = (int) recvfrom(bind_ctx->fd, buf, sizeof(buf), MSG_PEEK,
+                             (struct sockaddr *) &client_addr, &n);
 
 #if defined(_WIN32)
-        if( ret == SOCKET_ERROR &&
-            WSAGetLastError() == WSAEMSGSIZE )
-        {
+        if (ret == SOCKET_ERROR &&
+            WSAGetLastError() == WSAEMSGSIZE) {
             /* We know buf is too small, thanks, just peeking here */
             ret = 0;
         }
 #endif
     }
 
-    if( ret < 0 )
-    {
-        if( net_would_block( bind_ctx ) != 0 )
-            return( MBEDTLS_ERR_SSL_WANT_READ );
+    if (ret < 0) {
+        if (net_would_block(bind_ctx) != 0) {
+            return MBEDTLS_ERR_SSL_WANT_READ;
+        }
 
-        return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
+        return MBEDTLS_ERR_NET_ACCEPT_FAILED;
     }
 
     /* UDP: hijack the listening socket to communicate with the client,
      * then bind a new socket to accept new connections */
-    if( type != SOCK_STREAM )
-    {
+    if (type != SOCK_STREAM) {
         struct sockaddr_storage local_addr;
         int one = 1;
 
-        if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 )
-            return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
+        if (connect(bind_ctx->fd, (struct sockaddr *) &client_addr, n) != 0) {
+            return MBEDTLS_ERR_NET_ACCEPT_FAILED;
+        }
 
         client_ctx->fd = bind_ctx->fd;
         bind_ctx->fd   = -1; /* In case we exit early */
 
-        n = sizeof( struct sockaddr_storage );
-        if( getsockname( client_ctx->fd,
-                         (struct sockaddr *) &local_addr, &n ) != 0 ||
-            ( bind_ctx->fd = (int) socket( local_addr.ss_family,
-                                           SOCK_DGRAM, IPPROTO_UDP ) ) < 0 ||
-            setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,
-                        (const char *) &one, sizeof( one ) ) != 0 )
-        {
-            return( MBEDTLS_ERR_NET_SOCKET_FAILED );
+        n = sizeof(struct sockaddr_storage);
+        if (getsockname(client_ctx->fd,
+                        (struct sockaddr *) &local_addr, &n) != 0 ||
+            (bind_ctx->fd = (int) socket(local_addr.ss_family,
+                                         SOCK_DGRAM, IPPROTO_UDP)) < 0 ||
+            setsockopt(bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,
+                       (const char *) &one, sizeof(one)) != 0) {
+            return MBEDTLS_ERR_NET_SOCKET_FAILED;
         }
 
-        if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 )
-        {
-            return( MBEDTLS_ERR_NET_BIND_FAILED );
+        if (bind(bind_ctx->fd, (struct sockaddr *) &local_addr, n) != 0) {
+            return MBEDTLS_ERR_NET_BIND_FAILED;
         }
     }
 
-    if( client_ip != NULL )
-    {
-        if( client_addr.ss_family == AF_INET )
-        {
+    if (client_ip != NULL) {
+        if (client_addr.ss_family == AF_INET) {
             struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
-            *ip_len = sizeof( addr4->sin_addr.s_addr );
+            *ip_len = sizeof(addr4->sin_addr.s_addr);
 
-            if( buf_size < *ip_len )
-                return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
+            if (buf_size < *ip_len) {
+                return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL;
+            }
 
-            memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len );
-        }
-        else
-        {
+            memcpy(client_ip, &addr4->sin_addr.s_addr, *ip_len);
+        } else {
             struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
-            *ip_len = sizeof( addr6->sin6_addr.s6_addr );
+            *ip_len = sizeof(addr6->sin6_addr.s6_addr);
 
-            if( buf_size < *ip_len )
-                return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
+            if (buf_size < *ip_len) {
+                return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL;
+            }
 
-            memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len);
+            memcpy(client_ip, &addr6->sin6_addr.s6_addr, *ip_len);
         }
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Set the socket blocking or non-blocking
  */
-int mbedtls_net_set_block( mbedtls_net_context *ctx )
+int mbedtls_net_set_block(mbedtls_net_context *ctx)
 {
-#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
     !defined(EFI32)
     u_long n = 0;
-    return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
+    return ioctlsocket(ctx->fd, FIONBIO, &n);
 #else
-    return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) );
+    return fcntl(ctx->fd, F_SETFL, fcntl(ctx->fd, F_GETFL) & ~O_NONBLOCK);
 #endif
 }
 
-int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
+int mbedtls_net_set_nonblock(mbedtls_net_context *ctx)
 {
-#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
     !defined(EFI32)
     u_long n = 1;
-    return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
+    return ioctlsocket(ctx->fd, FIONBIO, &n);
 #else
-    return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) );
+    return fcntl(ctx->fd, F_SETFL, fcntl(ctx->fd, F_GETFL) | O_NONBLOCK);
 #endif
 }
 
@@ -483,7 +466,7 @@
  * Check if data is available on the socket
  */
 
-int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout )
+int mbedtls_net_poll(mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     struct timeval tv;
@@ -493,207 +476,220 @@
 
     int fd = ctx->fd;
 
-    ret = check_fd( fd, 1 );
-    if( ret != 0 )
-        return( ret );
+    ret = check_fd(fd, 1);
+    if (ret != 0) {
+        return ret;
+    }
 
 #if defined(__has_feature)
 #if __has_feature(memory_sanitizer)
     /* Ensure that memory sanitizers consider read_fds and write_fds as
      * initialized even on platforms such as Glibc/x86_64 where FD_ZERO
      * is implemented in assembly. */
-    memset( &read_fds, 0, sizeof( read_fds ) );
-    memset( &write_fds, 0, sizeof( write_fds ) );
+    memset(&read_fds, 0, sizeof(read_fds));
+    memset(&write_fds, 0, sizeof(write_fds));
 #endif
 #endif
 
-    FD_ZERO( &read_fds );
-    if( rw & MBEDTLS_NET_POLL_READ )
-    {
+    FD_ZERO(&read_fds);
+    if (rw & MBEDTLS_NET_POLL_READ) {
         rw &= ~MBEDTLS_NET_POLL_READ;
-        FD_SET( fd, &read_fds );
+        FD_SET(fd, &read_fds);
     }
 
-    FD_ZERO( &write_fds );
-    if( rw & MBEDTLS_NET_POLL_WRITE )
-    {
+    FD_ZERO(&write_fds);
+    if (rw & MBEDTLS_NET_POLL_WRITE) {
         rw &= ~MBEDTLS_NET_POLL_WRITE;
-        FD_SET( fd, &write_fds );
+        FD_SET(fd, &write_fds);
     }
 
-    if( rw != 0 )
-        return( MBEDTLS_ERR_NET_BAD_INPUT_DATA );
+    if (rw != 0) {
+        return MBEDTLS_ERR_NET_BAD_INPUT_DATA;
+    }
 
     tv.tv_sec  = timeout / 1000;
-    tv.tv_usec = ( timeout % 1000 ) * 1000;
+    tv.tv_usec = (timeout % 1000) * 1000;
 
-    do
-    {
-        ret = select( fd + 1, &read_fds, &write_fds, NULL,
-                      timeout == (uint32_t) -1 ? NULL : &tv );
+    do {
+        ret = select(fd + 1, &read_fds, &write_fds, NULL,
+                     timeout == (uint32_t) -1 ? NULL : &tv);
+    } while (IS_EINTR(ret));
+
+    if (ret < 0) {
+        return MBEDTLS_ERR_NET_POLL_FAILED;
     }
-    while( IS_EINTR( ret ) );
-
-    if( ret < 0 )
-        return( MBEDTLS_ERR_NET_POLL_FAILED );
 
     ret = 0;
-    if( FD_ISSET( fd, &read_fds ) )
+    if (FD_ISSET(fd, &read_fds)) {
         ret |= MBEDTLS_NET_POLL_READ;
-    if( FD_ISSET( fd, &write_fds ) )
+    }
+    if (FD_ISSET(fd, &write_fds)) {
         ret |= MBEDTLS_NET_POLL_WRITE;
+    }
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Portable usleep helper
  */
-void mbedtls_net_usleep( unsigned long usec )
+void mbedtls_net_usleep(unsigned long usec)
 {
 #if defined(_WIN32)
-    Sleep( ( usec + 999 ) / 1000 );
+    Sleep((usec + 999) / 1000);
 #else
     struct timeval tv;
     tv.tv_sec  = usec / 1000000;
 #if defined(__unix__) || defined(__unix) || \
-    ( defined(__APPLE__) && defined(__MACH__) )
+    (defined(__APPLE__) && defined(__MACH__))
     tv.tv_usec = (suseconds_t) usec % 1000000;
 #else
     tv.tv_usec = usec % 1000000;
 #endif
-    select( 0, NULL, NULL, NULL, &tv );
+    select(0, NULL, NULL, NULL, &tv);
 #endif
 }
 
 /*
  * Read at most 'len' characters
  */
-int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
+int mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     int fd = ((mbedtls_net_context *) ctx)->fd;
 
-    ret = check_fd( fd, 0 );
-    if( ret != 0 )
-        return( ret );
-
-    ret = (int) read( fd, buf, len );
-
-    if( ret < 0 )
-    {
-        if( net_would_block( ctx ) != 0 )
-            return( MBEDTLS_ERR_SSL_WANT_READ );
-
-#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
-    !defined(EFI32)
-        if( WSAGetLastError() == WSAECONNRESET )
-            return( MBEDTLS_ERR_NET_CONN_RESET );
-#else
-        if( errno == EPIPE || errno == ECONNRESET )
-            return( MBEDTLS_ERR_NET_CONN_RESET );
-
-        if( errno == EINTR )
-            return( MBEDTLS_ERR_SSL_WANT_READ );
-#endif
-
-        return( MBEDTLS_ERR_NET_RECV_FAILED );
+    ret = check_fd(fd, 0);
+    if (ret != 0) {
+        return ret;
     }
 
-    return( ret );
+    ret = (int) read(fd, buf, len);
+
+    if (ret < 0) {
+        if (net_would_block(ctx) != 0) {
+            return MBEDTLS_ERR_SSL_WANT_READ;
+        }
+
+#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
+        !defined(EFI32)
+        if (WSAGetLastError() == WSAECONNRESET) {
+            return MBEDTLS_ERR_NET_CONN_RESET;
+        }
+#else
+        if (errno == EPIPE || errno == ECONNRESET) {
+            return MBEDTLS_ERR_NET_CONN_RESET;
+        }
+
+        if (errno == EINTR) {
+            return MBEDTLS_ERR_SSL_WANT_READ;
+        }
+#endif
+
+        return MBEDTLS_ERR_NET_RECV_FAILED;
+    }
+
+    return ret;
 }
 
 /*
  * Read at most 'len' characters, blocking for at most 'timeout' ms
  */
-int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf,
-                              size_t len, uint32_t timeout )
+int mbedtls_net_recv_timeout(void *ctx, unsigned char *buf,
+                             size_t len, uint32_t timeout)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     struct timeval tv;
     fd_set read_fds;
     int fd = ((mbedtls_net_context *) ctx)->fd;
 
-    ret = check_fd( fd, 1 );
-    if( ret != 0 )
-        return( ret );
+    ret = check_fd(fd, 1);
+    if (ret != 0) {
+        return ret;
+    }
 
-    FD_ZERO( &read_fds );
-    FD_SET( fd, &read_fds );
+    FD_ZERO(&read_fds);
+    FD_SET(fd, &read_fds);
 
     tv.tv_sec  = timeout / 1000;
-    tv.tv_usec = ( timeout % 1000 ) * 1000;
+    tv.tv_usec = (timeout % 1000) * 1000;
 
-    ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv );
+    ret = select(fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv);
 
     /* Zero fds ready means we timed out */
-    if( ret == 0 )
-        return( MBEDTLS_ERR_SSL_TIMEOUT );
+    if (ret == 0) {
+        return MBEDTLS_ERR_SSL_TIMEOUT;
+    }
 
-    if( ret < 0 )
-    {
-#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
-    !defined(EFI32)
-        if( WSAGetLastError() == WSAEINTR )
-            return( MBEDTLS_ERR_SSL_WANT_READ );
+    if (ret < 0) {
+#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
+        !defined(EFI32)
+        if (WSAGetLastError() == WSAEINTR) {
+            return MBEDTLS_ERR_SSL_WANT_READ;
+        }
 #else
-        if( errno == EINTR )
-            return( MBEDTLS_ERR_SSL_WANT_READ );
+        if (errno == EINTR) {
+            return MBEDTLS_ERR_SSL_WANT_READ;
+        }
 #endif
 
-        return( MBEDTLS_ERR_NET_RECV_FAILED );
+        return MBEDTLS_ERR_NET_RECV_FAILED;
     }
 
     /* This call will not block */
-    return( mbedtls_net_recv( ctx, buf, len ) );
+    return mbedtls_net_recv(ctx, buf, len);
 }
 
 /*
  * Write at most 'len' characters
  */
-int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
+int mbedtls_net_send(void *ctx, const unsigned char *buf, size_t len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     int fd = ((mbedtls_net_context *) ctx)->fd;
 
-    ret = check_fd( fd, 0 );
-    if( ret != 0 )
-        return( ret );
-
-    ret = (int) write( fd, buf, len );
-
-    if( ret < 0 )
-    {
-        if( net_would_block( ctx ) != 0 )
-            return( MBEDTLS_ERR_SSL_WANT_WRITE );
-
-#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
-    !defined(EFI32)
-        if( WSAGetLastError() == WSAECONNRESET )
-            return( MBEDTLS_ERR_NET_CONN_RESET );
-#else
-        if( errno == EPIPE || errno == ECONNRESET )
-            return( MBEDTLS_ERR_NET_CONN_RESET );
-
-        if( errno == EINTR )
-            return( MBEDTLS_ERR_SSL_WANT_WRITE );
-#endif
-
-        return( MBEDTLS_ERR_NET_SEND_FAILED );
+    ret = check_fd(fd, 0);
+    if (ret != 0) {
+        return ret;
     }
 
-    return( ret );
+    ret = (int) write(fd, buf, len);
+
+    if (ret < 0) {
+        if (net_would_block(ctx) != 0) {
+            return MBEDTLS_ERR_SSL_WANT_WRITE;
+        }
+
+#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
+        !defined(EFI32)
+        if (WSAGetLastError() == WSAECONNRESET) {
+            return MBEDTLS_ERR_NET_CONN_RESET;
+        }
+#else
+        if (errno == EPIPE || errno == ECONNRESET) {
+            return MBEDTLS_ERR_NET_CONN_RESET;
+        }
+
+        if (errno == EINTR) {
+            return MBEDTLS_ERR_SSL_WANT_WRITE;
+        }
+#endif
+
+        return MBEDTLS_ERR_NET_SEND_FAILED;
+    }
+
+    return ret;
 }
 
 /*
  * Close the connection
  */
-void mbedtls_net_close( mbedtls_net_context *ctx )
+void mbedtls_net_close(mbedtls_net_context *ctx)
 {
-    if( ctx->fd == -1 )
+    if (ctx->fd == -1) {
         return;
+    }
 
-    close( ctx->fd );
+    close(ctx->fd);
 
     ctx->fd = -1;
 }
@@ -701,13 +697,14 @@
 /*
  * Gracefully close the connection
  */
-void mbedtls_net_free( mbedtls_net_context *ctx )
+void mbedtls_net_free(mbedtls_net_context *ctx)
 {
-    if( ctx->fd == -1 )
+    if (ctx->fd == -1) {
         return;
+    }
 
-    shutdown( ctx->fd, 2 );
-    close( ctx->fd );
+    shutdown(ctx->fd, 2);
+    close(ctx->fd);
 
     ctx->fd = -1;
 }
diff --git a/lib/libmbedtls/mbedtls/library/nist_kw.c b/lib/libmbedtls/mbedtls/library/nist_kw.c
index 1aea0b6..5817bf4 100644
--- a/lib/libmbedtls/mbedtls/library/nist_kw.c
+++ b/lib/libmbedtls/mbedtls/library/nist_kw.c
@@ -39,14 +39,7 @@
 #include <stdint.h>
 #include <string.h>
 
-#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
 
 #if !defined(MBEDTLS_NIST_KW_ALT)
 
@@ -54,35 +47,37 @@
 #define MIN_SEMIBLOCKS_COUNT   3
 
 /*! The 64-bit default integrity check value (ICV) for KW mode. */
-static const unsigned char NIST_KW_ICV1[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6};
+static const unsigned char NIST_KW_ICV1[] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 };
 /*! The 32-bit default integrity check value (ICV) for KWP mode. */
-static const  unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6};
+static const  unsigned char NIST_KW_ICV2[] = { 0xA6, 0x59, 0x59, 0xA6 };
 
 /*
  * Initialize context
  */
-void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx )
+void mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx)
 {
-    memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) );
+    memset(ctx, 0, sizeof(mbedtls_nist_kw_context));
 }
 
-int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx,
-                            mbedtls_cipher_id_t cipher,
-                            const unsigned char *key,
-                            unsigned int keybits,
-                            const int is_wrap )
+int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx,
+                           mbedtls_cipher_id_t cipher,
+                           const unsigned char *key,
+                           unsigned int keybits,
+                           const int is_wrap)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const mbedtls_cipher_info_t *cipher_info;
 
-    cipher_info = mbedtls_cipher_info_from_values( cipher,
-                                                   keybits,
-                                                   MBEDTLS_MODE_ECB );
-    if( cipher_info == NULL )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    cipher_info = mbedtls_cipher_info_from_values(cipher,
+                                                  keybits,
+                                                  MBEDTLS_MODE_ECB);
+    if (cipher_info == NULL) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
-    if( cipher_info->block_size != 16 )
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (cipher_info->block_size != 16) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
 
     /*
      * SP 800-38F currently defines AES cipher as the only block cipher allowed:
@@ -93,44 +88,44 @@
      *  Currently we don't support other 128 bit block ciphers for key wrapping,
      *  such as Camellia and Aria.
      */
-    if( cipher != MBEDTLS_CIPHER_ID_AES )
-        return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
-
-    mbedtls_cipher_free( &ctx->cipher_ctx );
-
-    if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
-        return( ret );
-
-    if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
-                                       is_wrap ? MBEDTLS_ENCRYPT :
-                                                 MBEDTLS_DECRYPT )
-                                                                   ) != 0 )
-    {
-        return( ret );
+    if (cipher != MBEDTLS_CIPHER_ID_AES) {
+        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
 
-    return( 0 );
+    mbedtls_cipher_free(&ctx->cipher_ctx);
+
+    if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
+        return ret;
+    }
+
+    if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
+                                     is_wrap ? MBEDTLS_ENCRYPT :
+                                     MBEDTLS_DECRYPT)
+         ) != 0) {
+        return ret;
+    }
+
+    return 0;
 }
 
 /*
  * Free context
  */
-void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx )
+void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx)
 {
-    mbedtls_cipher_free( &ctx->cipher_ctx );
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_nist_kw_context ) );
+    mbedtls_cipher_free(&ctx->cipher_ctx);
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context));
 }
 
 /*
  * Helper function for Xoring the uint64_t "t" with the encrypted A.
  * Defined in NIST SP 800-38F section 6.1
  */
-static void calc_a_xor_t( unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t )
+static void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t)
 {
     size_t i = 0;
-    for( i = 0; i < sizeof( t ); i++ )
-    {
-        A[i] ^= ( t >> ( ( sizeof( t ) - 1 - i ) * 8 ) ) & 0xff;
+    for (i = 0; i < sizeof(t); i++) {
+        A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff;
     }
 }
 
@@ -138,10 +133,10 @@
  * KW-AE as defined in SP 800-38F section 6.2
  * KWP-AE as defined in SP 800-38F section 6.3
  */
-int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx,
-                          mbedtls_nist_kw_mode_t mode,
-                          const unsigned char *input, size_t in_len,
-                          unsigned char *output, size_t *out_len, size_t out_size )
+int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx,
+                         mbedtls_nist_kw_mode_t mode,
+                         const unsigned char *input, size_t in_len,
+                         unsigned char *output, size_t *out_len, size_t out_size)
 {
     int ret = 0;
     size_t semiblocks = 0;
@@ -155,106 +150,96 @@
     /*
      * Generate the String to work on
      */
-    if( mode == MBEDTLS_KW_MODE_KW )
-    {
-        if( out_size < in_len + KW_SEMIBLOCK_LENGTH )
-        {
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (mode == MBEDTLS_KW_MODE_KW) {
+        if (out_size < in_len + KW_SEMIBLOCK_LENGTH) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
         }
 
         /*
          * According to SP 800-38F Table 1, the plaintext length for KW
          * must be between 2 to 2^54-1 semiblocks inclusive.
          */
-        if( in_len < 16 ||
+        if (in_len < 16 ||
 #if SIZE_MAX > 0x1FFFFFFFFFFFFF8
             in_len > 0x1FFFFFFFFFFFFF8 ||
 #endif
-            in_len % KW_SEMIBLOCK_LENGTH != 0 )
-        {
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+            in_len % KW_SEMIBLOCK_LENGTH != 0) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
         }
 
-        memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH );
-        memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len );
-    }
-    else
-    {
-        if( in_len % 8 != 0 )
-        {
-            padlen = ( 8 - ( in_len % 8 ) );
+        memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH);
+        memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len);
+    } else {
+        if (in_len % 8 != 0) {
+            padlen = (8 - (in_len % 8));
         }
 
-        if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen )
-        {
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+        if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
         }
 
         /*
          * According to SP 800-38F Table 1, the plaintext length for KWP
          * must be between 1 and 2^32-1 octets inclusive.
          */
-        if( in_len < 1
+        if (in_len < 1
 #if SIZE_MAX > 0xFFFFFFFF
             || in_len > 0xFFFFFFFF
 #endif
-          )
-        {
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+            ) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
         }
 
-        memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 );
-        MBEDTLS_PUT_UINT32_BE( ( in_len & 0xffffffff ), output,
-                       KW_SEMIBLOCK_LENGTH / 2 );
+        memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2);
+        MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output,
+                              KW_SEMIBLOCK_LENGTH / 2);
 
-        memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len );
-        memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen );
+        memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len);
+        memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen);
     }
-    semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1;
+    semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1;
 
-    s = 6 * ( semiblocks - 1 );
+    s = 6 * (semiblocks - 1);
 
-    if( mode == MBEDTLS_KW_MODE_KWP
-        && in_len <= KW_SEMIBLOCK_LENGTH )
-    {
-        memcpy( inbuff, output, 16 );
-        ret = mbedtls_cipher_update( &ctx->cipher_ctx,
-                                     inbuff, 16, output, &olen );
-        if( ret != 0 )
+    if (mode == MBEDTLS_KW_MODE_KWP
+        && in_len <= KW_SEMIBLOCK_LENGTH) {
+        memcpy(inbuff, output, 16);
+        ret = mbedtls_cipher_update(&ctx->cipher_ctx,
+                                    inbuff, 16, output, &olen);
+        if (ret != 0) {
             goto cleanup;
-    }
-    else
-    {
+        }
+    } else {
         unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
         unsigned char *A = output;
 
         /*
          * Do the wrapping function W, as defined in RFC 3394 section 2.2.1
          */
-        if( semiblocks < MIN_SEMIBLOCKS_COUNT )
-        {
+        if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
             ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
             goto cleanup;
         }
 
         /* Calculate intermediate values */
-        for( t = 1; t <= s; t++ )
-        {
-            memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
-            memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH );
+        for (t = 1; t <= s; t++) {
+            memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
+            memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH);
 
-            ret = mbedtls_cipher_update( &ctx->cipher_ctx,
-                                         inbuff, 16, outbuff, &olen );
-            if( ret != 0 )
+            ret = mbedtls_cipher_update(&ctx->cipher_ctx,
+                                        inbuff, 16, outbuff, &olen);
+            if (ret != 0) {
                 goto cleanup;
+            }
 
-            memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
-            calc_a_xor_t( A, t );
+            memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
+            calc_a_xor_t(A, t);
 
-            memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
+            memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
             R2 += KW_SEMIBLOCK_LENGTH;
-            if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) )
+            if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) {
                 R2 = output + KW_SEMIBLOCK_LENGTH;
+            }
         }
     }
 
@@ -262,14 +247,13 @@
 
 cleanup:
 
-    if( ret != 0)
-    {
-        memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH );
+    if (ret != 0) {
+        memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH);
     }
-    mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 );
-    mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 );
+    mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2);
+    mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2);
 
-    return( ret );
+    return ret;
 }
 
 /*
@@ -280,13 +264,13 @@
  * 3. Minimal number of semiblocks is 3.
  * 4. A is a buffer to hold the first semiblock of the input buffer.
  */
-static int unwrap( mbedtls_nist_kw_context *ctx,
-                   const unsigned char *input, size_t semiblocks,
-                   unsigned char A[KW_SEMIBLOCK_LENGTH],
-                   unsigned char *output, size_t* out_len )
+static int unwrap(mbedtls_nist_kw_context *ctx,
+                  const unsigned char *input, size_t semiblocks,
+                  unsigned char A[KW_SEMIBLOCK_LENGTH],
+                  unsigned char *output, size_t *out_len)
 {
     int ret = 0;
-    const size_t s = 6 * ( semiblocks - 1 );
+    const size_t s = 6 * (semiblocks - 1);
     size_t olen;
     uint64_t t = 0;
     unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
@@ -294,58 +278,59 @@
     unsigned char *R = NULL;
     *out_len = 0;
 
-    if( semiblocks < MIN_SEMIBLOCKS_COUNT )
-    {
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
-    memcpy( A, input, KW_SEMIBLOCK_LENGTH );
-    memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
-    R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
+    memcpy(A, input, KW_SEMIBLOCK_LENGTH);
+    memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
+    R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
 
     /* Calculate intermediate values */
-    for( t = s; t >= 1; t-- )
-    {
-        calc_a_xor_t( A, t );
+    for (t = s; t >= 1; t--) {
+        calc_a_xor_t(A, t);
 
-        memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH );
-        memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH );
+        memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
+        memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH);
 
-        ret = mbedtls_cipher_update( &ctx->cipher_ctx,
-                                     inbuff, 16, outbuff, &olen );
-        if( ret != 0 )
+        ret = mbedtls_cipher_update(&ctx->cipher_ctx,
+                                    inbuff, 16, outbuff, &olen);
+        if (ret != 0) {
             goto cleanup;
+        }
 
-        memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
+        memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
 
         /* Set R as LSB64 of outbuff */
-        memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
+        memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
 
-        if( R == output )
-            R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
-        else
+        if (R == output) {
+            R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
+        } else {
             R -= KW_SEMIBLOCK_LENGTH;
+        }
     }
 
-    *out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH;
+    *out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH;
 
 cleanup:
-    if( ret != 0)
-        memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
-    mbedtls_platform_zeroize( inbuff, sizeof( inbuff )  );
-    mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
+    if (ret != 0) {
+        memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
+    }
+    mbedtls_platform_zeroize(inbuff, sizeof(inbuff));
+    mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
 
-    return( ret );
+    return ret;
 }
 
 /*
  * KW-AD as defined in SP 800-38F section 6.2
  * KWP-AD as defined in SP 800-38F section 6.3
  */
-int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx,
-                            mbedtls_nist_kw_mode_t mode,
-                            const unsigned char *input, size_t in_len,
-                            unsigned char *output, size_t *out_len, size_t out_size )
+int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx,
+                           mbedtls_nist_kw_mode_t mode,
+                           const unsigned char *input, size_t in_len,
+                           unsigned char *output, size_t *out_len, size_t out_size)
 {
     int ret = 0;
     size_t i, olen;
@@ -353,89 +338,81 @@
     unsigned char diff, bad_padding = 0;
 
     *out_len = 0;
-    if( out_size < in_len - KW_SEMIBLOCK_LENGTH )
-    {
-        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    if (out_size < in_len - KW_SEMIBLOCK_LENGTH) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
-    if( mode == MBEDTLS_KW_MODE_KW )
-    {
+    if (mode == MBEDTLS_KW_MODE_KW) {
         /*
          * According to SP 800-38F Table 1, the ciphertext length for KW
          * must be between 3 to 2^54 semiblocks inclusive.
          */
-        if( in_len < 24 ||
+        if (in_len < 24 ||
 #if SIZE_MAX > 0x200000000000000
             in_len > 0x200000000000000 ||
 #endif
-            in_len % KW_SEMIBLOCK_LENGTH != 0 )
-        {
-            return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+            in_len % KW_SEMIBLOCK_LENGTH != 0) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
         }
 
-        ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
-                      A, output, out_len );
-        if( ret != 0 )
+        ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
+                     A, output, out_len);
+        if (ret != 0) {
             goto cleanup;
+        }
 
         /* Check ICV in "constant-time" */
-        diff = mbedtls_ct_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH );
+        diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH);
 
-        if( diff != 0 )
-        {
+        if (diff != 0) {
             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
             goto cleanup;
         }
 
-    }
-    else if( mode == MBEDTLS_KW_MODE_KWP )
-    {
+    } else if (mode == MBEDTLS_KW_MODE_KWP) {
         size_t padlen = 0;
         uint32_t Plen;
         /*
          * According to SP 800-38F Table 1, the ciphertext length for KWP
          * must be between 2 to 2^29 semiblocks inclusive.
          */
-        if( in_len < KW_SEMIBLOCK_LENGTH * 2 ||
+        if (in_len < KW_SEMIBLOCK_LENGTH * 2 ||
 #if SIZE_MAX > 0x100000000
             in_len > 0x100000000 ||
 #endif
-            in_len % KW_SEMIBLOCK_LENGTH != 0 )
-        {
-            return(  MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+            in_len % KW_SEMIBLOCK_LENGTH != 0) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
         }
 
-        if( in_len == KW_SEMIBLOCK_LENGTH * 2 )
-        {
+        if (in_len == KW_SEMIBLOCK_LENGTH * 2) {
             unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
-            ret = mbedtls_cipher_update( &ctx->cipher_ctx,
-                                         input, 16, outbuff, &olen );
-            if( ret != 0 )
+            ret = mbedtls_cipher_update(&ctx->cipher_ctx,
+                                        input, 16, outbuff, &olen);
+            if (ret != 0) {
                 goto cleanup;
+            }
 
-            memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH );
-            memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH );
-            mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) );
+            memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
+            memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
+            mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
             *out_len = KW_SEMIBLOCK_LENGTH;
-        }
-        else
-        {
+        } else {
             /* in_len >=  KW_SEMIBLOCK_LENGTH * 3 */
-            ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
-                          A, output, out_len );
-            if( ret != 0 )
+            ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
+                         A, output, out_len);
+            if (ret != 0) {
                 goto cleanup;
+            }
         }
 
         /* Check ICV in "constant-time" */
-        diff = mbedtls_ct_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 );
+        diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2);
 
-        if( diff != 0 )
-        {
+        if (diff != 0) {
             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
         }
 
-        Plen = MBEDTLS_GET_UINT32_BE( A, KW_SEMIBLOCK_LENGTH / 2 );
+        Plen = MBEDTLS_GET_UINT32_BE(A, KW_SEMIBLOCK_LENGTH / 2);
 
         /*
          * Plen is the length of the plaintext, when the input is valid.
@@ -443,51 +420,45 @@
          * larger than 8, because of the type wrap around.
          */
         padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
-        if ( padlen > 7 )
-        {
+        if (padlen > 7) {
             padlen &= 7;
             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
         }
 
         /* Check padding in "constant-time" */
-        for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ )
-        {
-             if( i >= KW_SEMIBLOCK_LENGTH - padlen )
-                 diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
-             else
-                 bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
+        for (diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++) {
+            if (i >= KW_SEMIBLOCK_LENGTH - padlen) {
+                diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
+            } else {
+                bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
+            }
         }
 
-        if( diff != 0 )
-        {
+        if (diff != 0) {
             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
         }
 
-        if( ret != 0 )
-        {
+        if (ret != 0) {
             goto cleanup;
         }
-        memset( output + Plen, 0, padlen );
+        memset(output + Plen, 0, padlen);
         *out_len = Plen;
-    }
-    else
-    {
+    } else {
         ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
         goto cleanup;
     }
 
 cleanup:
-    if( ret != 0 )
-    {
-        memset( output, 0, *out_len );
+    if (ret != 0) {
+        memset(output, 0, *out_len);
         *out_len = 0;
     }
 
-    mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) );
-    mbedtls_platform_zeroize( &diff, sizeof( diff ) );
-    mbedtls_platform_zeroize( A, sizeof( A ) );
+    mbedtls_platform_zeroize(&bad_padding, sizeof(bad_padding));
+    mbedtls_platform_zeroize(&diff, sizeof(diff));
+    mbedtls_platform_zeroize(A, sizeof(A));
 
-    return( ret );
+    return ret;
 }
 
 #endif /* !MBEDTLS_NIST_KW_ALT */
@@ -582,130 +553,133 @@
 };
 static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 };
 
-int mbedtls_nist_kw_self_test( int verbose )
+int mbedtls_nist_kw_self_test(int verbose)
 {
     mbedtls_nist_kw_context ctx;
     unsigned char out[48];
     size_t olen;
     int i;
     int ret = 0;
-    mbedtls_nist_kw_init( &ctx );
+    mbedtls_nist_kw_init(&ctx);
 
-    for( i = 0; i < KW_TESTS; i++ )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "  KW-AES-%u ", (unsigned int) key_len[i] * 8 );
+    for (i = 0; i < KW_TESTS; i++) {
+        if (verbose != 0) {
+            mbedtls_printf("  KW-AES-%u ", (unsigned int) key_len[i] * 8);
+        }
 
-        ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
-                                      kw_key[i], key_len[i] * 8, 1 );
-        if( ret != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "  KW: setup failed " );
+        ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
+                                     kw_key[i], key_len[i] * 8, 1);
+        if (ret != 0) {
+            if (verbose != 0) {
+                mbedtls_printf("  KW: setup failed ");
+            }
 
             goto end;
         }
 
-        ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
-                                    kw_msg_len[i], out, &olen, sizeof( out ) );
-        if( ret != 0 || kw_out_len[i] != olen ||
-            memcmp( out, kw_res[i], kw_out_len[i] ) != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "failed. ");
+        ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
+                                   kw_msg_len[i], out, &olen, sizeof(out));
+        if (ret != 0 || kw_out_len[i] != olen ||
+            memcmp(out, kw_res[i], kw_out_len[i]) != 0) {
+            if (verbose != 0) {
+                mbedtls_printf("failed. ");
+            }
 
             ret = 1;
             goto end;
         }
 
-        if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
-                                            kw_key[i], key_len[i] * 8, 0 ) )
-              != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "  KW: setup failed ");
+        if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
+                                          kw_key[i], key_len[i] * 8, 0))
+            != 0) {
+            if (verbose != 0) {
+                mbedtls_printf("  KW: setup failed ");
+            }
 
             goto end;
         }
 
-        ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW,
-                                      out, olen, out, &olen, sizeof( out ) );
+        ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW,
+                                     out, olen, out, &olen, sizeof(out));
 
-        if( ret != 0 || olen != kw_msg_len[i] ||
-            memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "failed\n" );
+        if (ret != 0 || olen != kw_msg_len[i] ||
+            memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) {
+            if (verbose != 0) {
+                mbedtls_printf("failed\n");
+            }
 
             ret = 1;
             goto end;
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( " passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf(" passed\n");
+        }
     }
 
-    for( i = 0; i < KW_TESTS; i++ )
-    {
-        olen = sizeof( out );
-        if( verbose != 0 )
-            mbedtls_printf( "  KWP-AES-%u ", (unsigned int) key_len[i] * 8 );
+    for (i = 0; i < KW_TESTS; i++) {
+        olen = sizeof(out);
+        if (verbose != 0) {
+            mbedtls_printf("  KWP-AES-%u ", (unsigned int) key_len[i] * 8);
+        }
 
-        ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
-                                      key_len[i] * 8, 1 );
-        if( ret  != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "  KWP: setup failed " );
+        ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
+                                     key_len[i] * 8, 1);
+        if (ret  != 0) {
+            if (verbose != 0) {
+                mbedtls_printf("  KWP: setup failed ");
+            }
 
             goto end;
         }
-        ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
-                                    kwp_msg_len[i], out, &olen, sizeof( out ) );
+        ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
+                                   kwp_msg_len[i], out, &olen, sizeof(out));
 
-        if( ret != 0 || kwp_out_len[i] != olen ||
-            memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "failed. ");
+        if (ret != 0 || kwp_out_len[i] != olen ||
+            memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) {
+            if (verbose != 0) {
+                mbedtls_printf("failed. ");
+            }
 
             ret = 1;
             goto end;
         }
 
-        if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
-                                            kwp_key[i], key_len[i] * 8, 0 ) )
-              != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "  KWP: setup failed ");
+        if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
+                                          kwp_key[i], key_len[i] * 8, 0))
+            != 0) {
+            if (verbose != 0) {
+                mbedtls_printf("  KWP: setup failed ");
+            }
 
             goto end;
         }
 
-        ret = mbedtls_nist_kw_unwrap(  &ctx, MBEDTLS_KW_MODE_KWP, out,
-                                       olen, out, &olen, sizeof( out ) );
+        ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out,
+                                     olen, out, &olen, sizeof(out));
 
-        if( ret != 0 || olen != kwp_msg_len[i] ||
-            memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "failed. ");
+        if (ret != 0 || olen != kwp_msg_len[i] ||
+            memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) {
+            if (verbose != 0) {
+                mbedtls_printf("failed. ");
+            }
 
             ret = 1;
             goto end;
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( " passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf(" passed\n");
+        }
     }
 end:
-    mbedtls_nist_kw_free( &ctx );
+    mbedtls_nist_kw_free(&ctx);
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
-    return( ret );
+    return ret;
 }
 
 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
diff --git a/lib/libmbedtls/mbedtls/library/oid.c b/lib/libmbedtls/mbedtls/library/oid.c
index 19c8ac2..63b3df3 100644
--- a/lib/libmbedtls/mbedtls/library/oid.c
+++ b/lib/libmbedtls/mbedtls/library/oid.c
@@ -26,15 +26,14 @@
 #include "mbedtls/oid.h"
 #include "mbedtls/rsa.h"
 #include "mbedtls/error.h"
+#include "mbedtls/pk.h"
+
+#include "mbedtls/legacy_or_psa.h"
 
 #include <stdio.h>
 #include <string.h>
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#define mbedtls_snprintf snprintf
-#endif
 
 /*
  * Macro to automatically add the size of #define'd OIDs
@@ -42,53 +41,66 @@
 #define ADD_LEN(s)      s, MBEDTLS_OID_SIZE(s)
 
 /*
+ * Macro to generate mbedtls_oid_descriptor_t
+ */
+#if !defined(MBEDTLS_X509_REMOVE_INFO)
+#define OID_DESCRIPTOR(s, name, description)  { ADD_LEN(s), name, description }
+#define NULL_OID_DESCRIPTOR                   { NULL, 0, NULL, NULL }
+#else
+#define OID_DESCRIPTOR(s, name, description)  { ADD_LEN(s) }
+#define NULL_OID_DESCRIPTOR                   { NULL, 0 }
+#endif
+
+/*
  * Macro to generate an internal function for oid_XXX_from_asn1() (used by
  * the other functions)
  */
-#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST )                    \
-    static const TYPE_T * oid_ ## NAME ## _from_asn1(                   \
-                                      const mbedtls_asn1_buf *oid )     \
+#define FN_OID_TYPED_FROM_ASN1(TYPE_T, NAME, LIST)                    \
+    static const TYPE_T *oid_ ## NAME ## _from_asn1(                   \
+        const mbedtls_asn1_buf *oid)     \
     {                                                                   \
         const TYPE_T *p = (LIST);                                       \
         const mbedtls_oid_descriptor_t *cur =                           \
             (const mbedtls_oid_descriptor_t *) p;                       \
-        if( p == NULL || oid == NULL ) return( NULL );                  \
-        while( cur->asn1 != NULL ) {                                    \
-            if( cur->asn1_len == oid->len &&                            \
-                memcmp( cur->asn1, oid->p, oid->len ) == 0 ) {          \
-                return( p );                                            \
+        if (p == NULL || oid == NULL) return NULL;                  \
+        while (cur->asn1 != NULL) {                                    \
+            if (cur->asn1_len == oid->len &&                            \
+                memcmp(cur->asn1, oid->p, oid->len) == 0) {          \
+                return p;                                            \
             }                                                           \
             p++;                                                        \
             cur = (const mbedtls_oid_descriptor_t *) p;                 \
         }                                                               \
-        return( NULL );                                                 \
+        return NULL;                                                 \
     }
 
+#if !defined(MBEDTLS_X509_REMOVE_INFO)
 /*
  * Macro to generate a function for retrieving a single attribute from the
  * descriptor of an mbedtls_oid_descriptor_t wrapper.
  */
 #define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \
-int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 )                  \
-{                                                                       \
-    const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid );        \
-    if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND );            \
-    *ATTR1 = data->descriptor.ATTR1;                                    \
-    return( 0 );                                                        \
-}
+    int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1)                  \
+    {                                                                       \
+        const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid);        \
+        if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND;            \
+        *ATTR1 = data->descriptor.ATTR1;                                    \
+        return 0;                                                        \
+    }
+#endif /* MBEDTLS_X509_REMOVE_INFO */
 
 /*
  * Macro to generate a function for retrieving a single attribute from an
  * mbedtls_oid_descriptor_t wrapper.
  */
 #define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \
-int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 )                  \
-{                                                                       \
-    const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid );        \
-    if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND );            \
-    *ATTR1 = data->ATTR1;                                               \
-    return( 0 );                                                        \
-}
+    int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1)                  \
+    {                                                                       \
+        const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid);        \
+        if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND;            \
+        *ATTR1 = data->ATTR1;                                               \
+        return 0;                                                        \
+    }
 
 /*
  * Macro to generate a function for retrieving two attributes from an
@@ -96,34 +108,34 @@
  */
 #define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1,     \
                          ATTR2_TYPE, ATTR2)                                 \
-int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1,               \
-                                          ATTR2_TYPE * ATTR2 )              \
-{                                                                           \
-    const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid );            \
-    if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND );                 \
-    *(ATTR1) = data->ATTR1;                                                 \
-    *(ATTR2) = data->ATTR2;                                                 \
-    return( 0 );                                                            \
-}
+    int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1,               \
+                ATTR2_TYPE * ATTR2)              \
+    {                                                                           \
+        const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid);            \
+        if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND;                 \
+        *(ATTR1) = data->ATTR1;                                                 \
+        *(ATTR2) = data->ATTR2;                                                 \
+        return 0;                                                            \
+    }
 
 /*
  * Macro to generate a function for retrieving the OID based on a single
  * attribute from a mbedtls_oid_descriptor_t wrapper.
  */
 #define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1)   \
-int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen )             \
-{                                                                           \
-    const TYPE_T *cur = (LIST);                                             \
-    while( cur->descriptor.asn1 != NULL ) {                                 \
-        if( cur->ATTR1 == (ATTR1) ) {                                       \
-            *oid = cur->descriptor.asn1;                                    \
-            *olen = cur->descriptor.asn1_len;                               \
-            return( 0 );                                                    \
-        }                                                                   \
-        cur++;                                                              \
-    }                                                                       \
-    return( MBEDTLS_ERR_OID_NOT_FOUND );                                    \
-}
+    int FN_NAME(ATTR1_TYPE ATTR1, const char **oid, size_t *olen)             \
+    {                                                                           \
+        const TYPE_T *cur = (LIST);                                             \
+        while (cur->descriptor.asn1 != NULL) {                                 \
+            if (cur->ATTR1 == (ATTR1)) {                                       \
+                *oid = cur->descriptor.asn1;                                    \
+                *olen = cur->descriptor.asn1_len;                               \
+                return 0;                                                    \
+            }                                                                   \
+            cur++;                                                              \
+        }                                                                       \
+        return MBEDTLS_ERR_OID_NOT_FOUND;                                    \
+    }
 
 /*
  * Macro to generate a function for retrieving the OID based on two
@@ -131,20 +143,20 @@
  */
 #define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1,   \
                                 ATTR2_TYPE, ATTR2)                          \
-int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid ,         \
-             size_t *olen )                                                 \
-{                                                                           \
-    const TYPE_T *cur = (LIST);                                             \
-    while( cur->descriptor.asn1 != NULL ) {                                 \
-        if( cur->ATTR1 == (ATTR1) && cur->ATTR2 == (ATTR2) ) {              \
-            *oid = cur->descriptor.asn1;                                    \
-            *olen = cur->descriptor.asn1_len;                               \
-            return( 0 );                                                    \
-        }                                                                   \
-        cur++;                                                              \
-    }                                                                       \
-    return( MBEDTLS_ERR_OID_NOT_FOUND );                                   \
-}
+    int FN_NAME(ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid,         \
+                size_t *olen)                                                 \
+    {                                                                           \
+        const TYPE_T *cur = (LIST);                                             \
+        while (cur->descriptor.asn1 != NULL) {                                 \
+            if (cur->ATTR1 == (ATTR1) && cur->ATTR2 == (ATTR2)) {              \
+                *oid = cur->descriptor.asn1;                                    \
+                *olen = cur->descriptor.asn1_len;                               \
+                return 0;                                                    \
+            }                                                                   \
+            cur++;                                                              \
+        }                                                                       \
+        return MBEDTLS_ERR_OID_NOT_FOUND;                                   \
+    }
 
 /*
  * For X520 attribute types
@@ -157,89 +169,112 @@
 static const oid_x520_attr_t oid_x520_attr_type[] =
 {
     {
-        { ADD_LEN( MBEDTLS_OID_AT_CN ),          "id-at-commonName",               "Common Name" },
+        OID_DESCRIPTOR(MBEDTLS_OID_AT_CN,          "id-at-commonName",               "Common Name"),
         "CN",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_AT_COUNTRY ),     "id-at-countryName",              "Country" },
+        OID_DESCRIPTOR(MBEDTLS_OID_AT_COUNTRY,     "id-at-countryName",              "Country"),
         "C",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_AT_LOCALITY ),    "id-at-locality",                 "Locality" },
+        OID_DESCRIPTOR(MBEDTLS_OID_AT_LOCALITY,    "id-at-locality",                 "Locality"),
         "L",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_AT_STATE ),       "id-at-state",                    "State" },
+        OID_DESCRIPTOR(MBEDTLS_OID_AT_STATE,       "id-at-state",                    "State"),
         "ST",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_AT_ORGANIZATION ),"id-at-organizationName",         "Organization" },
+        OID_DESCRIPTOR(MBEDTLS_OID_AT_ORGANIZATION, "id-at-organizationName",
+                       "Organization"),
         "O",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_AT_ORG_UNIT ),    "id-at-organizationalUnitName",   "Org Unit" },
+        OID_DESCRIPTOR(MBEDTLS_OID_AT_ORG_UNIT,    "id-at-organizationalUnitName",   "Org Unit"),
         "OU",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_PKCS9_EMAIL ),    "emailAddress",                   "E-mail address" },
+        OID_DESCRIPTOR(MBEDTLS_OID_PKCS9_EMAIL,
+                       "emailAddress",
+                       "E-mail address"),
         "emailAddress",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_AT_SERIAL_NUMBER ),"id-at-serialNumber",            "Serial number" },
+        OID_DESCRIPTOR(MBEDTLS_OID_AT_SERIAL_NUMBER,
+                       "id-at-serialNumber",
+                       "Serial number"),
         "serialNumber",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress",          "Postal address" },
+        OID_DESCRIPTOR(MBEDTLS_OID_AT_POSTAL_ADDRESS,
+                       "id-at-postalAddress",
+                       "Postal address"),
         "postalAddress",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_AT_POSTAL_CODE ), "id-at-postalCode",               "Postal code" },
+        OID_DESCRIPTOR(MBEDTLS_OID_AT_POSTAL_CODE, "id-at-postalCode",               "Postal code"),
         "postalCode",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_AT_SUR_NAME ),    "id-at-surName",                  "Surname" },
+        OID_DESCRIPTOR(MBEDTLS_OID_AT_SUR_NAME,    "id-at-surName",                  "Surname"),
         "SN",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_AT_GIVEN_NAME ),  "id-at-givenName",                "Given name" },
+        OID_DESCRIPTOR(MBEDTLS_OID_AT_GIVEN_NAME,  "id-at-givenName",                "Given name"),
         "GN",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_AT_INITIALS ),    "id-at-initials",                 "Initials" },
+        OID_DESCRIPTOR(MBEDTLS_OID_AT_INITIALS,    "id-at-initials",                 "Initials"),
         "initials",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" },
+        OID_DESCRIPTOR(MBEDTLS_OID_AT_GENERATION_QUALIFIER,
+                       "id-at-generationQualifier",
+                       "Generation qualifier"),
         "generationQualifier",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_AT_TITLE ),       "id-at-title",                    "Title" },
+        OID_DESCRIPTOR(MBEDTLS_OID_AT_TITLE,       "id-at-title",                    "Title"),
         "title",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_AT_DN_QUALIFIER ),"id-at-dnQualifier",              "Distinguished Name qualifier" },
+        OID_DESCRIPTOR(MBEDTLS_OID_AT_DN_QUALIFIER,
+                       "id-at-dnQualifier",
+                       "Distinguished Name qualifier"),
         "dnQualifier",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_AT_PSEUDONYM ),   "id-at-pseudonym",                "Pseudonym" },
+        OID_DESCRIPTOR(MBEDTLS_OID_AT_PSEUDONYM,   "id-at-pseudonym",                "Pseudonym"),
         "pseudonym",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_DOMAIN_COMPONENT ), "id-domainComponent",           "Domain component" },
+        OID_DESCRIPTOR(MBEDTLS_OID_UID,            "id-uid",                         "User Id"),
+        "uid",
+    },
+    {
+        OID_DESCRIPTOR(MBEDTLS_OID_DOMAIN_COMPONENT,
+                       "id-domainComponent",
+                       "Domain component"),
         "DC",
     },
     {
-        { ADD_LEN( MBEDTLS_OID_AT_UNIQUE_IDENTIFIER ), "id-at-uniqueIdentifier",    "Unique Identifier" },
+        OID_DESCRIPTOR(MBEDTLS_OID_AT_UNIQUE_IDENTIFIER,
+                       "id-at-uniqueIdentifier",
+                       "Unique Identifier"),
         "uniqueIdentifier",
     },
     {
-        { NULL, 0, NULL, NULL },
+        NULL_OID_DESCRIPTOR,
         NULL,
     }
 };
 
 FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type)
-FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name)
+FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name,
+                 oid_x520_attr_t,
+                 x520_attr,
+                 const char *,
+                 short_name)
 
 /*
  * For X509 extensions
@@ -252,31 +287,41 @@
 static const oid_x509_ext_t oid_x509_ext[] =
 {
     {
-        { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ),    "id-ce-basicConstraints",    "Basic Constraints" },
+        OID_DESCRIPTOR(MBEDTLS_OID_BASIC_CONSTRAINTS,
+                       "id-ce-basicConstraints",
+                       "Basic Constraints"),
         MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS,
     },
     {
-        { ADD_LEN( MBEDTLS_OID_KEY_USAGE ),            "id-ce-keyUsage",            "Key Usage" },
+        OID_DESCRIPTOR(MBEDTLS_OID_KEY_USAGE,            "id-ce-keyUsage",            "Key Usage"),
         MBEDTLS_OID_X509_EXT_KEY_USAGE,
     },
     {
-        { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ),   "id-ce-extKeyUsage",         "Extended Key Usage" },
+        OID_DESCRIPTOR(MBEDTLS_OID_EXTENDED_KEY_USAGE,
+                       "id-ce-extKeyUsage",
+                       "Extended Key Usage"),
         MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE,
     },
     {
-        { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ),     "id-ce-subjectAltName",      "Subject Alt Name" },
+        OID_DESCRIPTOR(MBEDTLS_OID_SUBJECT_ALT_NAME,
+                       "id-ce-subjectAltName",
+                       "Subject Alt Name"),
         MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME,
     },
     {
-        { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ),         "id-netscape-certtype",      "Netscape Certificate Type" },
+        OID_DESCRIPTOR(MBEDTLS_OID_NS_CERT_TYPE,
+                       "id-netscape-certtype",
+                       "Netscape Certificate Type"),
         MBEDTLS_OID_X509_EXT_NS_CERT_TYPE,
     },
     {
-        { ADD_LEN( MBEDTLS_OID_CERTIFICATE_POLICIES ), "id-ce-certificatePolicies", "Certificate Policies" },
+        OID_DESCRIPTOR(MBEDTLS_OID_CERTIFICATE_POLICIES,
+                       "id-ce-certificatePolicies",
+                       "Certificate Policies"),
         MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES,
     },
     {
-        { NULL, 0, NULL, NULL },
+        NULL_OID_DESCRIPTOR,
         0,
     },
 };
@@ -284,31 +329,46 @@
 FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext)
 FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type)
 
+#if !defined(MBEDTLS_X509_REMOVE_INFO)
 static const mbedtls_oid_descriptor_t oid_ext_key_usage[] =
 {
-    { ADD_LEN( MBEDTLS_OID_SERVER_AUTH ),      "id-kp-serverAuth",       "TLS Web Server Authentication" },
-    { ADD_LEN( MBEDTLS_OID_CLIENT_AUTH ),      "id-kp-clientAuth",       "TLS Web Client Authentication" },
-    { ADD_LEN( MBEDTLS_OID_CODE_SIGNING ),     "id-kp-codeSigning",      "Code Signing" },
-    { ADD_LEN( MBEDTLS_OID_EMAIL_PROTECTION ), "id-kp-emailProtection",  "E-mail Protection" },
-    { ADD_LEN( MBEDTLS_OID_TIME_STAMPING ),    "id-kp-timeStamping",     "Time Stamping" },
-    { ADD_LEN( MBEDTLS_OID_OCSP_SIGNING ),     "id-kp-OCSPSigning",      "OCSP Signing" },
-    { ADD_LEN( MBEDTLS_OID_WISUN_FAN ),        "id-kp-wisun-fan-device", "Wi-SUN Alliance Field Area Network (FAN)" },
-    { NULL, 0, NULL, NULL },
+    OID_DESCRIPTOR(MBEDTLS_OID_SERVER_AUTH,
+                   "id-kp-serverAuth",
+                   "TLS Web Server Authentication"),
+    OID_DESCRIPTOR(MBEDTLS_OID_CLIENT_AUTH,
+                   "id-kp-clientAuth",
+                   "TLS Web Client Authentication"),
+    OID_DESCRIPTOR(MBEDTLS_OID_CODE_SIGNING,     "id-kp-codeSigning",     "Code Signing"),
+    OID_DESCRIPTOR(MBEDTLS_OID_EMAIL_PROTECTION, "id-kp-emailProtection", "E-mail Protection"),
+    OID_DESCRIPTOR(MBEDTLS_OID_TIME_STAMPING,    "id-kp-timeStamping",    "Time Stamping"),
+    OID_DESCRIPTOR(MBEDTLS_OID_OCSP_SIGNING,     "id-kp-OCSPSigning",     "OCSP Signing"),
+    OID_DESCRIPTOR(MBEDTLS_OID_WISUN_FAN,
+                   "id-kp-wisun-fan-device",
+                   "Wi-SUN Alliance Field Area Network (FAN)"),
+    NULL_OID_DESCRIPTOR,
 };
 
 FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage)
-FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description)
+FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage,
+                 mbedtls_oid_descriptor_t,
+                 ext_key_usage,
+                 const char *,
+                 description)
 
 static const mbedtls_oid_descriptor_t oid_certificate_policies[] =
 {
-    { ADD_LEN( MBEDTLS_OID_ANY_POLICY ),      "anyPolicy",       "Any Policy" },
-    { NULL, 0, NULL, NULL },
+    OID_DESCRIPTOR(MBEDTLS_OID_ANY_POLICY,      "anyPolicy",       "Any Policy"),
+    NULL_OID_DESCRIPTOR,
 };
 
 FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, certificate_policies, oid_certificate_policies)
-FN_OID_GET_ATTR1(mbedtls_oid_get_certificate_policies, mbedtls_oid_descriptor_t, certificate_policies, const char *, description)
+FN_OID_GET_ATTR1(mbedtls_oid_get_certificate_policies,
+                 mbedtls_oid_descriptor_t,
+                 certificate_policies,
+                 const char *,
+                 description)
+#endif /* MBEDTLS_X509_REMOVE_INFO */
 
-#if defined(MBEDTLS_MD_C)
 /*
  * For SignatureAlgorithmIdentifier
  */
@@ -321,102 +381,121 @@
 static const oid_sig_alg_t oid_sig_alg[] =
 {
 #if defined(MBEDTLS_RSA_C)
-#if defined(MBEDTLS_MD2_C)
+#if defined(MBEDTLS_HAS_ALG_MD5_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_PKCS1_MD2 ),        "md2WithRSAEncryption",     "RSA with MD2" },
-        MBEDTLS_MD_MD2,      MBEDTLS_PK_RSA,
-    },
-#endif /* MBEDTLS_MD2_C */
-#if defined(MBEDTLS_MD4_C)
-    {
-        { ADD_LEN( MBEDTLS_OID_PKCS1_MD4 ),        "md4WithRSAEncryption",     "RSA with MD4" },
-        MBEDTLS_MD_MD4,      MBEDTLS_PK_RSA,
-    },
-#endif /* MBEDTLS_MD4_C */
-#if defined(MBEDTLS_MD5_C)
-    {
-        { ADD_LEN( MBEDTLS_OID_PKCS1_MD5 ),        "md5WithRSAEncryption",     "RSA with MD5" },
+        OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_MD5,        "md5WithRSAEncryption",     "RSA with MD5"),
         MBEDTLS_MD_MD5,      MBEDTLS_PK_RSA,
     },
-#endif /* MBEDTLS_MD5_C */
-#if defined(MBEDTLS_SHA1_C)
+#endif /* MBEDTLS_HAS_ALG_MD5_VIA_LOWLEVEL_OR_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_PKCS1_SHA1 ),       "sha-1WithRSAEncryption",   "RSA with SHA1" },
+        OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA1,       "sha-1WithRSAEncryption",   "RSA with SHA1"),
         MBEDTLS_MD_SHA1,     MBEDTLS_PK_RSA,
     },
-#endif /* MBEDTLS_SHA1_C */
-#if defined(MBEDTLS_SHA256_C)
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_PKCS1_SHA224 ),     "sha224WithRSAEncryption",  "RSA with SHA-224" },
+        OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA224,     "sha224WithRSAEncryption",
+                       "RSA with SHA-224"),
         MBEDTLS_MD_SHA224,   MBEDTLS_PK_RSA,
     },
+#endif /* MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_PKCS1_SHA256 ),     "sha256WithRSAEncryption",  "RSA with SHA-256" },
+        OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA256,     "sha256WithRSAEncryption",
+                       "RSA with SHA-256"),
         MBEDTLS_MD_SHA256,   MBEDTLS_PK_RSA,
     },
-#endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA512_C)
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_PKCS1_SHA384 ),     "sha384WithRSAEncryption",  "RSA with SHA-384" },
+        OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA384,     "sha384WithRSAEncryption",
+                       "RSA with SHA-384"),
         MBEDTLS_MD_SHA384,   MBEDTLS_PK_RSA,
     },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_PKCS1_SHA512 ),     "sha512WithRSAEncryption",  "RSA with SHA-512" },
+        OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA512,     "sha512WithRSAEncryption",
+                       "RSA with SHA-512"),
         MBEDTLS_MD_SHA512,   MBEDTLS_PK_RSA,
     },
-#endif /* MBEDTLS_SHA512_C */
-#if defined(MBEDTLS_SHA1_C)
+#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_RSA_SHA_OBS ),      "sha-1WithRSAEncryption",   "RSA with SHA1" },
+        OID_DESCRIPTOR(MBEDTLS_OID_RSA_SHA_OBS,      "sha-1WithRSAEncryption",   "RSA with SHA1"),
         MBEDTLS_MD_SHA1,     MBEDTLS_PK_RSA,
     },
-#endif /* MBEDTLS_SHA1_C */
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA */
 #endif /* MBEDTLS_RSA_C */
-#if defined(MBEDTLS_ECDSA_C)
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_ECDSA_SHA1 ),       "ecdsa-with-SHA1",      "ECDSA with SHA1" },
+        OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA1,       "ecdsa-with-SHA1",      "ECDSA with SHA1"),
         MBEDTLS_MD_SHA1,     MBEDTLS_PK_ECDSA,
     },
-#endif /* MBEDTLS_SHA1_C */
-#if defined(MBEDTLS_SHA256_C)
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_ECDSA_SHA224 ),     "ecdsa-with-SHA224",    "ECDSA with SHA224" },
+        OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA224,     "ecdsa-with-SHA224",    "ECDSA with SHA224"),
         MBEDTLS_MD_SHA224,   MBEDTLS_PK_ECDSA,
     },
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_ECDSA_SHA256 ),     "ecdsa-with-SHA256",    "ECDSA with SHA256" },
+        OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA256,     "ecdsa-with-SHA256",    "ECDSA with SHA256"),
         MBEDTLS_MD_SHA256,   MBEDTLS_PK_ECDSA,
     },
-#endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA512_C)
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_ECDSA_SHA384 ),     "ecdsa-with-SHA384",    "ECDSA with SHA384" },
+        OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA384,     "ecdsa-with-SHA384",    "ECDSA with SHA384"),
         MBEDTLS_MD_SHA384,   MBEDTLS_PK_ECDSA,
     },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_ECDSA_SHA512 ),     "ecdsa-with-SHA512",    "ECDSA with SHA512" },
+        OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA512,     "ecdsa-with-SHA512",    "ECDSA with SHA512"),
         MBEDTLS_MD_SHA512,   MBEDTLS_PK_ECDSA,
     },
-#endif /* MBEDTLS_SHA512_C */
-#endif /* MBEDTLS_ECDSA_C */
+#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA */
+#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */
 #if defined(MBEDTLS_RSA_C)
     {
-        { ADD_LEN( MBEDTLS_OID_RSASSA_PSS ),        "RSASSA-PSS",           "RSASSA-PSS" },
+        OID_DESCRIPTOR(MBEDTLS_OID_RSASSA_PSS,        "RSASSA-PSS",           "RSASSA-PSS"),
         MBEDTLS_MD_NONE,     MBEDTLS_PK_RSASSA_PSS,
     },
 #endif /* MBEDTLS_RSA_C */
     {
-        { NULL, 0, NULL, NULL },
+        NULL_OID_DESCRIPTOR,
         MBEDTLS_MD_NONE, MBEDTLS_PK_NONE,
     },
 };
 
 FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg)
-FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description)
-FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg)
-FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedtls_pk_type_t, pk_alg, mbedtls_md_type_t, md_alg)
-#endif /* MBEDTLS_MD_C */
+
+#if !defined(MBEDTLS_X509_REMOVE_INFO)
+FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc,
+                            oid_sig_alg_t,
+                            sig_alg,
+                            const char *,
+                            description)
+#endif
+
+FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg,
+                 oid_sig_alg_t,
+                 sig_alg,
+                 mbedtls_md_type_t,
+                 md_alg,
+                 mbedtls_pk_type_t,
+                 pk_alg)
+FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg,
+                        oid_sig_alg_t,
+                        oid_sig_alg,
+                        mbedtls_pk_type_t,
+                        pk_alg,
+                        mbedtls_md_type_t,
+                        md_alg)
 
 /*
  * For PublicKeyInfo (PKCS1, RFC 5480)
@@ -429,26 +508,30 @@
 static const oid_pk_alg_t oid_pk_alg[] =
 {
     {
-        { ADD_LEN( MBEDTLS_OID_PKCS1_RSA ),      "rsaEncryption",   "RSA" },
+        OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_RSA,           "rsaEncryption",    "RSA"),
         MBEDTLS_PK_RSA,
     },
     {
-        { ADD_LEN( MBEDTLS_OID_EC_ALG_UNRESTRICTED ),  "id-ecPublicKey",   "Generic EC key" },
+        OID_DESCRIPTOR(MBEDTLS_OID_EC_ALG_UNRESTRICTED, "id-ecPublicKey",   "Generic EC key"),
         MBEDTLS_PK_ECKEY,
     },
     {
-        { ADD_LEN( MBEDTLS_OID_EC_ALG_ECDH ),          "id-ecDH",          "EC key for ECDH" },
+        OID_DESCRIPTOR(MBEDTLS_OID_EC_ALG_ECDH,         "id-ecDH",          "EC key for ECDH"),
         MBEDTLS_PK_ECKEY_DH,
     },
     {
-        { NULL, 0, NULL, NULL },
+        NULL_OID_DESCRIPTOR,
         MBEDTLS_PK_NONE,
     },
 };
 
 FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg)
 FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg)
-FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg)
+FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg,
+                        oid_pk_alg_t,
+                        oid_pk_alg,
+                        mbedtls_pk_type_t,
+                        pk_alg)
 
 #if defined(MBEDTLS_ECP_C)
 /*
@@ -463,79 +546,83 @@
 {
 #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
     {
-        { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192R1 ), "secp192r1",    "secp192r1" },
+        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192R1, "secp192r1",    "secp192r1"),
         MBEDTLS_ECP_DP_SECP192R1,
     },
 #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
     {
-        { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224R1 ), "secp224r1",    "secp224r1" },
+        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224R1, "secp224r1",    "secp224r1"),
         MBEDTLS_ECP_DP_SECP224R1,
     },
 #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
     {
-        { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256R1 ), "secp256r1",    "secp256r1" },
+        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256R1, "secp256r1",    "secp256r1"),
         MBEDTLS_ECP_DP_SECP256R1,
     },
 #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
     {
-        { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP384R1 ), "secp384r1",    "secp384r1" },
+        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP384R1, "secp384r1",    "secp384r1"),
         MBEDTLS_ECP_DP_SECP384R1,
     },
 #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
     {
-        { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP521R1 ), "secp521r1",    "secp521r1" },
+        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP521R1, "secp521r1",    "secp521r1"),
         MBEDTLS_ECP_DP_SECP521R1,
     },
 #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
     {
-        { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192K1 ), "secp192k1",    "secp192k1" },
+        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192K1, "secp192k1",    "secp192k1"),
         MBEDTLS_ECP_DP_SECP192K1,
     },
 #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
     {
-        { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224K1 ), "secp224k1",    "secp224k1" },
+        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224K1, "secp224k1",    "secp224k1"),
         MBEDTLS_ECP_DP_SECP224K1,
     },
 #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
     {
-        { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256K1 ), "secp256k1",    "secp256k1" },
+        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256K1, "secp256k1",    "secp256k1"),
         MBEDTLS_ECP_DP_SECP256K1,
     },
 #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
     {
-        { ADD_LEN( MBEDTLS_OID_EC_GRP_BP256R1 ),   "brainpoolP256r1","brainpool256r1" },
+        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP256R1,   "brainpoolP256r1", "brainpool256r1"),
         MBEDTLS_ECP_DP_BP256R1,
     },
 #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
     {
-        { ADD_LEN( MBEDTLS_OID_EC_GRP_BP384R1 ),   "brainpoolP384r1","brainpool384r1" },
+        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP384R1,   "brainpoolP384r1", "brainpool384r1"),
         MBEDTLS_ECP_DP_BP384R1,
     },
 #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
     {
-        { ADD_LEN( MBEDTLS_OID_EC_GRP_BP512R1 ),   "brainpoolP512r1","brainpool512r1" },
+        OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP512R1,   "brainpoolP512r1", "brainpool512r1"),
         MBEDTLS_ECP_DP_BP512R1,
     },
 #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
     {
-        { NULL, 0, NULL, NULL },
+        NULL_OID_DESCRIPTOR,
         MBEDTLS_ECP_DP_NONE,
     },
 };
 
 FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp)
 FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id)
-FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id)
+FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp,
+                        oid_ecp_grp_t,
+                        oid_ecp_grp,
+                        mbedtls_ecp_group_id,
+                        grp_id)
 #endif /* MBEDTLS_ECP_C */
 
 #if defined(MBEDTLS_CIPHER_C)
@@ -550,24 +637,27 @@
 static const oid_cipher_alg_t oid_cipher_alg[] =
 {
     {
-        { ADD_LEN( MBEDTLS_OID_DES_CBC ),              "desCBC",       "DES-CBC" },
+        OID_DESCRIPTOR(MBEDTLS_OID_DES_CBC,              "desCBC",       "DES-CBC"),
         MBEDTLS_CIPHER_DES_CBC,
     },
     {
-        { ADD_LEN( MBEDTLS_OID_DES_EDE3_CBC ),         "des-ede3-cbc", "DES-EDE3-CBC" },
+        OID_DESCRIPTOR(MBEDTLS_OID_DES_EDE3_CBC,         "des-ede3-cbc", "DES-EDE3-CBC"),
         MBEDTLS_CIPHER_DES_EDE3_CBC,
     },
     {
-        { NULL, 0, NULL, NULL },
+        NULL_OID_DESCRIPTOR,
         MBEDTLS_CIPHER_NONE,
     },
 };
 
 FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg)
-FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg)
+FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg,
+                 oid_cipher_alg_t,
+                 cipher_alg,
+                 mbedtls_cipher_type_t,
+                 cipher_alg)
 #endif /* MBEDTLS_CIPHER_C */
 
-#if defined(MBEDTLS_MD_C)
 /*
  * For digestAlgorithm
  */
@@ -578,65 +668,61 @@
 
 static const oid_md_alg_t oid_md_alg[] =
 {
-#if defined(MBEDTLS_MD2_C)
+#if defined(MBEDTLS_HAS_ALG_MD5_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD2 ),       "id-md2",       "MD2" },
-        MBEDTLS_MD_MD2,
-    },
-#endif /* MBEDTLS_MD2_C */
-#if defined(MBEDTLS_MD4_C)
-    {
-        { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD4 ),       "id-md4",       "MD4" },
-        MBEDTLS_MD_MD4,
-    },
-#endif /* MBEDTLS_MD4_C */
-#if defined(MBEDTLS_MD5_C)
-    {
-        { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD5 ),       "id-md5",       "MD5" },
+        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_MD5,       "id-md5",       "MD5"),
         MBEDTLS_MD_MD5,
     },
-#endif /* MBEDTLS_MD5_C */
-#if defined(MBEDTLS_SHA1_C)
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA1 ),      "id-sha1",      "SHA-1" },
+        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA1,      "id-sha1",      "SHA-1"),
         MBEDTLS_MD_SHA1,
     },
-#endif /* MBEDTLS_SHA1_C */
-#if defined(MBEDTLS_SHA256_C)
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA224 ),    "id-sha224",    "SHA-224" },
+        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA224,    "id-sha224",    "SHA-224"),
         MBEDTLS_MD_SHA224,
     },
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA256 ),    "id-sha256",    "SHA-256" },
+        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA256,    "id-sha256",    "SHA-256"),
         MBEDTLS_MD_SHA256,
     },
-#endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA512_C)
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA384 ),    "id-sha384",    "SHA-384" },
+        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA384,    "id-sha384",    "SHA-384"),
         MBEDTLS_MD_SHA384,
     },
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA512 ),    "id-sha512",    "SHA-512" },
+        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA512,    "id-sha512",    "SHA-512"),
         MBEDTLS_MD_SHA512,
     },
-#endif /* MBEDTLS_SHA512_C */
-#if defined(MBEDTLS_RIPEMD160_C)
+#endif
+#if defined(MBEDTLS_HAS_ALG_RIPEMD160_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_RIPEMD160 ),       "id-ripemd160",       "RIPEMD-160" },
+        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_RIPEMD160, "id-ripemd160", "RIPEMD-160"),
         MBEDTLS_MD_RIPEMD160,
     },
-#endif /* MBEDTLS_RIPEMD160_C */
+#endif
     {
-        { NULL, 0, NULL, NULL },
+        NULL_OID_DESCRIPTOR,
         MBEDTLS_MD_NONE,
     },
 };
 
 FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg)
 FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg)
-FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg)
+FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md,
+                        oid_md_alg_t,
+                        oid_md_alg,
+                        mbedtls_md_type_t,
+                        md_alg)
 
 /*
  * For HMAC digestAlgorithm
@@ -648,41 +734,44 @@
 
 static const oid_md_hmac_t oid_md_hmac[] =
 {
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_HMAC_SHA1 ),      "hmacSHA1",      "HMAC-SHA-1" },
+        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA1,      "hmacSHA1",      "HMAC-SHA-1"),
         MBEDTLS_MD_SHA1,
     },
-#endif /* MBEDTLS_SHA1_C */
-#if defined(MBEDTLS_SHA256_C)
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_HMAC_SHA224 ),    "hmacSHA224",    "HMAC-SHA-224" },
+        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA224,    "hmacSHA224",    "HMAC-SHA-224"),
         MBEDTLS_MD_SHA224,
     },
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_HMAC_SHA256 ),    "hmacSHA256",    "HMAC-SHA-256" },
+        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA256,    "hmacSHA256",    "HMAC-SHA-256"),
         MBEDTLS_MD_SHA256,
     },
-#endif /* MBEDTLS_SHA256_C */
-#if defined(MBEDTLS_SHA512_C)
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_HMAC_SHA384 ),    "hmacSHA384",    "HMAC-SHA-384" },
+        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA384,    "hmacSHA384",    "HMAC-SHA-384"),
         MBEDTLS_MD_SHA384,
     },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA)
     {
-        { ADD_LEN( MBEDTLS_OID_HMAC_SHA512 ),    "hmacSHA512",    "HMAC-SHA-512" },
+        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA512,    "hmacSHA512",    "HMAC-SHA-512"),
         MBEDTLS_MD_SHA512,
     },
-#endif /* MBEDTLS_SHA512_C */
+#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA */
     {
-        { NULL, 0, NULL, NULL },
+        NULL_OID_DESCRIPTOR,
         MBEDTLS_MD_NONE,
     },
 };
 
 FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac)
 FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac)
-#endif /* MBEDTLS_MD_C */
 
 #if defined(MBEDTLS_PKCS12_C)
 /*
@@ -697,71 +786,100 @@
 static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] =
 {
     {
-        { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" },
+        OID_DESCRIPTOR(MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC,
+                       "pbeWithSHAAnd3-KeyTripleDES-CBC",
+                       "PBE with SHA1 and 3-Key 3DES"),
         MBEDTLS_MD_SHA1,      MBEDTLS_CIPHER_DES_EDE3_CBC,
     },
     {
-        { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" },
+        OID_DESCRIPTOR(MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC,
+                       "pbeWithSHAAnd2-KeyTripleDES-CBC",
+                       "PBE with SHA1 and 2-Key 3DES"),
         MBEDTLS_MD_SHA1,      MBEDTLS_CIPHER_DES_EDE_CBC,
     },
     {
-        { NULL, 0, NULL, NULL },
+        NULL_OID_DESCRIPTOR,
         MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE,
     },
 };
 
 FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg)
-FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, mbedtls_cipher_type_t, cipher_alg)
+FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg,
+                 oid_pkcs12_pbe_alg_t,
+                 pkcs12_pbe_alg,
+                 mbedtls_md_type_t,
+                 md_alg,
+                 mbedtls_cipher_type_t,
+                 cipher_alg)
 #endif /* MBEDTLS_PKCS12_C */
 
-#define OID_SAFE_SNPRINTF                               \
-    do {                                                \
-        if( ret < 0 || (size_t) ret >= n )              \
-            return( MBEDTLS_ERR_OID_BUF_TOO_SMALL );    \
-                                                        \
-        n -= (size_t) ret;                              \
-        p += (size_t) ret;                              \
-    } while( 0 )
-
 /* Return the x.y.z.... style numeric string for the given OID */
-int mbedtls_oid_get_numeric_string( char *buf, size_t size,
-                            const mbedtls_asn1_buf *oid )
+int mbedtls_oid_get_numeric_string(char *buf, size_t size,
+                                   const mbedtls_asn1_buf *oid)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t i, n;
-    unsigned int value;
-    char *p;
+    char *p = buf;
+    size_t n = size;
+    unsigned int value = 0;
 
-    p = buf;
-    n = size;
-
-    /* First byte contains first two dots */
-    if( oid->len > 0 )
-    {
-        ret = mbedtls_snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 );
-        OID_SAFE_SNPRINTF;
+    if (size > INT_MAX) {
+        /* Avoid overflow computing return value */
+        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
     }
 
-    value = 0;
-    for( i = 1; i < oid->len; i++ )
-    {
+    if (oid->len <= 0) {
+        /* OID must not be empty */
+        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+    }
+
+    for (size_t i = 0; i < oid->len; i++) {
         /* Prevent overflow in value. */
-        if( ( ( value << 7 ) >> 7 ) != value )
-            return( MBEDTLS_ERR_OID_BUF_TOO_SMALL );
+        if (value > (UINT_MAX >> 7)) {
+            return MBEDTLS_ERR_ASN1_INVALID_DATA;
+        }
+        if ((value == 0) && ((oid->p[i]) == 0x80)) {
+            /* Overlong encoding is not allowed */
+            return MBEDTLS_ERR_ASN1_INVALID_DATA;
+        }
 
         value <<= 7;
-        value += oid->p[i] & 0x7F;
+        value |= oid->p[i] & 0x7F;
 
-        if( !( oid->p[i] & 0x80 ) )
-        {
+        if (!(oid->p[i] & 0x80)) {
             /* Last byte */
-            ret = mbedtls_snprintf( p, n, ".%u", value );
-            OID_SAFE_SNPRINTF;
+            if (n == size) {
+                int component1;
+                unsigned int component2;
+                /* First subidentifier contains first two OID components */
+                if (value >= 80) {
+                    component1 = '2';
+                    component2 = value - 80;
+                } else if (value >= 40) {
+                    component1 = '1';
+                    component2 = value - 40;
+                } else {
+                    component1 = '0';
+                    component2 = value;
+                }
+                ret = mbedtls_snprintf(p, n, "%c.%u", component1, component2);
+            } else {
+                ret = mbedtls_snprintf(p, n, ".%u", value);
+            }
+            if (ret < 2 || (size_t) ret >= n) {
+                return MBEDTLS_ERR_OID_BUF_TOO_SMALL;
+            }
+            n -= (size_t) ret;
+            p += ret;
             value = 0;
         }
     }
 
-    return( (int) ( size - n ) );
+    if (value != 0) {
+        /* Unterminated subidentifier */
+        return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+    }
+
+    return (int) (size - n);
 }
 
 #endif /* MBEDTLS_OID_C */
diff --git a/lib/libmbedtls/mbedtls/library/padlock.c b/lib/libmbedtls/mbedtls/library/padlock.c
index 8373374..f42c40f 100644
--- a/lib/libmbedtls/mbedtls/library/padlock.c
+++ b/lib/libmbedtls/mbedtls/library/padlock.c
@@ -27,27 +27,22 @@
 
 #if defined(MBEDTLS_PADLOCK_C)
 
-#include "mbedtls/padlock.h"
+#include "padlock.h"
 
 #include <string.h>
 
-#ifndef asm
-#define asm __asm
-#endif
-
 #if defined(MBEDTLS_HAVE_X86)
 
 /*
  * PadLock detection routine
  */
-int mbedtls_padlock_has_support( int feature )
+int mbedtls_padlock_has_support(int feature)
 {
     static int flags = -1;
     int ebx = 0, edx = 0;
 
-    if( flags == -1 )
-    {
-        asm( "movl  %%ebx, %0           \n\t"
+    if (flags == -1) {
+        asm ("movl  %%ebx, %0           \n\t"
              "movl  $0xC0000000, %%eax  \n\t"
              "cpuid                     \n\t"
              "cmpl  $0xC0000001, %%eax  \n\t"
@@ -60,21 +55,21 @@
              "movl  %2, %%ebx           \n\t"
              : "=m" (ebx), "=m" (edx)
              :  "m" (ebx)
-             : "eax", "ecx", "edx" );
+             : "eax", "ecx", "edx");
 
         flags = edx;
     }
 
-    return( flags & feature );
+    return flags & feature;
 }
 
 /*
  * PadLock AES-ECB block en(de)cryption
  */
-int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx,
-                       int mode,
-                       const unsigned char input[16],
-                       unsigned char output[16] )
+int mbedtls_padlock_xcryptecb(mbedtls_aes_context *ctx,
+                              int mode,
+                              const unsigned char input[16],
+                              unsigned char output[16])
 {
     int ebx = 0;
     uint32_t *rk;
@@ -82,14 +77,19 @@
     uint32_t *ctrl;
     unsigned char buf[256];
 
-    rk  = ctx->rk;
-    blk = MBEDTLS_PADLOCK_ALIGN16( buf );
-    memcpy( blk, input, 16 );
+    rk = ctx->buf + ctx->rk_offset;
 
-     ctrl = blk + 4;
-    *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 );
+    if (((long) rk & 15) != 0) {
+        return MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED;
+    }
 
-    asm( "pushfl                        \n\t"
+    blk = MBEDTLS_PADLOCK_ALIGN16(buf);
+    memcpy(blk, input, 16);
+
+    ctrl = blk + 4;
+    *ctrl = 0x80 | ctx->nr | ((ctx->nr + (mode^1) - 10) << 9);
+
+    asm ("pushfl                        \n\t"
          "popfl                         \n\t"
          "movl    %%ebx, %0             \n\t"
          "movl    $1, %%ecx             \n\t"
@@ -101,22 +101,22 @@
          "movl    %1, %%ebx             \n\t"
          : "=m" (ebx)
          :  "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk)
-         : "memory", "ecx", "edx", "esi", "edi" );
+         : "memory", "ecx", "edx", "esi", "edi");
 
-    memcpy( output, blk, 16 );
+    memcpy(output, blk, 16);
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * PadLock AES-CBC buffer en(de)cryption
  */
-int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx,
-                       int mode,
-                       size_t length,
-                       unsigned char iv[16],
-                       const unsigned char *input,
-                       unsigned char *output )
+int mbedtls_padlock_xcryptcbc(mbedtls_aes_context *ctx,
+                              int mode,
+                              size_t length,
+                              unsigned char iv[16],
+                              const unsigned char *input,
+                              unsigned char *output)
 {
     int ebx = 0;
     size_t count;
@@ -125,20 +125,23 @@
     uint32_t *ctrl;
     unsigned char buf[256];
 
-    if( ( (long) input  & 15 ) != 0 ||
-        ( (long) output & 15 ) != 0 )
-        return( MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED );
+    rk = ctx->buf + ctx->rk_offset;
 
-    rk = ctx->rk;
-    iw = MBEDTLS_PADLOCK_ALIGN16( buf );
-    memcpy( iw, iv, 16 );
+    if (((long) input  & 15) != 0 ||
+        ((long) output & 15) != 0 ||
+        ((long) rk & 15) != 0) {
+        return MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED;
+    }
 
-     ctrl = iw + 4;
-    *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode ^ 1 ) - 10 ) << 9 );
+    iw = MBEDTLS_PADLOCK_ALIGN16(buf);
+    memcpy(iw, iv, 16);
 
-    count = ( length + 15 ) >> 4;
+    ctrl = iw + 4;
+    *ctrl = 0x80 | ctx->nr | ((ctx->nr + (mode ^ 1) - 10) << 9);
 
-    asm( "pushfl                        \n\t"
+    count = (length + 15) >> 4;
+
+    asm ("pushfl                        \n\t"
          "popfl                         \n\t"
          "movl    %%ebx, %0             \n\t"
          "movl    %2, %%ecx             \n\t"
@@ -151,12 +154,12 @@
          "movl    %1, %%ebx             \n\t"
          : "=m" (ebx)
          :  "m" (ebx), "m" (count), "m" (ctrl),
-            "m"  (rk), "m" (input), "m" (output), "m" (iw)
-         : "memory", "eax", "ecx", "edx", "esi", "edi" );
+         "m"  (rk), "m" (input), "m" (output), "m" (iw)
+         : "memory", "eax", "ecx", "edx", "esi", "edi");
 
-    memcpy( iv, iw, 16 );
+    memcpy(iv, iw, 16);
 
-    return( 0 );
+    return 0;
 }
 
 #endif /* MBEDTLS_HAVE_X86 */
diff --git a/lib/libmbedtls/mbedtls/library/padlock.h b/lib/libmbedtls/mbedtls/library/padlock.h
new file mode 100644
index 0000000..b5f0d7d
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/padlock.h
@@ -0,0 +1,120 @@
+/**
+ * \file padlock.h
+ *
+ * \brief VIA PadLock ACE for HW encryption/decryption supported by some
+ *        processors
+ *
+ * \warning These functions are only for internal use by other library
+ *          functions; you must not call them directly.
+ */
+/*
+ *  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_PADLOCK_H
+#define MBEDTLS_PADLOCK_H
+
+#include "mbedtls/build_info.h"
+
+#include "mbedtls/aes.h"
+
+#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED               -0x0030  /**< Input data should be aligned. */
+
+#if defined(__has_feature)
+#if __has_feature(address_sanitizer)
+#define MBEDTLS_HAVE_ASAN
+#endif
+#endif
+
+/* Some versions of ASan result in errors about not enough registers */
+#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) && \
+    !defined(MBEDTLS_HAVE_ASAN)
+
+#ifndef MBEDTLS_HAVE_X86
+#define MBEDTLS_HAVE_X86
+#endif
+
+#include <stdint.h>
+
+#define MBEDTLS_PADLOCK_RNG 0x000C
+#define MBEDTLS_PADLOCK_ACE 0x00C0
+#define MBEDTLS_PADLOCK_PHE 0x0C00
+#define MBEDTLS_PADLOCK_PMM 0x3000
+
+#define MBEDTLS_PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) (x) & ~15))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Internal PadLock detection routine
+ *
+ * \note           This function is only for internal use by other library
+ *                 functions; you must not call it directly.
+ *
+ * \param feature  The feature to detect
+ *
+ * \return         non-zero if CPU has support for the feature, 0 otherwise
+ */
+int mbedtls_padlock_has_support(int feature);
+
+/**
+ * \brief          Internal PadLock AES-ECB block en(de)cryption
+ *
+ * \note           This function is only for internal use by other library
+ *                 functions; you must not call it directly.
+ *
+ * \param ctx      AES context
+ * \param mode     MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
+ * \param input    16-byte input block
+ * \param output   16-byte output block
+ *
+ * \return         0 if success, 1 if operation failed
+ */
+int mbedtls_padlock_xcryptecb(mbedtls_aes_context *ctx,
+                              int mode,
+                              const unsigned char input[16],
+                              unsigned char output[16]);
+
+/**
+ * \brief          Internal PadLock AES-CBC buffer en(de)cryption
+ *
+ * \note           This function is only for internal use by other library
+ *                 functions; you must not call it directly.
+ *
+ * \param ctx      AES context
+ * \param mode     MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
+ * \param length   length of the input data
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ *
+ * \return         0 if success, 1 if operation failed
+ */
+int mbedtls_padlock_xcryptcbc(mbedtls_aes_context *ctx,
+                              int mode,
+                              size_t length,
+                              unsigned char iv[16],
+                              const unsigned char *input,
+                              unsigned char *output);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAVE_X86  */
+
+#endif /* padlock.h */
diff --git a/lib/libmbedtls/mbedtls/library/pem.c b/lib/libmbedtls/mbedtls/library/pem.c
index fcfde94..84bbb3d 100644
--- a/lib/libmbedtls/mbedtls/library/pem.c
+++ b/lib/libmbedtls/mbedtls/library/pem.c
@@ -25,167 +25,294 @@
 #include "mbedtls/base64.h"
 #include "mbedtls/des.h"
 #include "mbedtls/aes.h"
-#include "mbedtls/md5.h"
+#include "mbedtls/md.h"
 #include "mbedtls/cipher.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
+#include "hash_info.h"
 
 #include <string.h>
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free       free
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "psa/crypto.h"
 #endif
 
+#if !defined(MBEDTLS_MD5_C)
+#include "mbedtls/psa_util.h"
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,          \
+                                                           psa_to_md_errors,                     \
+                                                           psa_generic_status_to_mbedtls)
+#endif
+
+#include "mbedtls/legacy_or_psa.h"
+
+#if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA) &&  \
+    defined(MBEDTLS_CIPHER_MODE_CBC) &&                             \
+    (defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C))
+#define PEM_RFC1421
+#endif /* MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA &&
+          MBEDTLS_CIPHER_MODE_CBC &&
+          ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
+
 #if defined(MBEDTLS_PEM_PARSE_C)
-void mbedtls_pem_init( mbedtls_pem_context *ctx )
+void mbedtls_pem_init(mbedtls_pem_context *ctx)
 {
-    memset( ctx, 0, sizeof( mbedtls_pem_context ) );
+    memset(ctx, 0, sizeof(mbedtls_pem_context));
 }
 
-#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) &&         \
-    ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) )
+#if defined(PEM_RFC1421)
 /*
  * Read a 16-byte hex string and convert it to binary
  */
-static int pem_get_iv( const unsigned char *s, unsigned char *iv,
-                       size_t iv_len )
+static int pem_get_iv(const unsigned char *s, unsigned char *iv,
+                      size_t iv_len)
 {
     size_t i, j, k;
 
-    memset( iv, 0, iv_len );
+    memset(iv, 0, iv_len);
 
-    for( i = 0; i < iv_len * 2; i++, s++ )
-    {
-        if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
-        if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
-        if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
-            return( MBEDTLS_ERR_PEM_INVALID_ENC_IV );
+    for (i = 0; i < iv_len * 2; i++, s++) {
+        if (*s >= '0' && *s <= '9') {
+            j = *s - '0';
+        } else
+        if (*s >= 'A' && *s <= 'F') {
+            j = *s - '7';
+        } else
+        if (*s >= 'a' && *s <= 'f') {
+            j = *s - 'W';
+        } else {
+            return MBEDTLS_ERR_PEM_INVALID_ENC_IV;
+        }
 
-        k = ( ( i & 1 ) != 0 ) ? j : j << 4;
+        k = ((i & 1) != 0) ? j : j << 4;
 
-        iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
+        iv[i >> 1] = (unsigned char) (iv[i >> 1] | k);
     }
 
-    return( 0 );
+    return 0;
 }
 
-static int pem_pbkdf1( unsigned char *key, size_t keylen,
-                       unsigned char *iv,
-                       const unsigned char *pwd, size_t pwdlen )
+#if defined(MBEDTLS_MD5_C)
+static int pem_pbkdf1(unsigned char *key, size_t keylen,
+                      unsigned char *iv,
+                      const unsigned char *pwd, size_t pwdlen)
 {
-    mbedtls_md5_context md5_ctx;
+    mbedtls_md_context_t md5_ctx;
+    const mbedtls_md_info_t *md5_info;
     unsigned char md5sum[16];
     size_t use_len;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    mbedtls_md5_init( &md5_ctx );
+    mbedtls_md_init(&md5_ctx);
+
+    /* Prepare the context. (setup() errors gracefully on NULL info.) */
+    md5_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5);
+    if ((ret = mbedtls_md_setup(&md5_ctx, md5_info, 0)) != 0) {
+        goto exit;
+    }
 
     /*
      * key[ 0..15] = MD5(pwd || IV)
      */
-    if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 )
+    if ((ret = mbedtls_md_starts(&md5_ctx)) != 0) {
         goto exit;
-    if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 )
+    }
+    if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) {
         goto exit;
-    if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv,  8 ) ) != 0 )
+    }
+    if ((ret = mbedtls_md_update(&md5_ctx, iv,  8)) != 0) {
         goto exit;
-    if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 )
-        goto exit;
-
-    if( keylen <= 16 )
-    {
-        memcpy( key, md5sum, keylen );
+    }
+    if ((ret = mbedtls_md_finish(&md5_ctx, md5sum)) != 0) {
         goto exit;
     }
 
-    memcpy( key, md5sum, 16 );
+    if (keylen <= 16) {
+        memcpy(key, md5sum, keylen);
+        goto exit;
+    }
+
+    memcpy(key, md5sum, 16);
 
     /*
      * key[16..23] = MD5(key[ 0..15] || pwd || IV])
      */
-    if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 )
+    if ((ret = mbedtls_md_starts(&md5_ctx)) != 0) {
         goto exit;
-    if( ( ret = mbedtls_md5_update_ret( &md5_ctx, md5sum, 16 ) ) != 0 )
+    }
+    if ((ret = mbedtls_md_update(&md5_ctx, md5sum, 16)) != 0) {
         goto exit;
-    if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 )
+    }
+    if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) {
         goto exit;
-    if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 )
+    }
+    if ((ret = mbedtls_md_update(&md5_ctx, iv, 8)) != 0) {
         goto exit;
-    if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 )
+    }
+    if ((ret = mbedtls_md_finish(&md5_ctx, md5sum)) != 0) {
         goto exit;
+    }
 
     use_len = 16;
-    if( keylen < 32 )
+    if (keylen < 32) {
         use_len = keylen - 16;
+    }
 
-    memcpy( key + 16, md5sum, use_len );
+    memcpy(key + 16, md5sum, use_len);
 
 exit:
-    mbedtls_md5_free( &md5_ctx );
-    mbedtls_platform_zeroize( md5sum, 16 );
+    mbedtls_md_free(&md5_ctx);
+    mbedtls_platform_zeroize(md5sum, 16);
 
-    return( ret );
+    return ret;
 }
+#else
+static int pem_pbkdf1(unsigned char *key, size_t keylen,
+                      unsigned char *iv,
+                      const unsigned char *pwd, size_t pwdlen)
+{
+    unsigned char md5sum[16];
+    psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
+    size_t output_length = 0;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+
+    if ((status = psa_hash_setup(&operation, PSA_ALG_MD5)) != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if ((status = psa_hash_update(&operation, pwd, pwdlen)) != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if ((status = psa_hash_update(&operation, iv, 8)) != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if ((status = psa_hash_finish(&operation, md5sum,
+                                  PSA_HASH_LENGTH(PSA_ALG_MD5),
+                                  &output_length)) != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if ((status = psa_hash_abort(&operation)) != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    /*
+     * key[ 0..15] = MD5(pwd || IV)
+     */
+    if (keylen <= 16) {
+        memcpy(key, md5sum, keylen);
+        goto exit;
+    }
+
+    memcpy(key, md5sum, 16);
+
+    /*
+     * key[16..23] = MD5(key[ 0..15] || pwd || IV])
+     */
+    if ((status = psa_hash_setup(&operation, PSA_ALG_MD5)) != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if ((status = psa_hash_update(&operation, md5sum, 16)) != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if ((status = psa_hash_update(&operation, pwd, pwdlen)) != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if ((status = psa_hash_update(&operation, iv, 8)) != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if ((status = psa_hash_finish(&operation, md5sum,
+                                  PSA_HASH_LENGTH(PSA_ALG_MD5),
+                                  &output_length)) != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if ((status = psa_hash_abort(&operation)) != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    size_t use_len = 16;
+    if (keylen < 32) {
+        use_len = keylen - 16;
+    }
+
+    memcpy(key + 16, md5sum, use_len);
+
+exit:
+    mbedtls_platform_zeroize(md5sum, 16);
+
+    return PSA_TO_MBEDTLS_ERR(status);
+}
+#endif /* MBEDTLS_MD5_C */
 
 #if defined(MBEDTLS_DES_C)
 /*
  * Decrypt with DES-CBC, using PBKDF1 for key derivation
  */
-static int pem_des_decrypt( unsigned char des_iv[8],
-                            unsigned char *buf, size_t buflen,
-                            const unsigned char *pwd, size_t pwdlen )
+static int pem_des_decrypt(unsigned char des_iv[8],
+                           unsigned char *buf, size_t buflen,
+                           const unsigned char *pwd, size_t pwdlen)
 {
     mbedtls_des_context des_ctx;
     unsigned char des_key[8];
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    mbedtls_des_init( &des_ctx );
+    mbedtls_des_init(&des_ctx);
 
-    if( ( ret = pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ) ) != 0 )
+    if ((ret = pem_pbkdf1(des_key, 8, des_iv, pwd, pwdlen)) != 0) {
         goto exit;
+    }
 
-    if( ( ret = mbedtls_des_setkey_dec( &des_ctx, des_key ) ) != 0 )
+    if ((ret = mbedtls_des_setkey_dec(&des_ctx, des_key)) != 0) {
         goto exit;
-    ret = mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen,
-                     des_iv, buf, buf );
+    }
+    ret = mbedtls_des_crypt_cbc(&des_ctx, MBEDTLS_DES_DECRYPT, buflen,
+                                des_iv, buf, buf);
 
 exit:
-    mbedtls_des_free( &des_ctx );
-    mbedtls_platform_zeroize( des_key, 8 );
+    mbedtls_des_free(&des_ctx);
+    mbedtls_platform_zeroize(des_key, 8);
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
  */
-static int pem_des3_decrypt( unsigned char des3_iv[8],
-                             unsigned char *buf, size_t buflen,
-                             const unsigned char *pwd, size_t pwdlen )
+static int pem_des3_decrypt(unsigned char des3_iv[8],
+                            unsigned char *buf, size_t buflen,
+                            const unsigned char *pwd, size_t pwdlen)
 {
     mbedtls_des3_context des3_ctx;
     unsigned char des3_key[24];
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    mbedtls_des3_init( &des3_ctx );
+    mbedtls_des3_init(&des3_ctx);
 
-    if( ( ret = pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ) ) != 0 )
+    if ((ret = pem_pbkdf1(des3_key, 24, des3_iv, pwd, pwdlen)) != 0) {
         goto exit;
+    }
 
-    if( ( ret = mbedtls_des3_set3key_dec( &des3_ctx, des3_key ) ) != 0 )
+    if ((ret = mbedtls_des3_set3key_dec(&des3_ctx, des3_key)) != 0) {
         goto exit;
-    ret = mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen,
-                     des3_iv, buf, buf );
+    }
+    ret = mbedtls_des3_crypt_cbc(&des3_ctx, MBEDTLS_DES_DECRYPT, buflen,
+                                 des3_iv, buf, buf);
 
 exit:
-    mbedtls_des3_free( &des3_ctx );
-    mbedtls_platform_zeroize( des3_key, 24 );
+    mbedtls_des3_free(&des3_ctx);
+    mbedtls_platform_zeroize(des3_key, 24);
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_DES_C */
 
@@ -193,201 +320,224 @@
 /*
  * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation
  */
-static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
-                            unsigned char *buf, size_t buflen,
-                            const unsigned char *pwd, size_t pwdlen )
+static int pem_aes_decrypt(unsigned char aes_iv[16], unsigned int keylen,
+                           unsigned char *buf, size_t buflen,
+                           const unsigned char *pwd, size_t pwdlen)
 {
     mbedtls_aes_context aes_ctx;
     unsigned char aes_key[32];
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    mbedtls_aes_init( &aes_ctx );
+    mbedtls_aes_init(&aes_ctx);
 
-    if( ( ret = pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ) ) != 0 )
+    if ((ret = pem_pbkdf1(aes_key, keylen, aes_iv, pwd, pwdlen)) != 0) {
         goto exit;
+    }
 
-    if( ( ret = mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ) ) != 0 )
+    if ((ret = mbedtls_aes_setkey_dec(&aes_ctx, aes_key, keylen * 8)) != 0) {
         goto exit;
-    ret = mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen,
-                     aes_iv, buf, buf );
+    }
+    ret = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, buflen,
+                                aes_iv, buf, buf);
 
 exit:
-    mbedtls_aes_free( &aes_ctx );
-    mbedtls_platform_zeroize( aes_key, keylen );
+    mbedtls_aes_free(&aes_ctx);
+    mbedtls_platform_zeroize(aes_key, keylen);
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_AES_C */
 
-#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
-          ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
+#endif /* PEM_RFC1421 */
 
-int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer,
-                     const unsigned char *data, const unsigned char *pwd,
-                     size_t pwdlen, size_t *use_len )
+int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer,
+                            const unsigned char *data, const unsigned char *pwd,
+                            size_t pwdlen, size_t *use_len)
 {
     int ret, enc;
     size_t len;
     unsigned char *buf;
     const unsigned char *s1, *s2, *end;
-#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) &&         \
-    ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) )
+#if defined(PEM_RFC1421)
     unsigned char pem_iv[16];
     mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE;
 #else
     ((void) pwd);
     ((void) pwdlen);
-#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
-          ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
+#endif /* PEM_RFC1421 */
 
-    if( ctx == NULL )
-        return( MBEDTLS_ERR_PEM_BAD_INPUT_DATA );
+    if (ctx == NULL) {
+        return MBEDTLS_ERR_PEM_BAD_INPUT_DATA;
+    }
 
-    s1 = (unsigned char *) strstr( (const char *) data, header );
+    s1 = (unsigned char *) strstr((const char *) data, header);
 
-    if( s1 == NULL )
-        return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
+    if (s1 == NULL) {
+        return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
+    }
 
-    s2 = (unsigned char *) strstr( (const char *) data, footer );
+    s2 = (unsigned char *) strstr((const char *) data, footer);
 
-    if( s2 == NULL || s2 <= s1 )
-        return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
+    if (s2 == NULL || s2 <= s1) {
+        return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
+    }
 
-    s1 += strlen( header );
-    if( *s1 == ' '  ) s1++;
-    if( *s1 == '\r' ) s1++;
-    if( *s1 == '\n' ) s1++;
-    else return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
+    s1 += strlen(header);
+    if (*s1 == ' ') {
+        s1++;
+    }
+    if (*s1 == '\r') {
+        s1++;
+    }
+    if (*s1 == '\n') {
+        s1++;
+    } else {
+        return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
+    }
 
     end = s2;
-    end += strlen( footer );
-    if( *end == ' '  ) end++;
-    if( *end == '\r' ) end++;
-    if( *end == '\n' ) end++;
+    end += strlen(footer);
+    if (*end == ' ') {
+        end++;
+    }
+    if (*end == '\r') {
+        end++;
+    }
+    if (*end == '\n') {
+        end++;
+    }
     *use_len = end - data;
 
     enc = 0;
 
-    if( s2 - s1 >= 22 && memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
-    {
-#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) &&         \
-    ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) )
+    if (s2 - s1 >= 22 && memcmp(s1, "Proc-Type: 4,ENCRYPTED", 22) == 0) {
+#if defined(PEM_RFC1421)
         enc++;
 
         s1 += 22;
-        if( *s1 == '\r' ) s1++;
-        if( *s1 == '\n' ) s1++;
-        else return( MBEDTLS_ERR_PEM_INVALID_DATA );
+        if (*s1 == '\r') {
+            s1++;
+        }
+        if (*s1 == '\n') {
+            s1++;
+        } else {
+            return MBEDTLS_ERR_PEM_INVALID_DATA;
+        }
 
 
 #if defined(MBEDTLS_DES_C)
-        if( s2 - s1 >= 23 && memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 )
-        {
+        if (s2 - s1 >= 23 && memcmp(s1, "DEK-Info: DES-EDE3-CBC,", 23) == 0) {
             enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC;
 
             s1 += 23;
-            if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8 ) != 0 )
-                return( MBEDTLS_ERR_PEM_INVALID_ENC_IV );
+            if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) {
+                return MBEDTLS_ERR_PEM_INVALID_ENC_IV;
+            }
 
             s1 += 16;
-        }
-        else if( s2 - s1 >= 18 && memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 )
-        {
+        } else if (s2 - s1 >= 18 && memcmp(s1, "DEK-Info: DES-CBC,", 18) == 0) {
             enc_alg = MBEDTLS_CIPHER_DES_CBC;
 
             s1 += 18;
-            if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8) != 0 )
-                return( MBEDTLS_ERR_PEM_INVALID_ENC_IV );
+            if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) {
+                return MBEDTLS_ERR_PEM_INVALID_ENC_IV;
+            }
 
             s1 += 16;
         }
 #endif /* MBEDTLS_DES_C */
 
 #if defined(MBEDTLS_AES_C)
-        if( s2 - s1 >= 14 && memcmp( s1, "DEK-Info: AES-", 14 ) == 0 )
-        {
-            if( s2 - s1 < 22 )
-                return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG );
-            else if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 )
+        if (s2 - s1 >= 14 && memcmp(s1, "DEK-Info: AES-", 14) == 0) {
+            if (s2 - s1 < 22) {
+                return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG;
+            } else if (memcmp(s1, "DEK-Info: AES-128-CBC,", 22) == 0) {
                 enc_alg = MBEDTLS_CIPHER_AES_128_CBC;
-            else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 )
+            } else if (memcmp(s1, "DEK-Info: AES-192-CBC,", 22) == 0) {
                 enc_alg = MBEDTLS_CIPHER_AES_192_CBC;
-            else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 )
+            } else if (memcmp(s1, "DEK-Info: AES-256-CBC,", 22) == 0) {
                 enc_alg = MBEDTLS_CIPHER_AES_256_CBC;
-            else
-                return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG );
+            } else {
+                return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG;
+            }
 
             s1 += 22;
-            if( s2 - s1 < 32 || pem_get_iv( s1, pem_iv, 16 ) != 0 )
-                return( MBEDTLS_ERR_PEM_INVALID_ENC_IV );
+            if (s2 - s1 < 32 || pem_get_iv(s1, pem_iv, 16) != 0) {
+                return MBEDTLS_ERR_PEM_INVALID_ENC_IV;
+            }
 
             s1 += 32;
         }
 #endif /* MBEDTLS_AES_C */
 
-        if( enc_alg == MBEDTLS_CIPHER_NONE )
-            return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG );
+        if (enc_alg == MBEDTLS_CIPHER_NONE) {
+            return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG;
+        }
 
-        if( *s1 == '\r' ) s1++;
-        if( *s1 == '\n' ) s1++;
-        else return( MBEDTLS_ERR_PEM_INVALID_DATA );
+        if (*s1 == '\r') {
+            s1++;
+        }
+        if (*s1 == '\n') {
+            s1++;
+        } else {
+            return MBEDTLS_ERR_PEM_INVALID_DATA;
+        }
 #else
-        return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE );
-#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
-          ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
+        return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE;
+#endif /* PEM_RFC1421 */
     }
 
-    if( s1 >= s2 )
-        return( MBEDTLS_ERR_PEM_INVALID_DATA );
-
-    ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 );
-
-    if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PEM_INVALID_DATA, ret ) );
-
-    if( ( buf = mbedtls_calloc( 1, len ) ) == NULL )
-        return( MBEDTLS_ERR_PEM_ALLOC_FAILED );
-
-    if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 )
-    {
-        mbedtls_platform_zeroize( buf, len );
-        mbedtls_free( buf );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PEM_INVALID_DATA, ret ) );
+    if (s1 >= s2) {
+        return MBEDTLS_ERR_PEM_INVALID_DATA;
     }
 
-    if( enc != 0 )
-    {
-#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) &&         \
-    ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) )
-        if( pwd == NULL )
-        {
-            mbedtls_platform_zeroize( buf, len );
-            mbedtls_free( buf );
-            return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED );
+    ret = mbedtls_base64_decode(NULL, 0, &len, s1, s2 - s1);
+
+    if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret);
+    }
+
+    if ((buf = mbedtls_calloc(1, len)) == NULL) {
+        return MBEDTLS_ERR_PEM_ALLOC_FAILED;
+    }
+
+    if ((ret = mbedtls_base64_decode(buf, len, &len, s1, s2 - s1)) != 0) {
+        mbedtls_platform_zeroize(buf, len);
+        mbedtls_free(buf);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret);
+    }
+
+    if (enc != 0) {
+#if defined(PEM_RFC1421)
+        if (pwd == NULL) {
+            mbedtls_platform_zeroize(buf, len);
+            mbedtls_free(buf);
+            return MBEDTLS_ERR_PEM_PASSWORD_REQUIRED;
         }
 
         ret = 0;
 
 #if defined(MBEDTLS_DES_C)
-        if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC )
-            ret = pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen );
-        else if( enc_alg == MBEDTLS_CIPHER_DES_CBC )
-            ret = pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen );
+        if (enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC) {
+            ret = pem_des3_decrypt(pem_iv, buf, len, pwd, pwdlen);
+        } else if (enc_alg == MBEDTLS_CIPHER_DES_CBC) {
+            ret = pem_des_decrypt(pem_iv, buf, len, pwd, pwdlen);
+        }
 #endif /* MBEDTLS_DES_C */
 
 #if defined(MBEDTLS_AES_C)
-        if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC )
-            ret = pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen );
-        else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC )
-            ret = pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen );
-        else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC )
-            ret = pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen );
+        if (enc_alg == MBEDTLS_CIPHER_AES_128_CBC) {
+            ret = pem_aes_decrypt(pem_iv, 16, buf, len, pwd, pwdlen);
+        } else if (enc_alg == MBEDTLS_CIPHER_AES_192_CBC) {
+            ret = pem_aes_decrypt(pem_iv, 24, buf, len, pwd, pwdlen);
+        } else if (enc_alg == MBEDTLS_CIPHER_AES_256_CBC) {
+            ret = pem_aes_decrypt(pem_iv, 32, buf, len, pwd, pwdlen);
+        }
 #endif /* MBEDTLS_AES_C */
 
-        if( ret != 0 )
-        {
-            mbedtls_free( buf );
-            return( ret );
+        if (ret != 0) {
+            mbedtls_free(buf);
+            return ret;
         }
 
         /*
@@ -396,94 +546,88 @@
          *
          * Use that as a heuristic to try to detect password mismatches.
          */
-        if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 )
-        {
-            mbedtls_platform_zeroize( buf, len );
-            mbedtls_free( buf );
-            return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH );
+        if (len <= 2 || buf[0] != 0x30 || buf[1] > 0x83) {
+            mbedtls_platform_zeroize(buf, len);
+            mbedtls_free(buf);
+            return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
         }
 #else
-        mbedtls_platform_zeroize( buf, len );
-        mbedtls_free( buf );
-        return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE );
-#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
-          ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
+        mbedtls_platform_zeroize(buf, len);
+        mbedtls_free(buf);
+        return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE;
+#endif /* PEM_RFC1421 */
     }
 
     ctx->buf = buf;
     ctx->buflen = len;
 
-    return( 0 );
+    return 0;
 }
 
-void mbedtls_pem_free( mbedtls_pem_context *ctx )
+void mbedtls_pem_free(mbedtls_pem_context *ctx)
 {
-    if ( ctx->buf != NULL )
-    {
-        mbedtls_platform_zeroize( ctx->buf, ctx->buflen );
-        mbedtls_free( ctx->buf );
+    if (ctx->buf != NULL) {
+        mbedtls_platform_zeroize(ctx->buf, ctx->buflen);
+        mbedtls_free(ctx->buf);
     }
-    mbedtls_free( ctx->info );
+    mbedtls_free(ctx->info);
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pem_context ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pem_context));
 }
 #endif /* MBEDTLS_PEM_PARSE_C */
 
 #if defined(MBEDTLS_PEM_WRITE_C)
-int mbedtls_pem_write_buffer( const char *header, const char *footer,
-                      const unsigned char *der_data, size_t der_len,
-                      unsigned char *buf, size_t buf_len, size_t *olen )
+int mbedtls_pem_write_buffer(const char *header, const char *footer,
+                             const unsigned char *der_data, size_t der_len,
+                             unsigned char *buf, size_t buf_len, size_t *olen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *encode_buf = NULL, *c, *p = buf;
     size_t len = 0, use_len, add_len = 0;
 
-    mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len );
-    add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1;
+    mbedtls_base64_encode(NULL, 0, &use_len, der_data, der_len);
+    add_len = strlen(header) + strlen(footer) + (use_len / 64) + 1;
 
-    if( use_len + add_len > buf_len )
-    {
+    if (use_len + add_len > buf_len) {
         *olen = use_len + add_len;
-        return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
+        return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
     }
 
-    if( use_len != 0 &&
-        ( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL ) )
-        return( MBEDTLS_ERR_PEM_ALLOC_FAILED );
-
-    if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data,
-                               der_len ) ) != 0 )
-    {
-        mbedtls_free( encode_buf );
-        return( ret );
+    if (use_len != 0 &&
+        ((encode_buf = mbedtls_calloc(1, use_len)) == NULL)) {
+        return MBEDTLS_ERR_PEM_ALLOC_FAILED;
     }
 
-    memcpy( p, header, strlen( header ) );
-    p += strlen( header );
+    if ((ret = mbedtls_base64_encode(encode_buf, use_len, &use_len, der_data,
+                                     der_len)) != 0) {
+        mbedtls_free(encode_buf);
+        return ret;
+    }
+
+    memcpy(p, header, strlen(header));
+    p += strlen(header);
     c = encode_buf;
 
-    while( use_len )
-    {
-        len = ( use_len > 64 ) ? 64 : use_len;
-        memcpy( p, c, len );
+    while (use_len) {
+        len = (use_len > 64) ? 64 : use_len;
+        memcpy(p, c, len);
         use_len -= len;
         p += len;
         c += len;
         *p++ = '\n';
     }
 
-    memcpy( p, footer, strlen( footer ) );
-    p += strlen( footer );
+    memcpy(p, footer, strlen(footer));
+    p += strlen(footer);
 
     *p++ = '\0';
     *olen = p - buf;
 
-     /* Clean any remaining data previously written to the buffer */
-    memset( buf + *olen, 0, buf_len - *olen );
+    /* Clean any remaining data previously written to the buffer */
+    memset(buf + *olen, 0, buf_len - *olen);
 
-    mbedtls_free( encode_buf );
-    return( 0 );
+    mbedtls_free(encode_buf);
+    return 0;
 }
 #endif /* MBEDTLS_PEM_WRITE_C */
 #endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */
-
diff --git a/lib/libmbedtls/mbedtls/library/pk.c b/lib/libmbedtls/mbedtls/library/pk.c
index 05cc213..5e18ad2 100644
--- a/lib/libmbedtls/mbedtls/library/pk.c
+++ b/lib/libmbedtls/mbedtls/library/pk.c
@@ -21,7 +21,10 @@
 
 #if defined(MBEDTLS_PK_C)
 #include "mbedtls/pk.h"
-#include "mbedtls/pk_internal.h"
+#include "pk_wrap.h"
+#include "pkwrite.h"
+
+#include "hash_info.h"
 
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
@@ -36,26 +39,25 @@
 #include "mbedtls/ecdsa.h"
 #endif
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_PSA_CRYPTO_C)
 #include "mbedtls/psa_util.h"
+#define PSA_PK_TO_MBEDTLS_ERR(status) psa_pk_status_to_mbedtls(status)
+#define PSA_PK_RSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,     \
+                                                                  psa_to_pk_rsa_errors,            \
+                                                                  psa_pk_status_to_mbedtls)
+#define PSA_PK_ECDSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                                    psa_to_pk_ecdsa_errors,        \
+                                                                    psa_pk_status_to_mbedtls)
 #endif
 
 #include <limits.h>
 #include <stdint.h>
 
-/* Parameter validation macros based on platform_util.h */
-#define PK_VALIDATE_RET( cond )    \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA )
-#define PK_VALIDATE( cond )        \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
-
 /*
  * Initialise a mbedtls_pk_context
  */
-void mbedtls_pk_init( mbedtls_pk_context *ctx )
+void mbedtls_pk_init(mbedtls_pk_context *ctx)
 {
-    PK_VALIDATE( ctx != NULL );
-
     ctx->pk_info = NULL;
     ctx->pk_ctx = NULL;
 }
@@ -63,24 +65,25 @@
 /*
  * Free (the components of) a mbedtls_pk_context
  */
-void mbedtls_pk_free( mbedtls_pk_context *ctx )
+void mbedtls_pk_free(mbedtls_pk_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    if ( ctx->pk_info != NULL )
-        ctx->pk_info->ctx_free_func( ctx->pk_ctx );
+    if (ctx->pk_info != NULL) {
+        ctx->pk_info->ctx_free_func(ctx->pk_ctx);
+    }
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pk_context));
 }
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
 /*
  * Initialize a restart context
  */
-void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx )
+void mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx)
 {
-    PK_VALIDATE( ctx != NULL );
     ctx->pk_info = NULL;
     ctx->rs_ctx = NULL;
 }
@@ -88,15 +91,14 @@
 /*
  * Free the components of a restart context
  */
-void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx )
+void mbedtls_pk_restart_free(mbedtls_pk_restart_ctx *ctx)
 {
-    if( ctx == NULL || ctx->pk_info == NULL ||
-        ctx->pk_info->rs_free_func == NULL )
-    {
+    if (ctx == NULL || ctx->pk_info == NULL ||
+        ctx->pk_info->rs_free_func == NULL) {
         return;
     }
 
-    ctx->pk_info->rs_free_func( ctx->rs_ctx );
+    ctx->pk_info->rs_free_func(ctx->rs_ctx);
 
     ctx->pk_info = NULL;
     ctx->rs_ctx = NULL;
@@ -106,79 +108,87 @@
 /*
  * Get pk_info structure from type
  */
-const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type )
+const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type)
 {
-    switch( pk_type ) {
+    switch (pk_type) {
 #if defined(MBEDTLS_RSA_C)
         case MBEDTLS_PK_RSA:
-            return( &mbedtls_rsa_info );
+            return &mbedtls_rsa_info;
 #endif
 #if defined(MBEDTLS_ECP_C)
         case MBEDTLS_PK_ECKEY:
-            return( &mbedtls_eckey_info );
+            return &mbedtls_eckey_info;
         case MBEDTLS_PK_ECKEY_DH:
-            return( &mbedtls_eckeydh_info );
+            return &mbedtls_eckeydh_info;
 #endif
-#if defined(MBEDTLS_ECDSA_C)
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
         case MBEDTLS_PK_ECDSA:
-            return( &mbedtls_ecdsa_info );
+            return &mbedtls_ecdsa_info;
 #endif
         /* MBEDTLS_PK_RSA_ALT omitted on purpose */
         default:
-            return( NULL );
+            return NULL;
     }
 }
 
 /*
  * Initialise context
  */
-int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info )
+int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info)
 {
-    PK_VALIDATE_RET( ctx != NULL );
-    if( info == NULL || ctx->pk_info != NULL )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+    if (info == NULL || ctx->pk_info != NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
 
-    if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
-        return( MBEDTLS_ERR_PK_ALLOC_FAILED );
+    if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) {
+        return MBEDTLS_ERR_PK_ALLOC_FAILED;
+    }
 
     ctx->pk_info = info;
 
-    return( 0 );
+    return 0;
 }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 /*
  * Initialise a PSA-wrapping context
  */
-int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx,
-                             const psa_key_id_t key )
+int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx,
+                            const mbedtls_svc_key_id_t key)
 {
-    const mbedtls_pk_info_t * const info = &mbedtls_pk_opaque_info;
+    const mbedtls_pk_info_t *info = NULL;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_id_t *pk_ctx;
+    mbedtls_svc_key_id_t *pk_ctx;
     psa_key_type_t type;
 
-    if( ctx == NULL || ctx->pk_info != NULL )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+    if (ctx == NULL || ctx->pk_info != NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
 
-    if( PSA_SUCCESS != psa_get_key_attributes( key, &attributes ) )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
-    type = psa_get_key_type( &attributes );
-    psa_reset_key_attributes( &attributes );
+    if (PSA_SUCCESS != psa_get_key_attributes(key, &attributes)) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+    type = psa_get_key_type(&attributes);
+    psa_reset_key_attributes(&attributes);
 
-    /* Current implementation of can_do() relies on this. */
-    if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( type ) )
-        return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ;
+    if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
+        info = &mbedtls_pk_ecdsa_opaque_info;
+    } else if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
+        info = &mbedtls_pk_rsa_opaque_info;
+    } else {
+        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+    }
 
-    if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
-        return( MBEDTLS_ERR_PK_ALLOC_FAILED );
+    if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) {
+        return MBEDTLS_ERR_PK_ALLOC_FAILED;
+    }
 
     ctx->pk_info = info;
 
-    pk_ctx = (psa_key_id_t *) ctx->pk_ctx;
+    pk_ctx = (mbedtls_svc_key_id_t *) ctx->pk_ctx;
     *pk_ctx = key;
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
@@ -186,20 +196,21 @@
 /*
  * Initialize an RSA-alt context
  */
-int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key,
-                         mbedtls_pk_rsa_alt_decrypt_func decrypt_func,
-                         mbedtls_pk_rsa_alt_sign_func sign_func,
-                         mbedtls_pk_rsa_alt_key_len_func key_len_func )
+int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key,
+                             mbedtls_pk_rsa_alt_decrypt_func decrypt_func,
+                             mbedtls_pk_rsa_alt_sign_func sign_func,
+                             mbedtls_pk_rsa_alt_key_len_func key_len_func)
 {
     mbedtls_rsa_alt_context *rsa_alt;
     const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info;
 
-    PK_VALIDATE_RET( ctx != NULL );
-    if( ctx->pk_info != NULL )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+    if (ctx->pk_info != NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
 
-    if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
-        return( MBEDTLS_ERR_PK_ALLOC_FAILED );
+    if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) {
+        return MBEDTLS_ERR_PK_ALLOC_FAILED;
+    }
 
     ctx->pk_info = info;
 
@@ -210,377 +221,632 @@
     rsa_alt->sign_func = sign_func;
     rsa_alt->key_len_func = key_len_func;
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
 
 /*
  * Tell if a PK can do the operations of the given type
  */
-int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type )
+int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type)
 {
     /* A context with null pk_info is not set up yet and can't do anything.
      * For backward compatibility, also accept NULL instead of a context
      * pointer. */
-    if( ctx == NULL || ctx->pk_info == NULL )
-        return( 0 );
+    if (ctx == NULL || ctx->pk_info == NULL) {
+        return 0;
+    }
 
-    return( ctx->pk_info->can_do( type ) );
+    return ctx->pk_info->can_do(type);
 }
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+/*
+ * Tell if a PK can do the operations of the given PSA algorithm
+ */
+int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg,
+                          psa_key_usage_t usage)
+{
+    psa_key_usage_t key_usage;
+
+    /* A context with null pk_info is not set up yet and can't do anything.
+     * For backward compatibility, also accept NULL instead of a context
+     * pointer. */
+    if (ctx == NULL || ctx->pk_info == NULL) {
+        return 0;
+    }
+
+    /* Filter out non allowed algorithms */
+    if (PSA_ALG_IS_ECDSA(alg) == 0 &&
+        PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) == 0 &&
+        PSA_ALG_IS_RSA_PSS(alg) == 0 &&
+        alg != PSA_ALG_RSA_PKCS1V15_CRYPT &&
+        PSA_ALG_IS_ECDH(alg) == 0) {
+        return 0;
+    }
+
+    /* Filter out non allowed usage flags */
+    if (usage == 0 ||
+        (usage & ~(PSA_KEY_USAGE_SIGN_HASH |
+                   PSA_KEY_USAGE_DECRYPT |
+                   PSA_KEY_USAGE_DERIVE)) != 0) {
+        return 0;
+    }
+
+    /* Wildcard hash is not allowed */
+    if (PSA_ALG_IS_SIGN_HASH(alg) &&
+        PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH) {
+        return 0;
+    }
+
+    if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_OPAQUE) {
+        mbedtls_pk_type_t type;
+
+        if (PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_ECDH(alg)) {
+            type = MBEDTLS_PK_ECKEY;
+        } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||
+                   alg == PSA_ALG_RSA_PKCS1V15_CRYPT) {
+            type = MBEDTLS_PK_RSA;
+        } else if (PSA_ALG_IS_RSA_PSS(alg)) {
+            type = MBEDTLS_PK_RSASSA_PSS;
+        } else {
+            return 0;
+        }
+
+        if (ctx->pk_info->can_do(type) == 0) {
+            return 0;
+        }
+
+        switch (type) {
+            case MBEDTLS_PK_ECKEY:
+                key_usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_DERIVE;
+                break;
+            case MBEDTLS_PK_RSA:
+            case MBEDTLS_PK_RSASSA_PSS:
+                key_usage = PSA_KEY_USAGE_SIGN_HASH |
+                            PSA_KEY_USAGE_SIGN_MESSAGE |
+                            PSA_KEY_USAGE_DECRYPT;
+                break;
+            default:
+                /* Should never happen */
+                return 0;
+        }
+
+        return (key_usage & usage) == usage;
+    }
+
+    const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx->pk_ctx;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_algorithm_t key_alg, key_alg2;
+    psa_status_t status;
+
+    status = psa_get_key_attributes(*key, &attributes);
+    if (status != PSA_SUCCESS) {
+        return 0;
+    }
+
+    key_alg = psa_get_key_algorithm(&attributes);
+    key_alg2 = psa_get_key_enrollment_algorithm(&attributes);
+    key_usage = psa_get_key_usage_flags(&attributes);
+    psa_reset_key_attributes(&attributes);
+
+    if ((key_usage & usage) != usage) {
+        return 0;
+    }
+
+    /*
+     * Common case: the key alg or alg2 only allows alg.
+     * This will match PSA_ALG_RSA_PKCS1V15_CRYPT & PSA_ALG_IS_ECDH
+     * directly.
+     * This would also match ECDSA/RSA_PKCS1V15_SIGN/RSA_PSS with
+     * a fixed hash on key_alg/key_alg2.
+     */
+    if (alg == key_alg || alg == key_alg2) {
+        return 1;
+    }
+
+    /*
+     * If key_alg or key_alg2 is a hash-and-sign with a wildcard for the hash,
+     * and alg is the same hash-and-sign family with any hash,
+     * then alg is compliant with this key alg
+     */
+    if (PSA_ALG_IS_SIGN_HASH(alg)) {
+
+        if (PSA_ALG_IS_SIGN_HASH(key_alg) &&
+            PSA_ALG_SIGN_GET_HASH(key_alg) == PSA_ALG_ANY_HASH &&
+            (alg & ~PSA_ALG_HASH_MASK) == (key_alg & ~PSA_ALG_HASH_MASK)) {
+            return 1;
+        }
+
+        if (PSA_ALG_IS_SIGN_HASH(key_alg2) &&
+            PSA_ALG_SIGN_GET_HASH(key_alg2) == PSA_ALG_ANY_HASH &&
+            (alg & ~PSA_ALG_HASH_MASK) == (key_alg2 & ~PSA_ALG_HASH_MASK)) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
 /*
  * Helper for mbedtls_pk_sign and mbedtls_pk_verify
  */
-static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len )
+static inline int pk_hashlen_helper(mbedtls_md_type_t md_alg, size_t *hash_len)
 {
-    const mbedtls_md_info_t *md_info;
+    if (*hash_len != 0) {
+        return 0;
+    }
 
-    if( *hash_len != 0 && md_alg == MBEDTLS_MD_NONE )
-        return( 0 );
+    *hash_len = mbedtls_hash_info_get_size(md_alg);
 
-    if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
-        return( -1 );
+    if (*hash_len == 0) {
+        return -1;
+    }
 
-    if ( *hash_len != 0 && *hash_len != mbedtls_md_get_size( md_info ) )
-        return ( -1 );
-
-    *hash_len = mbedtls_md_get_size( md_info );
-    return( 0 );
+    return 0;
 }
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
 /*
  * Helper to set up a restart context if needed
  */
-static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx,
-                             const mbedtls_pk_info_t *info )
+static int pk_restart_setup(mbedtls_pk_restart_ctx *ctx,
+                            const mbedtls_pk_info_t *info)
 {
     /* Don't do anything if already set up or invalid */
-    if( ctx == NULL || ctx->pk_info != NULL )
-        return( 0 );
+    if (ctx == NULL || ctx->pk_info != NULL) {
+        return 0;
+    }
 
     /* Should never happen when we're called */
-    if( info->rs_alloc_func == NULL || info->rs_free_func == NULL )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+    if (info->rs_alloc_func == NULL || info->rs_free_func == NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
 
-    if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL )
-        return( MBEDTLS_ERR_PK_ALLOC_FAILED );
+    if ((ctx->rs_ctx = info->rs_alloc_func()) == NULL) {
+        return MBEDTLS_ERR_PK_ALLOC_FAILED;
+    }
 
     ctx->pk_info = info;
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
 
 /*
  * Verify a signature (restartable)
  */
-int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx,
-               mbedtls_md_type_t md_alg,
-               const unsigned char *hash, size_t hash_len,
-               const unsigned char *sig, size_t sig_len,
-               mbedtls_pk_restart_ctx *rs_ctx )
+int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx,
+                                  mbedtls_md_type_t md_alg,
+                                  const unsigned char *hash, size_t hash_len,
+                                  const unsigned char *sig, size_t sig_len,
+                                  mbedtls_pk_restart_ctx *rs_ctx)
 {
-    PK_VALIDATE_RET( ctx != NULL );
-    PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
-                     hash != NULL );
-    PK_VALIDATE_RET( sig != NULL );
+    if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
 
-    if( ctx->pk_info == NULL ||
-        pk_hashlen_helper( md_alg, &hash_len ) != 0 )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+    if (ctx->pk_info == NULL ||
+        pk_hashlen_helper(md_alg, &hash_len) != 0) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
     /* optimization: use non-restartable version if restart disabled */
-    if( rs_ctx != NULL &&
+    if (rs_ctx != NULL &&
         mbedtls_ecp_restart_is_enabled() &&
-        ctx->pk_info->verify_rs_func != NULL )
-    {
+        ctx->pk_info->verify_rs_func != NULL) {
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-        if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
-            return( ret );
+        if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) {
+            return ret;
+        }
 
-        ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx,
-                   md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx );
+        ret = ctx->pk_info->verify_rs_func(ctx->pk_ctx,
+                                           md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx);
 
-        if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
-            mbedtls_pk_restart_free( rs_ctx );
+        if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) {
+            mbedtls_pk_restart_free(rs_ctx);
+        }
 
-        return( ret );
+        return ret;
     }
 #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
     (void) rs_ctx;
 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
 
-    if( ctx->pk_info->verify_func == NULL )
-        return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
+    if (ctx->pk_info->verify_func == NULL) {
+        return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+    }
 
-    return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len,
-                                       sig, sig_len ) );
+    return ctx->pk_info->verify_func(ctx->pk_ctx, md_alg, hash, hash_len,
+                                     sig, sig_len);
 }
 
 /*
  * Verify a signature
  */
-int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
-               const unsigned char *hash, size_t hash_len,
-               const unsigned char *sig, size_t sig_len )
+int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
+                      const unsigned char *hash, size_t hash_len,
+                      const unsigned char *sig, size_t sig_len)
 {
-    return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len,
-                                           sig, sig_len, NULL ) );
+    return mbedtls_pk_verify_restartable(ctx, md_alg, hash, hash_len,
+                                         sig, sig_len, NULL);
 }
 
 /*
  * Verify a signature with options
  */
-int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
-                   mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
-                   const unsigned char *hash, size_t hash_len,
-                   const unsigned char *sig, size_t sig_len )
+int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options,
+                          mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
+                          const unsigned char *hash, size_t hash_len,
+                          const unsigned char *sig, size_t sig_len)
 {
-    PK_VALIDATE_RET( ctx != NULL );
-    PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
-                     hash != NULL );
-    PK_VALIDATE_RET( sig != NULL );
-
-    if( ctx->pk_info == NULL )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
-
-    if( ! mbedtls_pk_can_do( ctx, type ) )
-        return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
-
-    if( type == MBEDTLS_PK_RSASSA_PSS )
-    {
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        const mbedtls_pk_rsassa_pss_options *pss_opts;
-
-#if SIZE_MAX > UINT_MAX
-        if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )
-            return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
-#endif /* SIZE_MAX > UINT_MAX */
-
-        if( options == NULL )
-            return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
-
-        pss_opts = (const mbedtls_pk_rsassa_pss_options *) options;
-
-        if( sig_len < mbedtls_pk_get_len( ctx ) )
-            return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
-
-        ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ),
-                NULL, NULL, MBEDTLS_RSA_PUBLIC,
-                md_alg, (unsigned int) hash_len, hash,
-                pss_opts->mgf1_hash_id,
-                pss_opts->expected_salt_len,
-                sig );
-        if( ret != 0 )
-            return( ret );
-
-        if( sig_len > mbedtls_pk_get_len( ctx ) )
-            return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
-
-        return( 0 );
-#else
-        return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
-#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */
+    if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
 
-    /* General case: no options */
-    if( options != NULL )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+    if (ctx->pk_info == NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
 
-    return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) );
+    if (!mbedtls_pk_can_do(ctx, type)) {
+        return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+    }
+
+    if (type != MBEDTLS_PK_RSASSA_PSS) {
+        /* General case: no options */
+        if (options != NULL) {
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+        }
+
+        return mbedtls_pk_verify(ctx, md_alg, hash, hash_len, sig, sig_len);
+    }
+
+#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const mbedtls_pk_rsassa_pss_options *pss_opts;
+
+    if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    if (options == NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    pss_opts = (const mbedtls_pk_rsassa_pss_options *) options;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (pss_opts->mgf1_hash_id == md_alg) {
+        unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
+        unsigned char *p;
+        int key_len;
+        size_t signature_length;
+        psa_status_t status = PSA_ERROR_DATA_CORRUPT;
+        psa_status_t destruction_status = PSA_ERROR_DATA_CORRUPT;
+
+        psa_algorithm_t psa_md_alg = mbedtls_hash_info_psa_from_md(md_alg);
+        mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+        psa_algorithm_t psa_sig_alg = PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg);
+        p = buf + sizeof(buf);
+        key_len = mbedtls_pk_write_pubkey(&p, buf, ctx);
+
+        if (key_len < 0) {
+            return key_len;
+        }
+
+        psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);
+        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
+        psa_set_key_algorithm(&attributes, psa_sig_alg);
+
+        status = psa_import_key(&attributes,
+                                buf + sizeof(buf) - key_len, key_len,
+                                &key_id);
+        if (status != PSA_SUCCESS) {
+            psa_destroy_key(key_id);
+            return PSA_PK_TO_MBEDTLS_ERR(status);
+        }
+
+        /* This function requires returning MBEDTLS_ERR_PK_SIG_LEN_MISMATCH
+         * on a valid signature with trailing data in a buffer, but
+         * mbedtls_psa_rsa_verify_hash requires the sig_len to be exact,
+         * so for this reason the passed sig_len is overwritten. Smaller
+         * signature lengths should not be accepted for verification. */
+        signature_length = sig_len > mbedtls_pk_get_len(ctx) ?
+                           mbedtls_pk_get_len(ctx) : sig_len;
+        status = psa_verify_hash(key_id, psa_sig_alg, hash,
+                                 hash_len, sig, signature_length);
+        destruction_status = psa_destroy_key(key_id);
+
+        if (status == PSA_SUCCESS && sig_len > mbedtls_pk_get_len(ctx)) {
+            return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
+        }
+
+        if (status == PSA_SUCCESS) {
+            status = destruction_status;
+        }
+
+        return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
+    } else
+#endif
+    {
+        if (sig_len < mbedtls_pk_get_len(ctx)) {
+            return MBEDTLS_ERR_RSA_VERIFY_FAILED;
+        }
+
+        ret = mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_pk_rsa(*ctx),
+                                                md_alg, (unsigned int) hash_len, hash,
+                                                pss_opts->mgf1_hash_id,
+                                                pss_opts->expected_salt_len,
+                                                sig);
+        if (ret != 0) {
+            return ret;
+        }
+
+        if (sig_len > mbedtls_pk_get_len(ctx)) {
+            return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
+        }
+
+        return 0;
+    }
+#else
+    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */
 }
 
 /*
  * Make a signature (restartable)
  */
-int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx,
-             mbedtls_md_type_t md_alg,
-             const unsigned char *hash, size_t hash_len,
-             unsigned char *sig, size_t *sig_len,
-             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
-             mbedtls_pk_restart_ctx *rs_ctx )
+int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx,
+                                mbedtls_md_type_t md_alg,
+                                const unsigned char *hash, size_t hash_len,
+                                unsigned char *sig, size_t sig_size, size_t *sig_len,
+                                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                                mbedtls_pk_restart_ctx *rs_ctx)
 {
-    PK_VALIDATE_RET( ctx != NULL );
-    PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
-                     hash != NULL );
-    PK_VALIDATE_RET( sig != NULL );
+    if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
 
-    if( ctx->pk_info == NULL ||
-        pk_hashlen_helper( md_alg, &hash_len ) != 0 )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+    if (ctx->pk_info == NULL || pk_hashlen_helper(md_alg, &hash_len) != 0) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
     /* optimization: use non-restartable version if restart disabled */
-    if( rs_ctx != NULL &&
+    if (rs_ctx != NULL &&
         mbedtls_ecp_restart_is_enabled() &&
-        ctx->pk_info->sign_rs_func != NULL )
-    {
+        ctx->pk_info->sign_rs_func != NULL) {
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-        if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
-            return( ret );
+        if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) {
+            return ret;
+        }
 
-        ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg,
-                hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx->rs_ctx );
+        ret = ctx->pk_info->sign_rs_func(ctx->pk_ctx, md_alg,
+                                         hash, hash_len,
+                                         sig, sig_size, sig_len,
+                                         f_rng, p_rng, rs_ctx->rs_ctx);
 
-        if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
-            mbedtls_pk_restart_free( rs_ctx );
+        if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) {
+            mbedtls_pk_restart_free(rs_ctx);
+        }
 
-        return( ret );
+        return ret;
     }
 #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
     (void) rs_ctx;
 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
 
-    if( ctx->pk_info->sign_func == NULL )
-        return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
+    if (ctx->pk_info->sign_func == NULL) {
+        return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+    }
 
-    return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len,
-                                     sig, sig_len, f_rng, p_rng ) );
+    return ctx->pk_info->sign_func(ctx->pk_ctx, md_alg,
+                                   hash, hash_len,
+                                   sig, sig_size, sig_len,
+                                   f_rng, p_rng);
 }
 
 /*
  * Make a signature
  */
-int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
-             const unsigned char *hash, size_t hash_len,
-             unsigned char *sig, size_t *sig_len,
-             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
+                    const unsigned char *hash, size_t hash_len,
+                    unsigned char *sig, size_t sig_size, size_t *sig_len,
+                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
-    return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len,
-                                         sig, sig_len, f_rng, p_rng, NULL ) );
+    return mbedtls_pk_sign_restartable(ctx, md_alg, hash, hash_len,
+                                       sig, sig_size, sig_len,
+                                       f_rng, p_rng, NULL);
 }
 
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+/*
+ * Make a signature given a signature type.
+ */
+int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type,
+                        mbedtls_pk_context *ctx,
+                        mbedtls_md_type_t md_alg,
+                        const unsigned char *hash, size_t hash_len,
+                        unsigned char *sig, size_t sig_size, size_t *sig_len,
+                        int (*f_rng)(void *, unsigned char *, size_t),
+                        void *p_rng)
+{
+#if defined(MBEDTLS_RSA_C)
+    psa_algorithm_t psa_md_alg;
+#endif /* MBEDTLS_RSA_C */
+    *sig_len = 0;
+
+    if (ctx->pk_info == NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    if (!mbedtls_pk_can_do(ctx, pk_type)) {
+        return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+    }
+
+    if (pk_type != MBEDTLS_PK_RSASSA_PSS) {
+        return mbedtls_pk_sign(ctx, md_alg, hash, hash_len,
+                               sig, sig_size, sig_len, f_rng, p_rng);
+    }
+
+#if defined(MBEDTLS_RSA_C)
+    psa_md_alg = mbedtls_hash_info_psa_from_md(md_alg);
+    if (psa_md_alg == 0) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) {
+        const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx->pk_ctx;
+        psa_status_t status;
+
+        status = psa_sign_hash(*key, PSA_ALG_RSA_PSS(psa_md_alg),
+                               hash, hash_len,
+                               sig, sig_size, sig_len);
+        return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
+    }
+
+    return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PSS(psa_md_alg),
+                                       ctx->pk_ctx, hash, hash_len,
+                                       sig, sig_size, sig_len);
+#else /* MBEDTLS_RSA_C */
+    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+#endif /* !MBEDTLS_RSA_C */
+
+}
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
 /*
  * Decrypt message
  */
-int mbedtls_pk_decrypt( mbedtls_pk_context *ctx,
-                const unsigned char *input, size_t ilen,
-                unsigned char *output, size_t *olen, size_t osize,
-                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+int mbedtls_pk_decrypt(mbedtls_pk_context *ctx,
+                       const unsigned char *input, size_t ilen,
+                       unsigned char *output, size_t *olen, size_t osize,
+                       int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
-    PK_VALIDATE_RET( ctx != NULL );
-    PK_VALIDATE_RET( input != NULL || ilen == 0 );
-    PK_VALIDATE_RET( output != NULL || osize == 0 );
-    PK_VALIDATE_RET( olen != NULL );
+    if (ctx->pk_info == NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
 
-    if( ctx->pk_info == NULL )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+    if (ctx->pk_info->decrypt_func == NULL) {
+        return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+    }
 
-    if( ctx->pk_info->decrypt_func == NULL )
-        return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
-
-    return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen,
-                output, olen, osize, f_rng, p_rng ) );
+    return ctx->pk_info->decrypt_func(ctx->pk_ctx, input, ilen,
+                                      output, olen, osize, f_rng, p_rng);
 }
 
 /*
  * Encrypt message
  */
-int mbedtls_pk_encrypt( mbedtls_pk_context *ctx,
-                const unsigned char *input, size_t ilen,
-                unsigned char *output, size_t *olen, size_t osize,
-                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+int mbedtls_pk_encrypt(mbedtls_pk_context *ctx,
+                       const unsigned char *input, size_t ilen,
+                       unsigned char *output, size_t *olen, size_t osize,
+                       int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
-    PK_VALIDATE_RET( ctx != NULL );
-    PK_VALIDATE_RET( input != NULL || ilen == 0 );
-    PK_VALIDATE_RET( output != NULL || osize == 0 );
-    PK_VALIDATE_RET( olen != NULL );
+    if (ctx->pk_info == NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
 
-    if( ctx->pk_info == NULL )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+    if (ctx->pk_info->encrypt_func == NULL) {
+        return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+    }
 
-    if( ctx->pk_info->encrypt_func == NULL )
-        return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
-
-    return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen,
-                output, olen, osize, f_rng, p_rng ) );
+    return ctx->pk_info->encrypt_func(ctx->pk_ctx, input, ilen,
+                                      output, olen, osize, f_rng, p_rng);
 }
 
 /*
  * Check public-private key pair
  */
-int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv )
+int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
+                          const mbedtls_pk_context *prv,
+                          int (*f_rng)(void *, unsigned char *, size_t),
+                          void *p_rng)
 {
-    PK_VALIDATE_RET( pub != NULL );
-    PK_VALIDATE_RET( prv != NULL );
-
-    if( pub->pk_info == NULL ||
-        prv->pk_info == NULL )
-    {
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+    if (pub->pk_info == NULL ||
+        prv->pk_info == NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
 
-    if( prv->pk_info->check_pair_func == NULL )
-        return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
-
-    if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT )
-    {
-        if( pub->pk_info->type != MBEDTLS_PK_RSA )
-            return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
-    }
-    else
-    {
-        if( pub->pk_info != prv->pk_info )
-            return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
+    if (f_rng == NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
 
-    return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) );
+    if (prv->pk_info->check_pair_func == NULL) {
+        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+    }
+
+    if (prv->pk_info->type == MBEDTLS_PK_RSA_ALT) {
+        if (pub->pk_info->type != MBEDTLS_PK_RSA) {
+            return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+        }
+    } else {
+        if (pub->pk_info != prv->pk_info) {
+            return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+        }
+    }
+
+    return prv->pk_info->check_pair_func(pub->pk_ctx, prv->pk_ctx, f_rng, p_rng);
 }
 
 /*
  * Get key size in bits
  */
-size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx )
+size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx)
 {
     /* For backward compatibility, accept NULL or a context that
      * isn't set up yet, and return a fake value that should be safe. */
-    if( ctx == NULL || ctx->pk_info == NULL )
-        return( 0 );
+    if (ctx == NULL || ctx->pk_info == NULL) {
+        return 0;
+    }
 
-    return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) );
+    return ctx->pk_info->get_bitlen(ctx->pk_ctx);
 }
 
 /*
  * Export debug information
  */
-int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items )
+int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items)
 {
-    PK_VALIDATE_RET( ctx != NULL );
-    if( ctx->pk_info == NULL )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+    if (ctx->pk_info == NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
 
-    if( ctx->pk_info->debug_func == NULL )
-        return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
+    if (ctx->pk_info->debug_func == NULL) {
+        return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+    }
 
-    ctx->pk_info->debug_func( ctx->pk_ctx, items );
-    return( 0 );
+    ctx->pk_info->debug_func(ctx->pk_ctx, items);
+    return 0;
 }
 
 /*
  * Access the PK type name
  */
-const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx )
+const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx)
 {
-    if( ctx == NULL || ctx->pk_info == NULL )
-        return( "invalid PK" );
+    if (ctx == NULL || ctx->pk_info == NULL) {
+        return "invalid PK";
+    }
 
-    return( ctx->pk_info->name );
+    return ctx->pk_info->name;
 }
 
 /*
  * Access the PK type
  */
-mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx )
+mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx)
 {
-    if( ctx == NULL || ctx->pk_info == NULL )
-        return( MBEDTLS_PK_NONE );
+    if (ctx == NULL || ctx->pk_info == NULL) {
+        return MBEDTLS_PK_NONE;
+    }
 
-    return( ctx->pk_info->type );
+    return ctx->pk_info->type;
 }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
@@ -588,55 +854,107 @@
  * Load the key to a PSA key slot,
  * then turn the PK context into a wrapper for that key slot.
  *
- * Currently only works for EC private keys.
+ * Currently only works for EC & RSA private keys.
  */
-int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk,
-                               psa_key_id_t *key,
-                               psa_algorithm_t hash_alg )
+int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk,
+                              mbedtls_svc_key_id_t *key,
+                              psa_algorithm_t alg,
+                              psa_key_usage_t usage,
+                              psa_algorithm_t alg2)
 {
-#if !defined(MBEDTLS_ECP_C)
+#if !defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_RSA_C)
     ((void) pk);
     ((void) key);
-    ((void) hash_alg);
-    return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
+    ((void) alg);
+    ((void) usage);
+    ((void) alg2);
 #else
-    const mbedtls_ecp_keypair *ec;
-    unsigned char d[MBEDTLS_ECP_MAX_BYTES];
-    size_t d_len;
-    psa_ecc_family_t curve_id;
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_type_t key_type;
-    size_t bits;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+#if defined(MBEDTLS_ECP_C)
+    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECKEY) {
+        const mbedtls_ecp_keypair *ec;
+        unsigned char d[MBEDTLS_ECP_MAX_BYTES];
+        size_t d_len;
+        psa_ecc_family_t curve_id;
+        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+        psa_key_type_t key_type;
+        size_t bits;
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        psa_status_t status;
 
-    /* export the private key material in the format PSA wants */
-    if( mbedtls_pk_get_type( pk ) != MBEDTLS_PK_ECKEY )
-        return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
+        /* export the private key material in the format PSA wants */
+        ec = mbedtls_pk_ec(*pk);
+        d_len = PSA_BITS_TO_BYTES(ec->grp.nbits);
+        if ((ret = mbedtls_mpi_write_binary(&ec->d, d, d_len)) != 0) {
+            return ret;
+        }
 
-    ec = mbedtls_pk_ec( *pk );
-    d_len = ( ec->grp.nbits + 7 ) / 8;
-    if( ( ret = mbedtls_mpi_write_binary( &ec->d, d, d_len ) ) != 0 )
-        return( ret );
+        curve_id = mbedtls_ecc_group_to_psa(ec->grp.id, &bits);
+        key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(curve_id);
 
-    curve_id = mbedtls_ecc_group_to_psa( ec->grp.id, &bits );
-    key_type = PSA_KEY_TYPE_ECC_KEY_PAIR( curve_id );
+        /* prepare the key attributes */
+        psa_set_key_type(&attributes, key_type);
+        psa_set_key_bits(&attributes, bits);
+        psa_set_key_usage_flags(&attributes, usage);
+        psa_set_key_algorithm(&attributes, alg);
+        if (alg2 != PSA_ALG_NONE) {
+            psa_set_key_enrollment_algorithm(&attributes, alg2);
+        }
 
-    /* prepare the key attributes */
-    psa_set_key_type( &attributes, key_type );
-    psa_set_key_bits( &attributes, bits );
-    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH );
-    psa_set_key_algorithm( &attributes, PSA_ALG_ECDSA(hash_alg) );
+        /* import private key into PSA */
+        status = psa_import_key(&attributes, d, d_len, key);
+        if (status != PSA_SUCCESS) {
+            return PSA_PK_TO_MBEDTLS_ERR(status);
+        }
 
-    /* import private key into PSA */
-    if( PSA_SUCCESS != psa_import_key( &attributes, d, d_len, key ) )
-        return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
+        /* make PK context wrap the key slot */
+        mbedtls_pk_free(pk);
+        mbedtls_pk_init(pk);
 
-    /* make PK context wrap the key slot */
-    mbedtls_pk_free( pk );
-    mbedtls_pk_init( pk );
-
-    return( mbedtls_pk_setup_opaque( pk, *key ) );
+        return mbedtls_pk_setup_opaque(pk, *key);
+    } else
 #endif /* MBEDTLS_ECP_C */
+#if defined(MBEDTLS_RSA_C)
+    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA) {
+        unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES];
+        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+        int key_len;
+        psa_status_t status;
+
+        /* export the private key material in the format PSA wants */
+        key_len = mbedtls_pk_write_key_der(pk, buf, sizeof(buf));
+        if (key_len <= 0) {
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+        }
+
+        /* prepare the key attributes */
+        psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
+        psa_set_key_bits(&attributes, mbedtls_pk_get_bitlen(pk));
+        psa_set_key_usage_flags(&attributes, usage);
+        psa_set_key_algorithm(&attributes, alg);
+        if (alg2 != PSA_ALG_NONE) {
+            psa_set_key_enrollment_algorithm(&attributes, alg2);
+        }
+
+        /* import private key into PSA */
+        status = psa_import_key(&attributes,
+                                buf + sizeof(buf) - key_len,
+                                key_len, key);
+
+        mbedtls_platform_zeroize(buf, sizeof(buf));
+
+        if (status != PSA_SUCCESS) {
+            return PSA_PK_TO_MBEDTLS_ERR(status);
+        }
+
+        /* make PK context wrap the key slot */
+        mbedtls_pk_free(pk);
+        mbedtls_pk_init(pk);
+
+        return mbedtls_pk_setup_opaque(pk, *key);
+    } else
+#endif /* MBEDTLS_RSA_C */
+#endif /* !MBEDTLS_ECP_C && !MBEDTLS_RSA_C */
+    return MBEDTLS_ERR_PK_TYPE_MISMATCH;
 }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 #endif /* MBEDTLS_PK_C */
diff --git a/lib/libmbedtls/mbedtls/library/pk_wrap.c b/lib/libmbedtls/mbedtls/library/pk_wrap.c
index 107e912..4d91f22 100644
--- a/lib/libmbedtls/mbedtls/library/pk_wrap.c
+++ b/lib/libmbedtls/mbedtls/library/pk_wrap.c
@@ -19,15 +19,15 @@
 
 #include "common.h"
 
+#include "mbedtls/platform_util.h"
+
 #if defined(MBEDTLS_PK_C)
-#include "mbedtls/pk_internal.h"
+#include "pk_wrap.h"
 #include "mbedtls/error.h"
 
 /* Even if RSA not activated, for the sake of RSA-alt */
 #include "mbedtls/rsa.h"
 
-#include <string.h>
-
 #if defined(MBEDTLS_ECP_C)
 #include "mbedtls/ecp.h"
 #endif
@@ -36,156 +36,582 @@
 #include "mbedtls/ecdsa.h"
 #endif
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-#include "mbedtls/asn1write.h"
+#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PSA_CRYPTO_C)
+#include "pkwrite.h"
 #endif
 
-#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
-#include "mbedtls/platform_util.h"
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+#include "mbedtls/psa_util.h"
+#define PSA_PK_TO_MBEDTLS_ERR(status) psa_pk_status_to_mbedtls(status)
+#define PSA_PK_RSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,     \
+                                                                  psa_to_pk_rsa_errors,            \
+                                                                  psa_pk_status_to_mbedtls)
+#define PSA_PK_ECDSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                                    psa_to_pk_ecdsa_errors,        \
+                                                                    psa_pk_status_to_mbedtls)
 #endif
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 #include "psa/crypto.h"
-#include "mbedtls/psa_util.h"
+#include "hash_info.h"
+
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
+#include "mbedtls/asn1write.h"
 #include "mbedtls/asn1.h"
 #endif
+#endif  /* MBEDTLS_USE_PSA_CRYPTO */
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free       free
-#endif
 
 #include <limits.h>
 #include <stdint.h>
+#include <string.h>
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+int mbedtls_pk_error_from_psa(psa_status_t status)
+{
+    switch (status) {
+        case PSA_SUCCESS:
+            return 0;
+        case PSA_ERROR_INVALID_HANDLE:
+            return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
+        case PSA_ERROR_NOT_PERMITTED:
+            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
+        case PSA_ERROR_BUFFER_TOO_SMALL:
+            return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
+        case PSA_ERROR_NOT_SUPPORTED:
+            return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+        case PSA_ERROR_INVALID_ARGUMENT:
+            return MBEDTLS_ERR_PK_INVALID_ALG;
+        case PSA_ERROR_INSUFFICIENT_MEMORY:
+            return MBEDTLS_ERR_PK_ALLOC_FAILED;
+        case PSA_ERROR_BAD_STATE:
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+        case PSA_ERROR_COMMUNICATION_FAILURE:
+        case PSA_ERROR_HARDWARE_FAILURE:
+            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+        case PSA_ERROR_DATA_CORRUPT:
+        case PSA_ERROR_DATA_INVALID:
+        case PSA_ERROR_STORAGE_FAILURE:
+            return MBEDTLS_ERR_PK_FILE_IO_ERROR;
+        case PSA_ERROR_CORRUPTION_DETECTED:
+            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        default:
+            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
+    }
+}
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ||    \
+    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
+int mbedtls_pk_error_from_psa_rsa(psa_status_t status)
+{
+    switch (status) {
+        case PSA_ERROR_NOT_PERMITTED:
+        case PSA_ERROR_INVALID_ARGUMENT:
+        case PSA_ERROR_INVALID_HANDLE:
+            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+        case PSA_ERROR_BUFFER_TOO_SMALL:
+            return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
+        case PSA_ERROR_INSUFFICIENT_ENTROPY:
+            return MBEDTLS_ERR_RSA_RNG_FAILED;
+        case PSA_ERROR_INVALID_SIGNATURE:
+            return MBEDTLS_ERR_RSA_VERIFY_FAILED;
+        case PSA_ERROR_INVALID_PADDING:
+            return MBEDTLS_ERR_RSA_INVALID_PADDING;
+        case PSA_SUCCESS:
+            return 0;
+        case PSA_ERROR_NOT_SUPPORTED:
+            return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+        case PSA_ERROR_INSUFFICIENT_MEMORY:
+            return MBEDTLS_ERR_PK_ALLOC_FAILED;
+        case PSA_ERROR_BAD_STATE:
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+        case PSA_ERROR_COMMUNICATION_FAILURE:
+        case PSA_ERROR_HARDWARE_FAILURE:
+            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+        case PSA_ERROR_DATA_CORRUPT:
+        case PSA_ERROR_DATA_INVALID:
+        case PSA_ERROR_STORAGE_FAILURE:
+            return MBEDTLS_ERR_PK_FILE_IO_ERROR;
+        case PSA_ERROR_CORRUPTION_DETECTED:
+            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        default:
+            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
+    }
+}
+#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
+int mbedtls_pk_error_from_psa_ecdsa(psa_status_t status)
+{
+    switch (status) {
+        case PSA_ERROR_NOT_PERMITTED:
+        case PSA_ERROR_INVALID_ARGUMENT:
+            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+        case PSA_ERROR_INVALID_HANDLE:
+            return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+        case PSA_ERROR_BUFFER_TOO_SMALL:
+            return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+        case PSA_ERROR_INSUFFICIENT_ENTROPY:
+            return MBEDTLS_ERR_ECP_RANDOM_FAILED;
+        case PSA_ERROR_INVALID_SIGNATURE:
+            return MBEDTLS_ERR_ECP_VERIFY_FAILED;
+        case PSA_SUCCESS:
+            return 0;
+        case PSA_ERROR_NOT_SUPPORTED:
+            return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+        case PSA_ERROR_INSUFFICIENT_MEMORY:
+            return MBEDTLS_ERR_PK_ALLOC_FAILED;
+        case PSA_ERROR_BAD_STATE:
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+        case PSA_ERROR_COMMUNICATION_FAILURE:
+        case PSA_ERROR_HARDWARE_FAILURE:
+            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+        case PSA_ERROR_DATA_CORRUPT:
+        case PSA_ERROR_DATA_INVALID:
+        case PSA_ERROR_STORAGE_FAILURE:
+            return MBEDTLS_ERR_PK_FILE_IO_ERROR;
+        case PSA_ERROR_CORRUPTION_DETECTED:
+            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        default:
+            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
+    }
+}
+#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
 
 #if defined(MBEDTLS_RSA_C)
-static int rsa_can_do( mbedtls_pk_type_t type )
+static int rsa_can_do(mbedtls_pk_type_t type)
 {
-    return( type == MBEDTLS_PK_RSA ||
-            type == MBEDTLS_PK_RSASSA_PSS );
+    return type == MBEDTLS_PK_RSA ||
+           type == MBEDTLS_PK_RSASSA_PSS;
 }
 
-static size_t rsa_get_bitlen( const void *ctx )
+static size_t rsa_get_bitlen(const void *ctx)
 {
-    const mbedtls_rsa_context * rsa = (const mbedtls_rsa_context *) ctx;
-    return( 8 * mbedtls_rsa_get_len( rsa ) );
+    const mbedtls_rsa_context *rsa = (const mbedtls_rsa_context *) ctx;
+    return 8 * mbedtls_rsa_get_len(rsa);
 }
 
-static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
-                   const unsigned char *hash, size_t hash_len,
-                   const unsigned char *sig, size_t sig_len )
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+static int rsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg,
+                           const unsigned char *hash, size_t hash_len,
+                           const unsigned char *sig, size_t sig_len)
+{
+    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_status_t status;
+    mbedtls_pk_context key;
+    int key_len;
+    unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
+    psa_algorithm_t psa_alg_md =
+        PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_hash_info_psa_from_md(md_alg));
+    size_t rsa_len = mbedtls_rsa_get_len(rsa);
+
+    if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    if (sig_len < rsa_len) {
+        return MBEDTLS_ERR_RSA_VERIFY_FAILED;
+    }
+
+    /* mbedtls_pk_write_pubkey_der() expects a full PK context;
+     * re-construct one to make it happy */
+    key.pk_info = &mbedtls_rsa_info;
+    key.pk_ctx = ctx;
+    key_len = mbedtls_pk_write_pubkey_der(&key, buf, sizeof(buf));
+    if (key_len <= 0) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
+    psa_set_key_algorithm(&attributes, psa_alg_md);
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);
+
+    status = psa_import_key(&attributes,
+                            buf + sizeof(buf) - key_len, key_len,
+                            &key_id);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
+        goto cleanup;
+    }
+
+    status = psa_verify_hash(key_id, psa_alg_md, hash, hash_len,
+                             sig, sig_len);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status);
+        goto cleanup;
+    }
+    ret = 0;
+
+cleanup:
+    status = psa_destroy_key(key_id);
+    if (ret == 0 && status != PSA_SUCCESS) {
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
+    }
+
+    return ret;
+}
+#else
+static int rsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg,
+                           const unsigned char *hash, size_t hash_len,
+                           const unsigned char *sig, size_t sig_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
-    size_t rsa_len = mbedtls_rsa_get_len( rsa );
+    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
+    size_t rsa_len = mbedtls_rsa_get_len(rsa);
 
-#if SIZE_MAX > UINT_MAX
-    if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
-#endif /* SIZE_MAX > UINT_MAX */
+    if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
 
-    if( sig_len < rsa_len )
-        return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
+    if (sig_len < rsa_len) {
+        return MBEDTLS_ERR_RSA_VERIFY_FAILED;
+    }
 
-    if( ( ret = mbedtls_rsa_pkcs1_verify( rsa, NULL, NULL,
-                                  MBEDTLS_RSA_PUBLIC, md_alg,
-                                  (unsigned int) hash_len, hash, sig ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_rsa_pkcs1_verify(rsa, md_alg,
+                                        (unsigned int) hash_len,
+                                        hash, sig)) != 0) {
+        return ret;
+    }
 
     /* The buffer contains a valid signature followed by extra data.
      * We have a special error code for that so that so that callers can
      * use mbedtls_pk_verify() to check "Does the buffer start with a
      * valid signature?" and not just "Does the buffer contain a valid
      * signature?". */
-    if( sig_len > rsa_len )
-        return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
+    if (sig_len > rsa_len) {
+        return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
+    }
 
-    return( 0 );
+    return 0;
+}
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+int  mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t alg,
+                                 mbedtls_rsa_context *rsa_ctx,
+                                 const unsigned char *hash, size_t hash_len,
+                                 unsigned char *sig, size_t sig_size,
+                                 size_t *sig_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_status_t status;
+    mbedtls_pk_context key;
+    int key_len;
+    unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES];
+    mbedtls_pk_info_t pk_info = mbedtls_rsa_info;
+
+    *sig_len = mbedtls_rsa_get_len(rsa_ctx);
+    if (sig_size < *sig_len) {
+        return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
+    }
+
+    /* mbedtls_pk_write_key_der() expects a full PK context;
+     * re-construct one to make it happy */
+    key.pk_info = &pk_info;
+    key.pk_ctx = rsa_ctx;
+    key_len = mbedtls_pk_write_key_der(&key, buf, sizeof(buf));
+    if (key_len <= 0) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
+
+    status = psa_import_key(&attributes,
+                            buf + sizeof(buf) - key_len, key_len,
+                            &key_id);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
+        goto cleanup;
+    }
+    status = psa_sign_hash(key_id, alg, hash, hash_len,
+                           sig, sig_size, sig_len);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    status = psa_destroy_key(key_id);
+    if (ret == 0 && status != PSA_SUCCESS) {
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
+    }
+    return ret;
+}
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+static int rsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
+                         const unsigned char *hash, size_t hash_len,
+                         unsigned char *sig, size_t sig_size, size_t *sig_len,
+                         int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+    ((void) f_rng);
+    ((void) p_rng);
+
+    psa_algorithm_t psa_md_alg;
+    psa_md_alg = mbedtls_hash_info_psa_from_md(md_alg);
+    if (psa_md_alg == 0) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PKCS1V15_SIGN(
+                                           psa_md_alg),
+                                       ctx, hash, hash_len,
+                                       sig, sig_size, sig_len);
+}
+#else
+static int rsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
+                         const unsigned char *hash, size_t hash_len,
+                         unsigned char *sig, size_t sig_size, size_t *sig_len,
+                         int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
+
+    if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    *sig_len = mbedtls_rsa_get_len(rsa);
+    if (sig_size < *sig_len) {
+        return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
+    }
+
+    return mbedtls_rsa_pkcs1_sign(rsa, f_rng, p_rng,
+                                  md_alg, (unsigned int) hash_len,
+                                  hash, sig);
+}
+#endif
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+static int rsa_decrypt_wrap(void *ctx,
+                            const unsigned char *input, size_t ilen,
+                            unsigned char *output, size_t *olen, size_t osize,
+                            int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_status_t status;
+    mbedtls_pk_context key;
+    int key_len;
+    unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES];
+
+    ((void) f_rng);
+    ((void) p_rng);
+
+#if !defined(MBEDTLS_RSA_ALT)
+    if (rsa->padding != MBEDTLS_RSA_PKCS_V15) {
+        return MBEDTLS_ERR_RSA_INVALID_PADDING;
+    }
+#endif /* !MBEDTLS_RSA_ALT */
+
+    if (ilen != mbedtls_rsa_get_len(rsa)) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
+
+    /* mbedtls_pk_write_key_der() expects a full PK context;
+     * re-construct one to make it happy */
+    key.pk_info = &mbedtls_rsa_info;
+    key.pk_ctx = ctx;
+    key_len = mbedtls_pk_write_key_der(&key, buf, sizeof(buf));
+    if (key_len <= 0) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
+    psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
+
+    status = psa_import_key(&attributes,
+                            buf + sizeof(buf) - key_len, key_len,
+                            &key_id);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
+        goto cleanup;
+    }
+
+    status = psa_asymmetric_decrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
+                                    input, ilen,
+                                    NULL, 0,
+                                    output, osize, olen);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    mbedtls_platform_zeroize(buf, sizeof(buf));
+    status = psa_destroy_key(key_id);
+    if (ret == 0 && status != PSA_SUCCESS) {
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
+    }
+
+    return ret;
+}
+#else
+static int rsa_decrypt_wrap(void *ctx,
+                            const unsigned char *input, size_t ilen,
+                            unsigned char *output, size_t *olen, size_t osize,
+                            int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
+
+    if (ilen != mbedtls_rsa_get_len(rsa)) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
+
+    return mbedtls_rsa_pkcs1_decrypt(rsa, f_rng, p_rng,
+                                     olen, input, output, osize);
+}
+#endif
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+static int rsa_encrypt_wrap(void *ctx,
+                            const unsigned char *input, size_t ilen,
+                            unsigned char *output, size_t *olen, size_t osize,
+                            int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_status_t status;
+    mbedtls_pk_context key;
+    int key_len;
+    unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
+
+    ((void) f_rng);
+    ((void) p_rng);
+
+#if !defined(MBEDTLS_RSA_ALT)
+    if (rsa->padding != MBEDTLS_RSA_PKCS_V15) {
+        return MBEDTLS_ERR_RSA_INVALID_PADDING;
+    }
+#endif
+
+    if (mbedtls_rsa_get_len(rsa) > osize) {
+        return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
+    }
+
+    /* mbedtls_pk_write_pubkey_der() expects a full PK context;
+     * re-construct one to make it happy */
+    key.pk_info = &mbedtls_rsa_info;
+    key.pk_ctx = ctx;
+    key_len = mbedtls_pk_write_pubkey_der(&key, buf, sizeof(buf));
+    if (key_len <= 0) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
+    psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);
+
+    status = psa_import_key(&attributes,
+                            buf + sizeof(buf) - key_len, key_len,
+                            &key_id);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
+        goto cleanup;
+    }
+
+    status = psa_asymmetric_encrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
+                                    input, ilen,
+                                    NULL, 0,
+                                    output, osize, olen);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    status = psa_destroy_key(key_id);
+    if (ret == 0 && status != PSA_SUCCESS) {
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
+    }
+
+    return ret;
+}
+#else
+static int rsa_encrypt_wrap(void *ctx,
+                            const unsigned char *input, size_t ilen,
+                            unsigned char *output, size_t *olen, size_t osize,
+                            int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
+    *olen = mbedtls_rsa_get_len(rsa);
+
+    if (*olen > osize) {
+        return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
+    }
+
+    return mbedtls_rsa_pkcs1_encrypt(rsa, f_rng, p_rng,
+                                     ilen, input, output);
+}
+#endif
+
+static int rsa_check_pair_wrap(const void *pub, const void *prv,
+                               int (*f_rng)(void *, unsigned char *, size_t),
+                               void *p_rng)
+{
+    (void) f_rng;
+    (void) p_rng;
+    return mbedtls_rsa_check_pub_priv((const mbedtls_rsa_context *) pub,
+                                      (const mbedtls_rsa_context *) prv);
 }
 
-static int rsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
-                   const unsigned char *hash, size_t hash_len,
-                   unsigned char *sig, size_t *sig_len,
-                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+static void *rsa_alloc_wrap(void)
 {
-    mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
+    void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_context));
 
-#if SIZE_MAX > UINT_MAX
-    if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
-#endif /* SIZE_MAX > UINT_MAX */
+    if (ctx != NULL) {
+        mbedtls_rsa_init((mbedtls_rsa_context *) ctx);
+    }
 
-    *sig_len = mbedtls_rsa_get_len( rsa );
-
-    return( mbedtls_rsa_pkcs1_sign( rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE,
-                md_alg, (unsigned int) hash_len, hash, sig ) );
+    return ctx;
 }
 
-static int rsa_decrypt_wrap( void *ctx,
-                    const unsigned char *input, size_t ilen,
-                    unsigned char *output, size_t *olen, size_t osize,
-                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+static void rsa_free_wrap(void *ctx)
 {
-    mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
-
-    if( ilen != mbedtls_rsa_get_len( rsa ) )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
-    return( mbedtls_rsa_pkcs1_decrypt( rsa, f_rng, p_rng,
-                MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) );
+    mbedtls_rsa_free((mbedtls_rsa_context *) ctx);
+    mbedtls_free(ctx);
 }
 
-static int rsa_encrypt_wrap( void *ctx,
-                    const unsigned char *input, size_t ilen,
-                    unsigned char *output, size_t *olen, size_t osize,
-                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+static void rsa_debug(const void *ctx, mbedtls_pk_debug_item *items)
 {
-    mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
-    *olen = mbedtls_rsa_get_len( rsa );
-
-    if( *olen > osize )
-        return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE );
-
-    return( mbedtls_rsa_pkcs1_encrypt( rsa, f_rng, p_rng, MBEDTLS_RSA_PUBLIC,
-                                       ilen, input, output ) );
-}
-
-static int rsa_check_pair_wrap( const void *pub, const void *prv )
-{
-    return( mbedtls_rsa_check_pub_priv( (const mbedtls_rsa_context *) pub,
-                                (const mbedtls_rsa_context *) prv ) );
-}
-
-static void *rsa_alloc_wrap( void )
-{
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_context ) );
-
-    if( ctx != NULL )
-        mbedtls_rsa_init( (mbedtls_rsa_context *) ctx, 0, 0 );
-
-    return( ctx );
-}
-
-static void rsa_free_wrap( void *ctx )
-{
-    mbedtls_rsa_free( (mbedtls_rsa_context *) ctx );
-    mbedtls_free( ctx );
-}
-
-static void rsa_debug( const void *ctx, mbedtls_pk_debug_item *items )
-{
+#if defined(MBEDTLS_RSA_ALT)
+    /* Not supported */
+    (void) ctx;
+    (void) items;
+#else
     items->type = MBEDTLS_PK_DEBUG_MPI;
     items->name = "rsa.N";
-    items->value = &( ((mbedtls_rsa_context *) ctx)->N );
+    items->value = &(((mbedtls_rsa_context *) ctx)->N);
 
     items++;
 
     items->type = MBEDTLS_PK_DEBUG_MPI;
     items->name = "rsa.E";
-    items->value = &( ((mbedtls_rsa_context *) ctx)->E );
+    items->value = &(((mbedtls_rsa_context *) ctx)->E);
+#endif
 }
 
 const mbedtls_pk_info_t mbedtls_rsa_info = {
@@ -216,77 +642,363 @@
 /*
  * Generic EC key
  */
-static int eckey_can_do( mbedtls_pk_type_t type )
+static int eckey_can_do(mbedtls_pk_type_t type)
 {
-    return( type == MBEDTLS_PK_ECKEY ||
-            type == MBEDTLS_PK_ECKEY_DH ||
-            type == MBEDTLS_PK_ECDSA );
+    return type == MBEDTLS_PK_ECKEY ||
+           type == MBEDTLS_PK_ECKEY_DH ||
+           type == MBEDTLS_PK_ECDSA;
 }
 
-static size_t eckey_get_bitlen( const void *ctx )
+static size_t eckey_get_bitlen(const void *ctx)
 {
-    return( ((mbedtls_ecp_keypair *) ctx)->grp.pbits );
+    return ((mbedtls_ecp_keypair *) ctx)->grp.pbits;
 }
 
-#if defined(MBEDTLS_ECDSA_C)
-/* Forward declarations */
-static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
-                       const unsigned char *hash, size_t hash_len,
-                       const unsigned char *sig, size_t sig_len );
-
-static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
-                   const unsigned char *hash, size_t hash_len,
-                   unsigned char *sig, size_t *sig_len,
-                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
-
-static int eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
-                       const unsigned char *hash, size_t hash_len,
-                       const unsigned char *sig, size_t sig_len )
+#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+/*
+ * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of
+ * those integers and convert it to the fixed-length encoding expected by PSA.
+ */
+static int extract_ecdsa_sig_int(unsigned char **from, const unsigned char *end,
+                                 unsigned char *to, size_t to_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_ecdsa_context ecdsa;
+    size_t unpadded_len, padding_len;
 
-    mbedtls_ecdsa_init( &ecdsa );
+    if ((ret = mbedtls_asn1_get_tag(from, end, &unpadded_len,
+                                    MBEDTLS_ASN1_INTEGER)) != 0) {
+        return ret;
+    }
 
-    if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 )
-        ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len );
+    while (unpadded_len > 0 && **from == 0x00) {
+        (*from)++;
+        unpadded_len--;
+    }
 
-    mbedtls_ecdsa_free( &ecdsa );
+    if (unpadded_len > to_len || unpadded_len == 0) {
+        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+    }
 
-    return( ret );
+    padding_len = to_len - unpadded_len;
+    memset(to, 0x00, padding_len);
+    memcpy(to + padding_len, *from, unpadded_len);
+    (*from) += unpadded_len;
+
+    return 0;
 }
 
-static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
-                   const unsigned char *hash, size_t hash_len,
-                   unsigned char *sig, size_t *sig_len,
-                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+/*
+ * Convert a signature from an ASN.1 sequence of two integers
+ * to a raw {r,s} buffer. Note: the provided sig buffer must be at least
+ * twice as big as int_size.
+ */
+static int extract_ecdsa_sig(unsigned char **p, const unsigned char *end,
+                             unsigned char *sig, size_t int_size)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_ecdsa_context ecdsa;
+    size_t tmp_size;
 
-    mbedtls_ecdsa_init( &ecdsa );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &tmp_size,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return ret;
+    }
 
-    if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 )
-        ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len,
-                               f_rng, p_rng );
+    /* Extract r */
+    if ((ret = extract_ecdsa_sig_int(p, end, sig, int_size)) != 0) {
+        return ret;
+    }
+    /* Extract s */
+    if ((ret = extract_ecdsa_sig_int(p, end, sig + int_size, int_size)) != 0) {
+        return ret;
+    }
 
-    mbedtls_ecdsa_free( &ecdsa );
-
-    return( ret );
+    return 0;
 }
 
-#if defined(MBEDTLS_ECP_RESTARTABLE)
-/* Forward declarations */
-static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
-                       const unsigned char *hash, size_t hash_len,
-                       const unsigned char *sig, size_t sig_len,
-                       void *rs_ctx );
+static int ecdsa_verify_wrap(void *ctx_arg, mbedtls_md_type_t md_alg,
+                             const unsigned char *hash, size_t hash_len,
+                             const unsigned char *sig, size_t sig_len)
+{
+    mbedtls_ecp_keypair *ctx = ctx_arg;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_status_t status;
+    size_t key_len;
+    /* This buffer will initially contain the public key and then the signature
+     * but at different points in time. For all curves except secp224k1, which
+     * is not currently supported in PSA, the public key is one byte longer
+     * (header byte + 2 numbers, while the signature is only 2 numbers),
+     * so use that as the buffer size. */
+    unsigned char buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
+    unsigned char *p;
+    psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY;
+    size_t curve_bits;
+    psa_ecc_family_t curve =
+        mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits);
+    const size_t signature_part_size = (ctx->grp.nbits + 7) / 8;
+    ((void) md_alg);
 
-static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
-                   const unsigned char *hash, size_t hash_len,
-                   unsigned char *sig, size_t *sig_len,
-                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
-                   void *rs_ctx );
+    if (curve == 0) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve));
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
+    psa_set_key_algorithm(&attributes, psa_sig_md);
+
+    ret = mbedtls_ecp_point_write_binary(&ctx->grp, &ctx->Q,
+                                         MBEDTLS_ECP_PF_UNCOMPRESSED,
+                                         &key_len, buf, sizeof(buf));
+    if (ret != 0) {
+        goto cleanup;
+    }
+
+    status = psa_import_key(&attributes,
+                            buf, key_len,
+                            &key_id);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
+        goto cleanup;
+    }
+
+    /* We don't need the exported key anymore and can
+     * reuse its buffer for signature extraction. */
+    if (2 * signature_part_size > sizeof(buf)) {
+        ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+        goto cleanup;
+    }
+
+    p = (unsigned char *) sig;
+    if ((ret = extract_ecdsa_sig(&p, sig + sig_len, buf,
+                                 signature_part_size)) != 0) {
+        goto cleanup;
+    }
+
+    status = psa_verify_hash(key_id, psa_sig_md,
+                             hash, hash_len,
+                             buf, 2 * signature_part_size);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
+        goto cleanup;
+    }
+
+    if (p != sig + sig_len) {
+        ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
+        goto cleanup;
+    }
+    ret = 0;
+
+cleanup:
+    status = psa_destroy_key(key_id);
+    if (ret == 0 && status != PSA_SUCCESS) {
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
+    }
+
+    return ret;
+}
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+static int ecdsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg,
+                             const unsigned char *hash, size_t hash_len,
+                             const unsigned char *sig, size_t sig_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    ((void) md_alg);
+
+    ret = mbedtls_ecdsa_read_signature((mbedtls_ecdsa_context *) ctx,
+                                       hash, hash_len, sig, sig_len);
+
+    if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) {
+        return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
+    }
+
+    return ret;
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */
+
+#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+/*
+ * Simultaneously convert and move raw MPI from the beginning of a buffer
+ * to an ASN.1 MPI at the end of the buffer.
+ * See also mbedtls_asn1_write_mpi().
+ *
+ * p: pointer to the end of the output buffer
+ * start: start of the output buffer, and also of the mpi to write at the end
+ * n_len: length of the mpi to read from start
+ */
+static int asn1_write_mpibuf(unsigned char **p, unsigned char *start,
+                             size_t n_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t len = 0;
+
+    if ((size_t) (*p - start) < n_len) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    }
+
+    len = n_len;
+    *p -= len;
+    memmove(*p, start, len);
+
+    /* ASN.1 DER encoding requires minimal length, so skip leading 0s.
+     * Neither r nor s should be 0, but as a failsafe measure, still detect
+     * that rather than overflowing the buffer in case of a PSA error. */
+    while (len > 0 && **p == 0x00) {
+        ++(*p);
+        --len;
+    }
+
+    /* this is only reached if the signature was invalid */
+    if (len == 0) {
+        return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+    }
+
+    /* if the msb is 1, ASN.1 requires that we prepend a 0.
+     * Neither r nor s can be 0, so we can assume len > 0 at all times. */
+    if (**p & 0x80) {
+        if (*p - start < 1) {
+            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+        }
+
+        *--(*p) = 0x00;
+        len += 1;
+    }
+
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
+                                                     MBEDTLS_ASN1_INTEGER));
+
+    return (int) len;
+}
+
+/* Transcode signature from PSA format to ASN.1 sequence.
+ * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of
+ * MPIs, and in-place.
+ *
+ * [in/out] sig: the signature pre- and post-transcoding
+ * [in/out] sig_len: signature length pre- and post-transcoding
+ * [int] buf_len: the available size the in/out buffer
+ */
+static int pk_ecdsa_sig_asn1_from_psa(unsigned char *sig, size_t *sig_len,
+                                      size_t buf_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t len = 0;
+    const size_t rs_len = *sig_len / 2;
+    unsigned char *p = sig + buf_len;
+
+    MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig + rs_len, rs_len));
+    MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig, rs_len));
+
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, sig, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, sig,
+                                                     MBEDTLS_ASN1_CONSTRUCTED |
+                                                     MBEDTLS_ASN1_SEQUENCE));
+
+    memmove(sig, p, len);
+    *sig_len = len;
+
+    return 0;
+}
+
+static int ecdsa_sign_wrap(void *ctx_arg, mbedtls_md_type_t md_alg,
+                           const unsigned char *hash, size_t hash_len,
+                           unsigned char *sig, size_t sig_size, size_t *sig_len,
+                           int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+    mbedtls_ecp_keypair *ctx = ctx_arg;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_status_t status;
+    unsigned char buf[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH];
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+    psa_algorithm_t psa_sig_md =
+        PSA_ALG_DETERMINISTIC_ECDSA(mbedtls_hash_info_psa_from_md(md_alg));
+#else
+    psa_algorithm_t psa_sig_md =
+        PSA_ALG_ECDSA(mbedtls_hash_info_psa_from_md(md_alg));
+#endif
+    size_t curve_bits;
+    psa_ecc_family_t curve =
+        mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits);
+    size_t key_len = PSA_BITS_TO_BYTES(curve_bits);
+
+    /* PSA has its own RNG */
+    ((void) f_rng);
+    ((void) p_rng);
+
+    if (curve == 0) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    if (key_len > sizeof(buf)) {
+        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    }
+    ret = mbedtls_mpi_write_binary(&ctx->d, buf, key_len);
+    if (ret != 0) {
+        goto cleanup;
+    }
+
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
+    psa_set_key_algorithm(&attributes, psa_sig_md);
+
+    status = psa_import_key(&attributes,
+                            buf, key_len,
+                            &key_id);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
+        goto cleanup;
+    }
+
+    status = psa_sign_hash(key_id, psa_sig_md, hash, hash_len,
+                           sig, sig_size, sig_len);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
+        goto cleanup;
+    }
+
+    ret = pk_ecdsa_sig_asn1_from_psa(sig, sig_len, sig_size);
+
+cleanup:
+    mbedtls_platform_zeroize(buf, sizeof(buf));
+    status = psa_destroy_key(key_id);
+    if (ret == 0 && status != PSA_SUCCESS) {
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
+    }
+
+    return ret;
+}
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+static int ecdsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
+                           const unsigned char *hash, size_t hash_len,
+                           unsigned char *sig, size_t sig_size, size_t *sig_len,
+                           int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+    return mbedtls_ecdsa_write_signature((mbedtls_ecdsa_context *) ctx,
+                                         md_alg, hash, hash_len,
+                                         sig, sig_size, sig_len,
+                                         f_rng, p_rng);
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+/* Forward declarations */
+static int ecdsa_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
+                                const unsigned char *hash, size_t hash_len,
+                                const unsigned char *sig, size_t sig_len,
+                                void *rs_ctx);
+
+static int ecdsa_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
+                              const unsigned char *hash, size_t hash_len,
+                              unsigned char *sig, size_t sig_size, size_t *sig_len,
+                              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                              void *rs_ctx);
 
 /*
  * Restart context for ECDSA operations with ECKEY context
@@ -294,120 +1006,126 @@
  * We need to store an actual ECDSA context, as we need to pass the same to
  * the underlying ecdsa function, so we can't create it on the fly every time.
  */
-typedef struct
-{
+typedef struct {
     mbedtls_ecdsa_restart_ctx ecdsa_rs;
     mbedtls_ecdsa_context ecdsa_ctx;
 } eckey_restart_ctx;
 
-static void *eckey_rs_alloc( void )
+static void *eckey_rs_alloc(void)
 {
     eckey_restart_ctx *rs_ctx;
 
-    void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) );
+    void *ctx = mbedtls_calloc(1, sizeof(eckey_restart_ctx));
 
-    if( ctx != NULL )
-    {
+    if (ctx != NULL) {
         rs_ctx = ctx;
-        mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs );
-        mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx );
+        mbedtls_ecdsa_restart_init(&rs_ctx->ecdsa_rs);
+        mbedtls_ecdsa_init(&rs_ctx->ecdsa_ctx);
     }
 
-    return( ctx );
+    return ctx;
 }
 
-static void eckey_rs_free( void *ctx )
+static void eckey_rs_free(void *ctx)
 {
     eckey_restart_ctx *rs_ctx;
 
-    if( ctx == NULL)
+    if (ctx == NULL) {
         return;
+    }
 
     rs_ctx = ctx;
-    mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs );
-    mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx );
+    mbedtls_ecdsa_restart_free(&rs_ctx->ecdsa_rs);
+    mbedtls_ecdsa_free(&rs_ctx->ecdsa_ctx);
 
-    mbedtls_free( ctx );
+    mbedtls_free(ctx);
 }
 
-static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
-                       const unsigned char *hash, size_t hash_len,
-                       const unsigned char *sig, size_t sig_len,
-                       void *rs_ctx )
+static int eckey_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
+                                const unsigned char *hash, size_t hash_len,
+                                const unsigned char *sig, size_t sig_len,
+                                void *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     eckey_restart_ctx *rs = rs_ctx;
 
     /* Should never happen */
-    if( rs == NULL )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+    if (rs == NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
 
     /* set up our own sub-context if needed (that is, on first run) */
-    if( rs->ecdsa_ctx.grp.pbits == 0 )
-        MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) );
+    if (rs->ecdsa_ctx.grp.pbits == 0) {
+        MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, ctx));
+    }
 
-    MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx,
-                                           md_alg, hash, hash_len,
-                                           sig, sig_len, &rs->ecdsa_rs ) );
+    MBEDTLS_MPI_CHK(ecdsa_verify_rs_wrap(&rs->ecdsa_ctx,
+                                         md_alg, hash, hash_len,
+                                         sig, sig_len, &rs->ecdsa_rs));
 
 cleanup:
-    return( ret );
+    return ret;
 }
 
-static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
-                   const unsigned char *hash, size_t hash_len,
-                   unsigned char *sig, size_t *sig_len,
-                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
-                       void *rs_ctx )
+static int eckey_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
+                              const unsigned char *hash, size_t hash_len,
+                              unsigned char *sig, size_t sig_size, size_t *sig_len,
+                              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                              void *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     eckey_restart_ctx *rs = rs_ctx;
 
     /* Should never happen */
-    if( rs == NULL )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+    if (rs == NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
 
     /* set up our own sub-context if needed (that is, on first run) */
-    if( rs->ecdsa_ctx.grp.pbits == 0 )
-        MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) );
+    if (rs->ecdsa_ctx.grp.pbits == 0) {
+        MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, ctx));
+    }
 
-    MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg,
-                                         hash, hash_len, sig, sig_len,
-                                         f_rng, p_rng, &rs->ecdsa_rs ) );
+    MBEDTLS_MPI_CHK(ecdsa_sign_rs_wrap(&rs->ecdsa_ctx, md_alg,
+                                       hash, hash_len, sig, sig_size, sig_len,
+                                       f_rng, p_rng, &rs->ecdsa_rs));
 
 cleanup:
-    return( ret );
+    return ret;
 }
-#endif /* MBEDTLS_ECP_RESTARTABLE */
-#endif /* MBEDTLS_ECDSA_C */
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
 
-static int eckey_check_pair( const void *pub, const void *prv )
+static int eckey_check_pair(const void *pub, const void *prv,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng)
 {
-    return( mbedtls_ecp_check_pub_priv( (const mbedtls_ecp_keypair *) pub,
-                                (const mbedtls_ecp_keypair *) prv ) );
+    return mbedtls_ecp_check_pub_priv((const mbedtls_ecp_keypair *) pub,
+                                      (const mbedtls_ecp_keypair *) prv,
+                                      f_rng, p_rng);
 }
 
-static void *eckey_alloc_wrap( void )
+static void *eckey_alloc_wrap(void)
 {
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) );
+    void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair));
 
-    if( ctx != NULL )
-        mbedtls_ecp_keypair_init( ctx );
+    if (ctx != NULL) {
+        mbedtls_ecp_keypair_init(ctx);
+    }
 
-    return( ctx );
+    return ctx;
 }
 
-static void eckey_free_wrap( void *ctx )
+static void eckey_free_wrap(void *ctx)
 {
-    mbedtls_ecp_keypair_free( (mbedtls_ecp_keypair *) ctx );
-    mbedtls_free( ctx );
+    mbedtls_ecp_keypair_free((mbedtls_ecp_keypair *) ctx);
+    mbedtls_free(ctx);
 }
 
-static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items )
+static void eckey_debug(const void *ctx, mbedtls_pk_debug_item *items)
 {
     items->type = MBEDTLS_PK_DEBUG_ECP;
     items->name = "eckey.Q";
-    items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q );
+    items->value = &(((mbedtls_ecp_keypair *) ctx)->Q);
 }
 
 const mbedtls_pk_info_t mbedtls_eckey_info = {
@@ -415,17 +1133,20 @@
     "EC",
     eckey_get_bitlen,
     eckey_can_do,
-#if defined(MBEDTLS_ECDSA_C)
-    eckey_verify_wrap,
-    eckey_sign_wrap,
-#if defined(MBEDTLS_ECP_RESTARTABLE)
+#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)
+    ecdsa_verify_wrap,   /* Compatible key structures */
+#else
+    NULL,
+#endif
+#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
+    ecdsa_sign_wrap,   /* Compatible key structures */
+#else
+    NULL,
+#endif
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
     eckey_verify_rs_wrap,
     eckey_sign_rs_wrap,
 #endif
-#else /* MBEDTLS_ECDSA_C */
-    NULL,
-    NULL,
-#endif /* MBEDTLS_ECDSA_C */
     NULL,
     NULL,
     eckey_check_pair,
@@ -441,10 +1162,10 @@
 /*
  * EC key restricted to ECDH
  */
-static int eckeydh_can_do( mbedtls_pk_type_t type )
+static int eckeydh_can_do(mbedtls_pk_type_t type)
 {
-    return( type == MBEDTLS_PK_ECKEY ||
-            type == MBEDTLS_PK_ECKEY_DH );
+    return type == MBEDTLS_PK_ECKEY ||
+           type == MBEDTLS_PK_ECKEY_DH;
 }
 
 const mbedtls_pk_info_t mbedtls_eckeydh_info = {
@@ -471,370 +1192,201 @@
 };
 #endif /* MBEDTLS_ECP_C */
 
-#if defined(MBEDTLS_ECDSA_C)
-static int ecdsa_can_do( mbedtls_pk_type_t type )
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
+static int ecdsa_can_do(mbedtls_pk_type_t type)
 {
-    return( type == MBEDTLS_PK_ECDSA );
+    return type == MBEDTLS_PK_ECDSA;
 }
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-/*
- * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of
- * those integers and convert it to the fixed-length encoding expected by PSA.
- */
-static int extract_ecdsa_sig_int( unsigned char **from, const unsigned char *end,
-                                  unsigned char *to, size_t to_len )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t unpadded_len, padding_len;
-
-    if( ( ret = mbedtls_asn1_get_tag( from, end, &unpadded_len,
-                                      MBEDTLS_ASN1_INTEGER ) ) != 0 )
-    {
-        return( ret );
-    }
-
-    while( unpadded_len > 0 && **from == 0x00 )
-    {
-        ( *from )++;
-        unpadded_len--;
-    }
-
-    if( unpadded_len > to_len || unpadded_len == 0 )
-        return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-
-    padding_len = to_len - unpadded_len;
-    memset( to, 0x00, padding_len );
-    memcpy( to + padding_len, *from, unpadded_len );
-    ( *from ) += unpadded_len;
-
-    return( 0 );
-}
-
-/*
- * Convert a signature from an ASN.1 sequence of two integers
- * to a raw {r,s} buffer. Note: the provided sig buffer must be at least
- * twice as big as int_size.
- */
-static int extract_ecdsa_sig( unsigned char **p, const unsigned char *end,
-                              unsigned char *sig, size_t int_size )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t tmp_size;
-
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &tmp_size,
-                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( ret );
-
-    /* Extract r */
-    if( ( ret = extract_ecdsa_sig_int( p, end, sig, int_size ) ) != 0 )
-        return( ret );
-    /* Extract s */
-    if( ( ret = extract_ecdsa_sig_int( p, end, sig + int_size, int_size ) ) != 0 )
-        return( ret );
-
-    return( 0 );
-}
-
-static int ecdsa_verify_wrap( void *ctx_arg, mbedtls_md_type_t md_alg,
-                       const unsigned char *hash, size_t hash_len,
-                       const unsigned char *sig, size_t sig_len )
-{
-    mbedtls_ecdsa_context *ctx = ctx_arg;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_id_t key_id = 0;
-    psa_status_t status;
-    mbedtls_pk_context key;
-    int key_len;
-    /* see ECP_PUB_DER_MAX_BYTES in pkwrite.c */
-    unsigned char buf[30 + 2 * MBEDTLS_ECP_MAX_BYTES];
-    unsigned char *p;
-    mbedtls_pk_info_t pk_info = mbedtls_eckey_info;
-    psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY;
-    size_t curve_bits;
-    psa_ecc_family_t curve =
-        mbedtls_ecc_group_to_psa( ctx->grp.id, &curve_bits );
-    const size_t signature_part_size = ( ctx->grp.nbits + 7 ) / 8;
-    ((void) md_alg);
-
-    if( curve == 0 )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
-
-    /* mbedtls_pk_write_pubkey() expects a full PK context;
-     * re-construct one to make it happy */
-    key.pk_info = &pk_info;
-    key.pk_ctx = ctx;
-    p = buf + sizeof( buf );
-    key_len = mbedtls_pk_write_pubkey( &p, buf, &key );
-    if( key_len <= 0 )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
-
-    psa_set_key_type( &attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY( curve ) );
-    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH );
-    psa_set_key_algorithm( &attributes, psa_sig_md );
-
-    status = psa_import_key( &attributes,
-                             buf + sizeof( buf ) - key_len, key_len,
-                             &key_id );
-    if( status != PSA_SUCCESS )
-    {
-        ret = mbedtls_psa_err_translate_pk( status );
-        goto cleanup;
-    }
-
-    /* We don't need the exported key anymore and can
-     * reuse its buffer for signature extraction. */
-    if( 2 * signature_part_size > sizeof( buf ) )
-    {
-        ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-        goto cleanup;
-    }
-
-    p = (unsigned char*) sig;
-    if( ( ret = extract_ecdsa_sig( &p, sig + sig_len, buf,
-                                   signature_part_size ) ) != 0 )
-    {
-        goto cleanup;
-    }
-
-    if( psa_verify_hash( key_id, psa_sig_md,
-                         hash, hash_len,
-                         buf, 2 * signature_part_size )
-         != PSA_SUCCESS )
-    {
-         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
-         goto cleanup;
-    }
-
-    if( p != sig + sig_len )
-    {
-        ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
-        goto cleanup;
-    }
-    ret = 0;
-
-cleanup:
-    psa_destroy_key( key_id );
-    return( ret );
-}
-#else /* MBEDTLS_USE_PSA_CRYPTO */
-static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
-                       const unsigned char *hash, size_t hash_len,
-                       const unsigned char *sig, size_t sig_len )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    ((void) md_alg);
-
-    ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx,
-                                hash, hash_len, sig, sig_len );
-
-    if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH )
-        return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
-
-    return( ret );
-}
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
-                   const unsigned char *hash, size_t hash_len,
-                   unsigned char *sig, size_t *sig_len,
-                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
-{
-    return( mbedtls_ecdsa_write_signature( (mbedtls_ecdsa_context *) ctx,
-                md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) );
-}
-
-#if defined(MBEDTLS_ECP_RESTARTABLE)
-static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
-                       const unsigned char *hash, size_t hash_len,
-                       const unsigned char *sig, size_t sig_len,
-                       void *rs_ctx )
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+static int ecdsa_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
+                                const unsigned char *hash, size_t hash_len,
+                                const unsigned char *sig, size_t sig_len,
+                                void *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     ((void) md_alg);
 
     ret = mbedtls_ecdsa_read_signature_restartable(
-            (mbedtls_ecdsa_context *) ctx,
-            hash, hash_len, sig, sig_len,
-            (mbedtls_ecdsa_restart_ctx *) rs_ctx );
+        (mbedtls_ecdsa_context *) ctx,
+        hash, hash_len, sig, sig_len,
+        (mbedtls_ecdsa_restart_ctx *) rs_ctx);
 
-    if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH )
-        return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
+    if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) {
+        return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
+    }
 
-    return( ret );
+    return ret;
 }
 
-static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
-                   const unsigned char *hash, size_t hash_len,
-                   unsigned char *sig, size_t *sig_len,
-                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
-                   void *rs_ctx )
+static int ecdsa_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
+                              const unsigned char *hash, size_t hash_len,
+                              unsigned char *sig, size_t sig_size, size_t *sig_len,
+                              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                              void *rs_ctx)
 {
-    return( mbedtls_ecdsa_write_signature_restartable(
-                (mbedtls_ecdsa_context *) ctx,
-                md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng,
-                (mbedtls_ecdsa_restart_ctx *) rs_ctx ) );
+    return mbedtls_ecdsa_write_signature_restartable(
+        (mbedtls_ecdsa_context *) ctx,
+        md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng,
+        (mbedtls_ecdsa_restart_ctx *) rs_ctx);
 
 }
-#endif /* MBEDTLS_ECP_RESTARTABLE */
 
-static void *ecdsa_alloc_wrap( void )
+static void *ecdsa_rs_alloc(void)
 {
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) );
+    void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecdsa_restart_ctx));
 
-    if( ctx != NULL )
-        mbedtls_ecdsa_init( (mbedtls_ecdsa_context *) ctx );
+    if (ctx != NULL) {
+        mbedtls_ecdsa_restart_init(ctx);
+    }
 
-    return( ctx );
+    return ctx;
 }
 
-static void ecdsa_free_wrap( void *ctx )
+static void ecdsa_rs_free(void *ctx)
 {
-    mbedtls_ecdsa_free( (mbedtls_ecdsa_context *) ctx );
-    mbedtls_free( ctx );
+    mbedtls_ecdsa_restart_free(ctx);
+    mbedtls_free(ctx);
 }
-
-#if defined(MBEDTLS_ECP_RESTARTABLE)
-static void *ecdsa_rs_alloc( void )
-{
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) );
-
-    if( ctx != NULL )
-        mbedtls_ecdsa_restart_init( ctx );
-
-    return( ctx );
-}
-
-static void ecdsa_rs_free( void *ctx )
-{
-    mbedtls_ecdsa_restart_free( ctx );
-    mbedtls_free( ctx );
-}
-#endif /* MBEDTLS_ECP_RESTARTABLE */
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
 
 const mbedtls_pk_info_t mbedtls_ecdsa_info = {
     MBEDTLS_PK_ECDSA,
     "ECDSA",
     eckey_get_bitlen,     /* Compatible key structures */
     ecdsa_can_do,
-    ecdsa_verify_wrap,
-    ecdsa_sign_wrap,
-#if defined(MBEDTLS_ECP_RESTARTABLE)
+#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)
+    ecdsa_verify_wrap,   /* Compatible key structures */
+#else
+    NULL,
+#endif
+#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
+    ecdsa_sign_wrap,   /* Compatible key structures */
+#else
+    NULL,
+#endif
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
     ecdsa_verify_rs_wrap,
     ecdsa_sign_rs_wrap,
 #endif
     NULL,
     NULL,
     eckey_check_pair,   /* Compatible key structures */
-    ecdsa_alloc_wrap,
-    ecdsa_free_wrap,
-#if defined(MBEDTLS_ECP_RESTARTABLE)
+    eckey_alloc_wrap,   /* Compatible key structures */
+    eckey_free_wrap,   /* Compatible key structures */
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
     ecdsa_rs_alloc,
     ecdsa_rs_free,
 #endif
     eckey_debug,        /* Compatible key structures */
 };
-#endif /* MBEDTLS_ECDSA_C */
+#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */
 
 #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
 /*
  * Support for alternative RSA-private implementations
  */
 
-static int rsa_alt_can_do( mbedtls_pk_type_t type )
+static int rsa_alt_can_do(mbedtls_pk_type_t type)
 {
-    return( type == MBEDTLS_PK_RSA );
+    return type == MBEDTLS_PK_RSA;
 }
 
-static size_t rsa_alt_get_bitlen( const void *ctx )
+static size_t rsa_alt_get_bitlen(const void *ctx)
 {
     const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx;
 
-    return( 8 * rsa_alt->key_len_func( rsa_alt->key ) );
+    return 8 * rsa_alt->key_len_func(rsa_alt->key);
 }
 
-static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
-                   const unsigned char *hash, size_t hash_len,
-                   unsigned char *sig, size_t *sig_len,
-                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+static int rsa_alt_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
+                             const unsigned char *hash, size_t hash_len,
+                             unsigned char *sig, size_t sig_size, size_t *sig_len,
+                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
     mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx;
 
-#if SIZE_MAX > UINT_MAX
-    if( UINT_MAX < hash_len )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
-#endif /* SIZE_MAX > UINT_MAX */
+    if (UINT_MAX < hash_len) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
 
-    *sig_len = rsa_alt->key_len_func( rsa_alt->key );
-    if( *sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+    *sig_len = rsa_alt->key_len_func(rsa_alt->key);
+    if (*sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+    if (*sig_len > sig_size) {
+        return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
+    }
 
-    return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE,
-                md_alg, (unsigned int) hash_len, hash, sig ) );
+    return rsa_alt->sign_func(rsa_alt->key, f_rng, p_rng,
+                              md_alg, (unsigned int) hash_len, hash, sig);
 }
 
-static int rsa_alt_decrypt_wrap( void *ctx,
-                    const unsigned char *input, size_t ilen,
-                    unsigned char *output, size_t *olen, size_t osize,
-                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+static int rsa_alt_decrypt_wrap(void *ctx,
+                                const unsigned char *input, size_t ilen,
+                                unsigned char *output, size_t *olen, size_t osize,
+                                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
     mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx;
 
     ((void) f_rng);
     ((void) p_rng);
 
-    if( ilen != rsa_alt->key_len_func( rsa_alt->key ) )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (ilen != rsa_alt->key_len_func(rsa_alt->key)) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
-    return( rsa_alt->decrypt_func( rsa_alt->key,
-                MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) );
+    return rsa_alt->decrypt_func(rsa_alt->key,
+                                 olen, input, output, osize);
 }
 
 #if defined(MBEDTLS_RSA_C)
-static int rsa_alt_check_pair( const void *pub, const void *prv )
+static int rsa_alt_check_pair(const void *pub, const void *prv,
+                              int (*f_rng)(void *, unsigned char *, size_t),
+                              void *p_rng)
 {
     unsigned char sig[MBEDTLS_MPI_MAX_SIZE];
     unsigned char hash[32];
     size_t sig_len = 0;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) )
-        return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
-
-    memset( hash, 0x2a, sizeof( hash ) );
-
-    if( ( ret = rsa_alt_sign_wrap( (void *) prv, MBEDTLS_MD_NONE,
-                                   hash, sizeof( hash ),
-                                   sig, &sig_len, NULL, NULL ) ) != 0 )
-    {
-        return( ret );
+    if (rsa_alt_get_bitlen(prv) != rsa_get_bitlen(pub)) {
+        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     }
 
-    if( rsa_verify_wrap( (void *) pub, MBEDTLS_MD_NONE,
-                         hash, sizeof( hash ), sig, sig_len ) != 0 )
-    {
-        return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
+    memset(hash, 0x2a, sizeof(hash));
+
+    if ((ret = rsa_alt_sign_wrap((void *) prv, MBEDTLS_MD_NONE,
+                                 hash, sizeof(hash),
+                                 sig, sizeof(sig), &sig_len,
+                                 f_rng, p_rng)) != 0) {
+        return ret;
     }
 
-    return( 0 );
+    if (rsa_verify_wrap((void *) pub, MBEDTLS_MD_NONE,
+                        hash, sizeof(hash), sig, sig_len) != 0) {
+        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
+    }
+
+    return 0;
 }
 #endif /* MBEDTLS_RSA_C */
 
-static void *rsa_alt_alloc_wrap( void )
+static void *rsa_alt_alloc_wrap(void)
 {
-    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_alt_context ) );
+    void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_alt_context));
 
-    if( ctx != NULL )
-        memset( ctx, 0, sizeof( mbedtls_rsa_alt_context ) );
+    if (ctx != NULL) {
+        memset(ctx, 0, sizeof(mbedtls_rsa_alt_context));
+    }
 
-    return( ctx );
+    return ctx;
 }
 
-static void rsa_alt_free_wrap( void *ctx )
+static void rsa_alt_free_wrap(void *ctx)
 {
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) );
-    mbedtls_free( ctx );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_rsa_alt_context));
+    mbedtls_free(ctx);
 }
 
 const mbedtls_pk_info_t mbedtls_rsa_alt_info = {
@@ -868,191 +1420,187 @@
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 
-static void *pk_opaque_alloc_wrap( void )
+static void *pk_opaque_alloc_wrap(void)
 {
-    void *ctx = mbedtls_calloc( 1, sizeof( psa_key_id_t ) );
+    void *ctx = mbedtls_calloc(1, sizeof(mbedtls_svc_key_id_t));
 
-    /* no _init() function to call, an calloc() already zeroized */
+    /* no _init() function to call, as calloc() already zeroized */
 
-    return( ctx );
+    return ctx;
 }
 
-static void pk_opaque_free_wrap( void *ctx )
+static void pk_opaque_free_wrap(void *ctx)
 {
-    mbedtls_platform_zeroize( ctx, sizeof( psa_key_id_t ) );
-    mbedtls_free( ctx );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_svc_key_id_t));
+    mbedtls_free(ctx);
 }
 
-static size_t pk_opaque_get_bitlen( const void *ctx )
+static size_t pk_opaque_get_bitlen(const void *ctx)
 {
-    const psa_key_id_t *key = (const psa_key_id_t *) ctx;
+    const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx;
     size_t bits;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-    if( PSA_SUCCESS != psa_get_key_attributes( *key, &attributes ) )
-        return( 0 );
-
-    bits = psa_get_key_bits( &attributes );
-    psa_reset_key_attributes( &attributes );
-    return( bits );
-}
-
-static int pk_opaque_can_do( mbedtls_pk_type_t type )
-{
-    /* For now opaque PSA keys can only wrap ECC keypairs,
-     * as checked by setup_psa().
-     * Also, ECKEY_DH does not really make sense with the current API. */
-    return( type == MBEDTLS_PK_ECKEY ||
-            type == MBEDTLS_PK_ECDSA );
-}
-
-#if defined(MBEDTLS_ECDSA_C)
-
-/*
- * Simultaneously convert and move raw MPI from the beginning of a buffer
- * to an ASN.1 MPI at the end of the buffer.
- * See also mbedtls_asn1_write_mpi().
- *
- * p: pointer to the end of the output buffer
- * start: start of the output buffer, and also of the mpi to write at the end
- * n_len: length of the mpi to read from start
- */
-static int asn1_write_mpibuf( unsigned char **p, unsigned char *start,
-                              size_t n_len )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t len = 0;
-
-    if( (size_t)( *p - start ) < n_len )
-        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
-
-    len = n_len;
-    *p -= len;
-    memmove( *p, start, len );
-
-    /* ASN.1 DER encoding requires minimal length, so skip leading 0s.
-     * Neither r nor s should be 0, but as a failsafe measure, still detect
-     * that rather than overflowing the buffer in case of a PSA error. */
-    while( len > 0 && **p == 0x00 )
-    {
-        ++(*p);
-        --len;
+    if (PSA_SUCCESS != psa_get_key_attributes(*key, &attributes)) {
+        return 0;
     }
 
-    /* this is only reached if the signature was invalid */
-    if( len == 0 )
-        return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
-
-    /* if the msb is 1, ASN.1 requires that we prepend a 0.
-     * Neither r nor s can be 0, so we can assume len > 0 at all times. */
-    if( **p & 0x80 )
-    {
-        if( *p - start < 1 )
-            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
-
-        *--(*p) = 0x00;
-        len += 1;
-    }
-
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
-                                                MBEDTLS_ASN1_INTEGER ) );
-
-    return( (int) len );
+    bits = psa_get_key_bits(&attributes);
+    psa_reset_key_attributes(&attributes);
+    return bits;
 }
 
-/* Transcode signature from PSA format to ASN.1 sequence.
- * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of
- * MPIs, and in-place.
- *
- * [in/out] sig: the signature pre- and post-transcoding
- * [in/out] sig_len: signature length pre- and post-transcoding
- * [int] buf_len: the available size the in/out buffer
- */
-static int pk_ecdsa_sig_asn1_from_psa( unsigned char *sig, size_t *sig_len,
-                                       size_t buf_len )
+static int pk_opaque_ecdsa_can_do(mbedtls_pk_type_t type)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t len = 0;
-    const size_t rs_len = *sig_len / 2;
-    unsigned char *p = sig + buf_len;
-
-    MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig + rs_len, rs_len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig, rs_len ) );
-
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, sig, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, sig,
-                          MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
-
-    memmove( sig, p, len );
-    *sig_len = len;
-
-    return( 0 );
+    return type == MBEDTLS_PK_ECKEY ||
+           type == MBEDTLS_PK_ECDSA;
 }
 
-#endif /* MBEDTLS_ECDSA_C */
-
-static int pk_opaque_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
-                   const unsigned char *hash, size_t hash_len,
-                   unsigned char *sig, size_t *sig_len,
-                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+static int pk_opaque_rsa_can_do(mbedtls_pk_type_t type)
 {
-#if !defined(MBEDTLS_ECDSA_C)
+    return type == MBEDTLS_PK_RSA ||
+           type == MBEDTLS_PK_RSASSA_PSS;
+}
+
+static int pk_opaque_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
+                               const unsigned char *hash, size_t hash_len,
+                               unsigned char *sig, size_t sig_size, size_t *sig_len,
+                               int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+#if !defined(MBEDTLS_PK_CAN_ECDSA_SIGN) && !defined(MBEDTLS_RSA_C)
     ((void) ctx);
     ((void) md_alg);
     ((void) hash);
     ((void) hash_len);
     ((void) sig);
+    ((void) sig_size);
     ((void) sig_len);
     ((void) f_rng);
     ((void) p_rng);
-    return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
-#else /* !MBEDTLS_ECDSA_C */
-    const psa_key_id_t *key = (const psa_key_id_t *) ctx;
+    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+#else /* !MBEDTLS_PK_CAN_ECDSA_SIGN && !MBEDTLS_RSA_C */
+    const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_algorithm_t alg = PSA_ALG_ECDSA( mbedtls_psa_translate_md( md_alg ) );
-    size_t buf_len;
+    psa_algorithm_t alg;
+    psa_key_type_t type;
     psa_status_t status;
 
     /* PSA has its own RNG */
     (void) f_rng;
     (void) p_rng;
 
-    /* PSA needs an output buffer of known size, but our API doesn't provide
-     * that information. Assume that the buffer is large enough for a
-     * maximal-length signature with that key (otherwise the application is
-     * buggy anyway). */
-    status = psa_get_key_attributes( *key, &attributes );
-    if( status != PSA_SUCCESS )
-        return( mbedtls_psa_err_translate_pk( status ) );
-    buf_len = MBEDTLS_ECDSA_MAX_SIG_LEN( psa_get_key_bits( &attributes ) );
-    psa_reset_key_attributes( &attributes );
-    if( buf_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+    status = psa_get_key_attributes(*key, &attributes);
+    if (status != PSA_SUCCESS) {
+        return PSA_PK_TO_MBEDTLS_ERR(status);
+    }
+
+    type = psa_get_key_type(&attributes);
+    psa_reset_key_attributes(&attributes);
+
+#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
+    if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
+        alg = PSA_ALG_ECDSA(mbedtls_hash_info_psa_from_md(md_alg));
+    } else
+#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
+#if defined(MBEDTLS_RSA_C)
+    if (PSA_KEY_TYPE_IS_RSA(type)) {
+        alg = PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_hash_info_psa_from_md(md_alg));
+    } else
+#endif /* MBEDTLS_RSA_C */
+    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
 
     /* make the signature */
-    status = psa_sign_hash( *key, alg, hash, hash_len,
-                            sig, buf_len, sig_len );
-    if( status != PSA_SUCCESS )
-        return( mbedtls_psa_err_translate_pk( status ) );
+    status = psa_sign_hash(*key, alg, hash, hash_len,
+                           sig, sig_size, sig_len);
+    if (status != PSA_SUCCESS) {
+#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
+        if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
+            return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
+        } else
+#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
+#if defined(MBEDTLS_RSA_C)
+        if (PSA_KEY_TYPE_IS_RSA(type)) {
+            return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
+        } else
+#endif /* MBEDTLS_RSA_C */
+        return PSA_PK_TO_MBEDTLS_ERR(status);
+    }
 
-    /* transcode it to ASN.1 sequence */
-    return( pk_ecdsa_sig_asn1_from_psa( sig, sig_len, buf_len ) );
-#endif /* !MBEDTLS_ECDSA_C */
+#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
+    if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
+        /* transcode it to ASN.1 sequence */
+        return pk_ecdsa_sig_asn1_from_psa(sig, sig_len, sig_size);
+    }
+#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
+
+    return 0;
+#endif /* !MBEDTLS_PK_CAN_ECDSA_SIGN && !MBEDTLS_RSA_C */
 }
 
-const mbedtls_pk_info_t mbedtls_pk_opaque_info = {
+const mbedtls_pk_info_t mbedtls_pk_ecdsa_opaque_info = {
     MBEDTLS_PK_OPAQUE,
     "Opaque",
     pk_opaque_get_bitlen,
-    pk_opaque_can_do,
+    pk_opaque_ecdsa_can_do,
     NULL, /* verify - will be done later */
     pk_opaque_sign_wrap,
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
     NULL, /* restartable verify - not relevant */
     NULL, /* restartable sign - not relevant */
 #endif
-    NULL, /* decrypt - will be done later */
+    NULL, /* decrypt - not relevant */
+    NULL, /* encrypt - not relevant */
+    NULL, /* check_pair - could be done later or left NULL */
+    pk_opaque_alloc_wrap,
+    pk_opaque_free_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    NULL, /* restart alloc - not relevant */
+    NULL, /* restart free - not relevant */
+#endif
+    NULL, /* debug - could be done later, or even left NULL */
+};
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
+static int pk_opaque_rsa_decrypt(void *ctx,
+                                 const unsigned char *input, size_t ilen,
+                                 unsigned char *output, size_t *olen, size_t osize,
+                                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+    const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx;
+    psa_status_t status;
+
+    /* PSA has its own RNG */
+    (void) f_rng;
+    (void) p_rng;
+
+    status = psa_asymmetric_decrypt(*key, PSA_ALG_RSA_PKCS1V15_CRYPT,
+                                    input, ilen,
+                                    NULL, 0,
+                                    output, osize, olen);
+    if (status != PSA_SUCCESS) {
+        return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
+    }
+
+    return 0;
+}
+#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */
+
+const mbedtls_pk_info_t mbedtls_pk_rsa_opaque_info = {
+    MBEDTLS_PK_OPAQUE,
+    "Opaque",
+    pk_opaque_get_bitlen,
+    pk_opaque_rsa_can_do,
+    NULL, /* verify - will be done later */
+    pk_opaque_sign_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    NULL, /* restartable verify - not relevant */
+    NULL, /* restartable sign - not relevant */
+#endif
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
+    pk_opaque_rsa_decrypt,
+#else
+    NULL, /* decrypt - not available */
+#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY */
     NULL, /* encrypt - will be done later */
     NULL, /* check_pair - could be done later or left NULL */
     pk_opaque_alloc_wrap,
diff --git a/lib/libmbedtls/mbedtls/library/pk_wrap.h b/lib/libmbedtls/mbedtls/library/pk_wrap.h
new file mode 100644
index 0000000..c5cd4df
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/pk_wrap.h
@@ -0,0 +1,168 @@
+/**
+ * \file pk_wrap.h
+ *
+ * \brief Public Key abstraction layer: wrapper functions
+ */
+/*
+ *  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_PK_WRAP_H
+#define MBEDTLS_PK_WRAP_H
+
+#include "mbedtls/build_info.h"
+
+#include "mbedtls/pk.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+#include "psa/crypto.h"
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
+struct mbedtls_pk_info_t {
+    /** Public key type */
+    mbedtls_pk_type_t type;
+
+    /** Type name */
+    const char *name;
+
+    /** Get key size in bits */
+    size_t (*get_bitlen)(const void *);
+
+    /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */
+    int (*can_do)(mbedtls_pk_type_t type);
+
+    /** Verify signature */
+    int (*verify_func)(void *ctx, mbedtls_md_type_t md_alg,
+                       const unsigned char *hash, size_t hash_len,
+                       const unsigned char *sig, size_t sig_len);
+
+    /** Make signature */
+    int (*sign_func)(void *ctx, mbedtls_md_type_t md_alg,
+                     const unsigned char *hash, size_t hash_len,
+                     unsigned char *sig, size_t sig_size, size_t *sig_len,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng);
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    /** Verify signature (restartable) */
+    int (*verify_rs_func)(void *ctx, mbedtls_md_type_t md_alg,
+                          const unsigned char *hash, size_t hash_len,
+                          const unsigned char *sig, size_t sig_len,
+                          void *rs_ctx);
+
+    /** Make signature (restartable) */
+    int (*sign_rs_func)(void *ctx, mbedtls_md_type_t md_alg,
+                        const unsigned char *hash, size_t hash_len,
+                        unsigned char *sig, size_t sig_size, size_t *sig_len,
+                        int (*f_rng)(void *, unsigned char *, size_t),
+                        void *p_rng, void *rs_ctx);
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
+    /** Decrypt message */
+    int (*decrypt_func)(void *ctx, const unsigned char *input, size_t ilen,
+                        unsigned char *output, size_t *olen, size_t osize,
+                        int (*f_rng)(void *, unsigned char *, size_t),
+                        void *p_rng);
+
+    /** Encrypt message */
+    int (*encrypt_func)(void *ctx, const unsigned char *input, size_t ilen,
+                        unsigned char *output, size_t *olen, size_t osize,
+                        int (*f_rng)(void *, unsigned char *, size_t),
+                        void *p_rng);
+
+    /** Check public-private key pair */
+    int (*check_pair_func)(const void *pub, const void *prv,
+                           int (*f_rng)(void *, unsigned char *, size_t),
+                           void *p_rng);
+
+    /** Allocate a new context */
+    void * (*ctx_alloc_func)(void);
+
+    /** Free the given context */
+    void (*ctx_free_func)(void *ctx);
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    /** Allocate the restart context */
+    void *(*rs_alloc_func)(void);
+
+    /** Free the restart context */
+    void (*rs_free_func)(void *rs_ctx);
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+
+    /** Interface with the debug module */
+    void (*debug_func)(const void *ctx, mbedtls_pk_debug_item *items);
+
+};
+#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
+/* Container for RSA-alt */
+typedef struct {
+    void *key;
+    mbedtls_pk_rsa_alt_decrypt_func decrypt_func;
+    mbedtls_pk_rsa_alt_sign_func sign_func;
+    mbedtls_pk_rsa_alt_key_len_func key_len_func;
+} mbedtls_rsa_alt_context;
+#endif
+
+#if defined(MBEDTLS_RSA_C)
+extern const mbedtls_pk_info_t mbedtls_rsa_info;
+#endif
+
+#if defined(MBEDTLS_ECP_C)
+extern const mbedtls_pk_info_t mbedtls_eckey_info;
+extern const mbedtls_pk_info_t mbedtls_eckeydh_info;
+#endif
+
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
+extern const mbedtls_pk_info_t mbedtls_ecdsa_info;
+#endif
+
+#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
+extern const mbedtls_pk_info_t mbedtls_rsa_alt_info;
+#endif
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+extern const mbedtls_pk_info_t mbedtls_pk_ecdsa_opaque_info;
+extern const mbedtls_pk_info_t mbedtls_pk_rsa_opaque_info;
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
+int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa_ecdsa(psa_status_t status);
+#endif
+#endif
+
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa(psa_status_t status);
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ||    \
+    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
+int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa_rsa(psa_status_t status);
+#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+
+#if defined(MBEDTLS_RSA_C)
+int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t psa_alg_md,
+                                mbedtls_rsa_context *rsa_ctx,
+                                const unsigned char *hash, size_t hash_len,
+                                unsigned char *sig, size_t sig_size,
+                                size_t *sig_len);
+#endif /* MBEDTLS_RSA_C */
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
+#endif /* MBEDTLS_PK_WRAP_H */
diff --git a/lib/libmbedtls/mbedtls/library/pkcs11.c b/lib/libmbedtls/mbedtls/library/pkcs11.c
deleted file mode 100644
index 4deccf3..0000000
--- a/lib/libmbedtls/mbedtls/library/pkcs11.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/**
- * \file pkcs11.c
- *
- * \brief Wrapper for PKCS#11 library libpkcs11-helper
- *
- * \author Adriaan de Jong <dejong@fox-it.com>
- *
- *  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.
- */
-
-#include "mbedtls/pkcs11.h"
-
-#if defined(MBEDTLS_PKCS11_C)
-
-#include "mbedtls/md.h"
-#include "mbedtls/oid.h"
-#include "mbedtls/x509_crt.h"
-
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free       free
-#endif
-
-#include <string.h>
-
-void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx )
-{
-    memset( ctx, 0, sizeof( mbedtls_pkcs11_context ) );
-}
-
-int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11_cert )
-{
-    int ret = 1;
-    unsigned char *cert_blob = NULL;
-    size_t cert_blob_size = 0;
-
-    if( cert == NULL )
-    {
-        ret = 2;
-        goto cleanup;
-    }
-
-    if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL,
-                                                &cert_blob_size ) != CKR_OK )
-    {
-        ret = 3;
-        goto cleanup;
-    }
-
-    cert_blob = mbedtls_calloc( 1, cert_blob_size );
-    if( NULL == cert_blob )
-    {
-        ret = 4;
-        goto cleanup;
-    }
-
-    if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob,
-                                                &cert_blob_size ) != CKR_OK )
-    {
-        ret = 5;
-        goto cleanup;
-    }
-
-    if( 0 != mbedtls_x509_crt_parse( cert, cert_blob, cert_blob_size ) )
-    {
-        ret = 6;
-        goto cleanup;
-    }
-
-    ret = 0;
-
-cleanup:
-    if( NULL != cert_blob )
-        mbedtls_free( cert_blob );
-
-    return( ret );
-}
-
-
-int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key,
-        pkcs11h_certificate_t pkcs11_cert )
-{
-    int ret = 1;
-    mbedtls_x509_crt cert;
-
-    mbedtls_x509_crt_init( &cert );
-
-    if( priv_key == NULL )
-        goto cleanup;
-
-    if( 0 != mbedtls_pkcs11_x509_cert_bind( &cert, pkcs11_cert ) )
-        goto cleanup;
-
-    priv_key->len = mbedtls_pk_get_len( &cert.pk );
-    priv_key->pkcs11h_cert = pkcs11_cert;
-
-    ret = 0;
-
-cleanup:
-    mbedtls_x509_crt_free( &cert );
-
-    return( ret );
-}
-
-void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key )
-{
-    if( NULL != priv_key )
-        pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert );
-}
-
-int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx,
-                       int mode, size_t *olen,
-                       const unsigned char *input,
-                       unsigned char *output,
-                       size_t output_max_len )
-{
-    size_t input_len, output_len;
-
-    if( NULL == ctx )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
-    if( MBEDTLS_RSA_PRIVATE != mode )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
-    output_len = input_len = ctx->len;
-
-    if( input_len < 16 || input_len > output_max_len )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
-    /* Determine size of output buffer */
-    if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input,
-            input_len, NULL, &output_len ) != CKR_OK )
-    {
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-    }
-
-    if( output_len > output_max_len )
-        return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE );
-
-    if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input,
-            input_len, output, &output_len ) != CKR_OK )
-    {
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-    }
-    *olen = output_len;
-    return( 0 );
-}
-
-int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx,
-                    int mode,
-                    mbedtls_md_type_t md_alg,
-                    unsigned int hashlen,
-                    const unsigned char *hash,
-                    unsigned char *sig )
-{
-    size_t sig_len = 0, asn_len = 0, oid_size = 0;
-    unsigned char *p = sig;
-    const char *oid;
-
-    if( NULL == ctx )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
-    if( MBEDTLS_RSA_PRIVATE != mode )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
-    if( md_alg != MBEDTLS_MD_NONE )
-    {
-        const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
-        if( md_info == NULL )
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
-        if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 )
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
-        hashlen = mbedtls_md_get_size( md_info );
-        asn_len = 10 + oid_size;
-    }
-
-    sig_len = ctx->len;
-    if( hashlen > sig_len || asn_len > sig_len ||
-        hashlen + asn_len > sig_len )
-    {
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-    }
-
-    if( md_alg != MBEDTLS_MD_NONE )
-    {
-        /*
-         * DigestInfo ::= SEQUENCE {
-         *   digestAlgorithm DigestAlgorithmIdentifier,
-         *   digest Digest }
-         *
-         * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
-         *
-         * Digest ::= OCTET STRING
-         */
-        *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
-        *p++ = (unsigned char) ( 0x08 + oid_size + hashlen );
-        *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
-        *p++ = (unsigned char) ( 0x04 + oid_size );
-        *p++ = MBEDTLS_ASN1_OID;
-        *p++ = oid_size & 0xFF;
-        memcpy( p, oid, oid_size );
-        p += oid_size;
-        *p++ = MBEDTLS_ASN1_NULL;
-        *p++ = 0x00;
-        *p++ = MBEDTLS_ASN1_OCTET_STRING;
-        *p++ = hashlen;
-    }
-
-    memcpy( p, hash, hashlen );
-
-    if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig,
-            asn_len + hashlen, sig, &sig_len ) != CKR_OK )
-    {
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-    }
-
-    return( 0 );
-}
-
-#endif /* defined(MBEDTLS_PKCS11_C) */
diff --git a/lib/libmbedtls/mbedtls/library/pkcs12.c b/lib/libmbedtls/mbedtls/library/pkcs12.c
index cacf7db..8521483 100644
--- a/lib/libmbedtls/mbedtls/library/pkcs12.c
+++ b/lib/libmbedtls/mbedtls/library/pkcs12.c
@@ -35,18 +35,24 @@
 
 #include <string.h>
 
-#if defined(MBEDTLS_ARC4_C)
-#include "mbedtls/arc4.h"
+#if !defined(MBEDTLS_MD_C)
+#include "mbedtls/psa_util.h"
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_md_errors,              \
+                                                           psa_generic_status_to_mbedtls)
 #endif
 
 #if defined(MBEDTLS_DES_C)
 #include "mbedtls/des.h"
 #endif
 
+#include "hash_info.h"
+#include "mbedtls/psa_util.h"
+
 #if defined(MBEDTLS_ASN1_PARSE_C)
 
-static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params,
-                                    mbedtls_asn1_buf *salt, int *iterations )
+static int pkcs12_parse_pbe_params(mbedtls_asn1_buf *params,
+                                   mbedtls_asn1_buf *salt, int *iterations)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char **p = &params->p;
@@ -59,118 +65,83 @@
      *  }
      *
      */
-    if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
+    if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
+    }
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret);
+    }
 
     salt->p = *p;
     *p += salt->len;
 
-    if( ( ret = mbedtls_asn1_get_int( p, end, iterations ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_int(p, end, iterations)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret);
+    }
 
-    if( *p != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (*p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
-    return( 0 );
+    return 0;
 }
 
 #define PKCS12_MAX_PWDLEN 128
 
-static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type,
-                                     const unsigned char *pwd,  size_t pwdlen,
-                                     unsigned char *key, size_t keylen,
-                                     unsigned char *iv,  size_t ivlen )
+static int pkcs12_pbe_derive_key_iv(mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type,
+                                    const unsigned char *pwd,  size_t pwdlen,
+                                    unsigned char *key, size_t keylen,
+                                    unsigned char *iv,  size_t ivlen)
 {
     int ret, iterations = 0;
     mbedtls_asn1_buf salt;
     size_t i;
     unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2];
 
-    if( pwdlen > PKCS12_MAX_PWDLEN )
-        return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
+    if (pwdlen > PKCS12_MAX_PWDLEN) {
+        return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;
+    }
 
-    memset( &salt, 0, sizeof(mbedtls_asn1_buf) );
-    memset( &unipwd, 0, sizeof(unipwd) );
+    memset(&salt, 0, sizeof(mbedtls_asn1_buf));
+    memset(&unipwd, 0, sizeof(unipwd));
 
-    if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt,
-                                         &iterations ) ) != 0 )
-        return( ret );
+    if ((ret = pkcs12_parse_pbe_params(pbe_params, &salt,
+                                       &iterations)) != 0) {
+        return ret;
+    }
 
-    for( i = 0; i < pwdlen; i++ )
+    for (i = 0; i < pwdlen; i++) {
         unipwd[i * 2 + 1] = pwd[i];
-
-    if( ( ret = mbedtls_pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2,
-                                   salt.p, salt.len, md_type,
-                                   MBEDTLS_PKCS12_DERIVE_KEY, iterations ) ) != 0 )
-    {
-        return( ret );
     }
 
-    if( iv == NULL || ivlen == 0 )
-        return( 0 );
-
-    if( ( ret = mbedtls_pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2,
-                                   salt.p, salt.len, md_type,
-                                   MBEDTLS_PKCS12_DERIVE_IV, iterations ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_pkcs12_derivation(key, keylen, unipwd, pwdlen * 2 + 2,
+                                         salt.p, salt.len, md_type,
+                                         MBEDTLS_PKCS12_DERIVE_KEY, iterations)) != 0) {
+        return ret;
     }
-    return( 0 );
+
+    if (iv == NULL || ivlen == 0) {
+        return 0;
+    }
+
+    if ((ret = mbedtls_pkcs12_derivation(iv, ivlen, unipwd, pwdlen * 2 + 2,
+                                         salt.p, salt.len, md_type,
+                                         MBEDTLS_PKCS12_DERIVE_IV, iterations)) != 0) {
+        return ret;
+    }
+    return 0;
 }
 
 #undef PKCS12_MAX_PWDLEN
 
-int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode,
-                             const unsigned char *pwd,  size_t pwdlen,
-                             const unsigned char *data, size_t len,
-                             unsigned char *output )
-{
-#if !defined(MBEDTLS_ARC4_C)
-    ((void) pbe_params);
-    ((void) mode);
-    ((void) pwd);
-    ((void) pwdlen);
-    ((void) data);
-    ((void) len);
-    ((void) output);
-    return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
-#else
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char key[16];
-    mbedtls_arc4_context ctx;
-    ((void) mode);
-
-    mbedtls_arc4_init( &ctx );
-
-    if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, MBEDTLS_MD_SHA1,
-                                          pwd, pwdlen,
-                                          key, 16, NULL, 0 ) ) != 0 )
-    {
-        return( ret );
-    }
-
-    mbedtls_arc4_setup( &ctx, key, 16 );
-    if( ( ret = mbedtls_arc4_crypt( &ctx, len, data, output ) ) != 0 )
-        goto exit;
-
-exit:
-    mbedtls_platform_zeroize( key, sizeof( key ) );
-    mbedtls_arc4_free( &ctx );
-
-    return( ret );
-#endif /* MBEDTLS_ARC4_C */
-}
-
-int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode,
-                mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type,
-                const unsigned char *pwd,  size_t pwdlen,
-                const unsigned char *data, size_t len,
-                unsigned char *output )
+int mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode,
+                       mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type,
+                       const unsigned char *pwd,  size_t pwdlen,
+                       const unsigned char *data, size_t len,
+                       unsigned char *output)
 {
     int ret, keylen = 0;
     unsigned char key[32];
@@ -179,73 +150,76 @@
     mbedtls_cipher_context_t cipher_ctx;
     size_t olen = 0;
 
-    if( pwd == NULL && pwdlen != 0 )
-        return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
+    if (pwd == NULL && pwdlen != 0) {
+        return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;
+    }
 
-    cipher_info = mbedtls_cipher_info_from_type( cipher_type );
-    if( cipher_info == NULL )
-        return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
+    cipher_info = mbedtls_cipher_info_from_type(cipher_type);
+    if (cipher_info == NULL) {
+        return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE;
+    }
 
     keylen = cipher_info->key_bitlen / 8;
 
-    if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen,
-                                          key, keylen,
-                                          iv, cipher_info->iv_size ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = pkcs12_pbe_derive_key_iv(pbe_params, md_type, pwd, pwdlen,
+                                        key, keylen,
+                                        iv, cipher_info->iv_size)) != 0) {
+        return ret;
     }
 
-    mbedtls_cipher_init( &cipher_ctx );
+    mbedtls_cipher_init(&cipher_ctx);
 
-    if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 )
-        goto exit;
-
-    if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 )
-        goto exit;
-
-    if( ( ret = mbedtls_cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 )
-        goto exit;
-
-    if( ( ret = mbedtls_cipher_reset( &cipher_ctx ) ) != 0 )
-        goto exit;
-
-    if( ( ret = mbedtls_cipher_update( &cipher_ctx, data, len,
-                                output, &olen ) ) != 0 )
-    {
+    if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0) {
         goto exit;
     }
 
-    if( ( ret = mbedtls_cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 )
+    if ((ret =
+             mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen,
+                                   (mbedtls_operation_t) mode)) != 0) {
+        goto exit;
+    }
+
+    if ((ret = mbedtls_cipher_set_iv(&cipher_ctx, iv, cipher_info->iv_size)) != 0) {
+        goto exit;
+    }
+
+    if ((ret = mbedtls_cipher_reset(&cipher_ctx)) != 0) {
+        goto exit;
+    }
+
+    if ((ret = mbedtls_cipher_update(&cipher_ctx, data, len,
+                                     output, &olen)) != 0) {
+        goto exit;
+    }
+
+    if ((ret = mbedtls_cipher_finish(&cipher_ctx, output + olen, &olen)) != 0) {
         ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH;
+    }
 
 exit:
-    mbedtls_platform_zeroize( key, sizeof( key ) );
-    mbedtls_platform_zeroize( iv,  sizeof( iv  ) );
-    mbedtls_cipher_free( &cipher_ctx );
+    mbedtls_platform_zeroize(key, sizeof(key));
+    mbedtls_platform_zeroize(iv,  sizeof(iv));
+    mbedtls_cipher_free(&cipher_ctx);
 
-    return( ret );
+    return ret;
 }
 
 #endif /* MBEDTLS_ASN1_PARSE_C */
 
-static void pkcs12_fill_buffer( unsigned char *data, size_t data_len,
-                                const unsigned char *filler, size_t fill_len )
+static void pkcs12_fill_buffer(unsigned char *data, size_t data_len,
+                               const unsigned char *filler, size_t fill_len)
 {
     unsigned char *p = data;
     size_t use_len;
 
-    if( filler != NULL && fill_len != 0 )
-    {
-        while( data_len > 0 )
-        {
-            use_len = ( data_len > fill_len ) ? fill_len : data_len;
-            memcpy( p, filler, use_len );
+    if (filler != NULL && fill_len != 0) {
+        while (data_len > 0) {
+            use_len = (data_len > fill_len) ? fill_len : data_len;
+            memcpy(p, filler, use_len);
             p += use_len;
             data_len -= use_len;
         }
-    }
-    else
-    {
+    } else {
         /* If either of the above are not true then clearly there is nothing
          * that this function can do. The function should *not* be called
          * under either of those circumstances, as you could end up with an
@@ -254,17 +228,129 @@
     }
 }
 
-int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen,
-                       const unsigned char *pwd, size_t pwdlen,
-                       const unsigned char *salt, size_t saltlen,
-                       mbedtls_md_type_t md_type, int id, int iterations )
+
+static int calculate_hashes(mbedtls_md_type_t md_type, int iterations,
+                            unsigned char *diversifier, unsigned char *salt_block,
+                            unsigned char *pwd_block, unsigned char *hash_output, int use_salt,
+                            int use_password, size_t hlen, size_t v)
+{
+#if defined(MBEDTLS_MD_C)
+    int ret = -1;
+    size_t i;
+    const mbedtls_md_info_t *md_info;
+    mbedtls_md_context_t md_ctx;
+    md_info = mbedtls_md_info_from_type(md_type);
+    if (md_info == NULL) {
+        return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE;
+    }
+
+    mbedtls_md_init(&md_ctx);
+
+    if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) {
+        return ret;
+    }
+    // Calculate hash( diversifier || salt_block || pwd_block )
+    if ((ret = mbedtls_md_starts(&md_ctx)) != 0) {
+        goto exit;
+    }
+
+    if ((ret = mbedtls_md_update(&md_ctx, diversifier, v)) != 0) {
+        goto exit;
+    }
+
+    if (use_salt != 0) {
+        if ((ret = mbedtls_md_update(&md_ctx, salt_block, v)) != 0) {
+            goto exit;
+        }
+    }
+
+    if (use_password != 0) {
+        if ((ret = mbedtls_md_update(&md_ctx, pwd_block, v)) != 0) {
+            goto exit;
+        }
+    }
+
+    if ((ret = mbedtls_md_finish(&md_ctx, hash_output)) != 0) {
+        goto exit;
+    }
+
+    // Perform remaining ( iterations - 1 ) recursive hash calculations
+    for (i = 1; i < (size_t) iterations; i++) {
+        if ((ret = mbedtls_md(md_info, hash_output, hlen, hash_output))
+            != 0) {
+            goto exit;
+        }
+    }
+
+exit:
+    mbedtls_md_free(&md_ctx);
+    return ret;
+#else
+    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
+    psa_algorithm_t alg = mbedtls_psa_translate_md(md_type);
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t status_abort = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t i, out_len, out_size = PSA_HASH_LENGTH(alg);
+
+    if (alg == PSA_ALG_NONE) {
+        return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE;
+    }
+
+    if ((status = psa_hash_setup(&op, alg)) != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    // Calculate hash( diversifier || salt_block || pwd_block )
+    if ((status = psa_hash_update(&op, diversifier, v)) != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (use_salt != 0) {
+        if ((status = psa_hash_update(&op, salt_block, v)) != PSA_SUCCESS) {
+            goto exit;
+        }
+    }
+
+    if (use_password != 0) {
+        if ((status = psa_hash_update(&op, pwd_block, v)) != PSA_SUCCESS) {
+            goto exit;
+        }
+    }
+
+    if ((status = psa_hash_finish(&op, hash_output, out_size, &out_len))
+        != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    // Perform remaining ( iterations - 1 ) recursive hash calculations
+    for (i = 1; i < (size_t) iterations; i++) {
+        if ((status = psa_hash_compute(alg, hash_output, hlen, hash_output,
+                                       out_size, &out_len)) != PSA_SUCCESS) {
+            goto exit;
+        }
+    }
+
+exit:
+    status_abort = psa_hash_abort(&op);
+    if (status == PSA_SUCCESS) {
+        status = status_abort;
+    }
+    return PSA_TO_MBEDTLS_ERR(status);
+#endif /* !MBEDTLS_MD_C */
+}
+
+
+int mbedtls_pkcs12_derivation(unsigned char *data, size_t datalen,
+                              const unsigned char *pwd, size_t pwdlen,
+                              const unsigned char *salt, size_t saltlen,
+                              mbedtls_md_type_t md_type, int id, int iterations)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned int j;
 
     unsigned char diversifier[128];
-    unsigned char salt_block[128], pwd_block[128], hash_block[128];
-    unsigned char hash_output[MBEDTLS_MD_MAX_SIZE];
+    unsigned char salt_block[128], pwd_block[128], hash_block[128] = { 0 };
+    unsigned char hash_output[MBEDTLS_HASH_MAX_SIZE];
     unsigned char *p;
     unsigned char c;
     int           use_password = 0;
@@ -272,118 +358,84 @@
 
     size_t hlen, use_len, v, i;
 
-    const mbedtls_md_info_t *md_info;
-    mbedtls_md_context_t md_ctx;
-
     // This version only allows max of 64 bytes of password or salt
-    if( datalen > 128 || pwdlen > 64 || saltlen > 64 )
-        return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
-
-    if( pwd == NULL && pwdlen != 0 )
-        return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
-
-    if( salt == NULL && saltlen != 0 )
-        return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
-
-    use_password = ( pwd && pwdlen != 0 );
-    use_salt = ( salt && saltlen != 0 );
-
-    md_info = mbedtls_md_info_from_type( md_type );
-    if( md_info == NULL )
-        return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
-
-    mbedtls_md_init( &md_ctx );
-
-    if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
-        return( ret );
-    hlen = mbedtls_md_get_size( md_info );
-
-    if( hlen <= 32 )
-        v = 64;
-    else
-        v = 128;
-
-    memset( diversifier, (unsigned char) id, v );
-
-    if( use_salt != 0 )
-    {
-        pkcs12_fill_buffer( salt_block, v, salt, saltlen );
+    if (datalen > 128 || pwdlen > 64 || saltlen > 64) {
+        return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;
     }
 
-    if( use_password != 0 )
-    {
-        pkcs12_fill_buffer( pwd_block,  v, pwd,  pwdlen  );
+    if (pwd == NULL && pwdlen != 0) {
+        return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;
+    }
+
+    if (salt == NULL && saltlen != 0) {
+        return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;
+    }
+
+    use_password = (pwd && pwdlen != 0);
+    use_salt = (salt && saltlen != 0);
+
+    hlen = mbedtls_hash_info_get_size(md_type);
+
+    if (hlen <= 32) {
+        v = 64;
+    } else {
+        v = 128;
+    }
+
+    memset(diversifier, (unsigned char) id, v);
+
+    if (use_salt != 0) {
+        pkcs12_fill_buffer(salt_block, v, salt, saltlen);
+    }
+
+    if (use_password != 0) {
+        pkcs12_fill_buffer(pwd_block,  v, pwd,  pwdlen);
     }
 
     p = data;
-    while( datalen > 0 )
-    {
-        // Calculate hash( diversifier || salt_block || pwd_block )
-        if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 )
+    while (datalen > 0) {
+        if (calculate_hashes(md_type, iterations, diversifier, salt_block,
+                             pwd_block, hash_output, use_salt, use_password, hlen,
+                             v) != 0) {
             goto exit;
-
-        if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 )
-            goto exit;
-
-        if( use_salt != 0 )
-        {
-            if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v )) != 0 )
-                goto exit;
         }
 
-        if( use_password != 0)
-        {
-            if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v )) != 0 )
-                goto exit;
-        }
-
-        if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 )
-            goto exit;
-
-        // Perform remaining ( iterations - 1 ) recursive hash calculations
-        for( i = 1; i < (size_t) iterations; i++ )
-        {
-            if( ( ret = mbedtls_md( md_info, hash_output, hlen, hash_output ) ) != 0 )
-                goto exit;
-        }
-
-        use_len = ( datalen > hlen ) ? hlen : datalen;
-        memcpy( p, hash_output, use_len );
+        use_len = (datalen > hlen) ? hlen : datalen;
+        memcpy(p, hash_output, use_len);
         datalen -= use_len;
         p += use_len;
 
-        if( datalen == 0 )
+        if (datalen == 0) {
             break;
+        }
 
         // Concatenating copies of hash_output into hash_block (B)
-        pkcs12_fill_buffer( hash_block, v, hash_output, hlen );
+        pkcs12_fill_buffer(hash_block, v, hash_output, hlen);
 
         // B += 1
-        for( i = v; i > 0; i-- )
-            if( ++hash_block[i - 1] != 0 )
+        for (i = v; i > 0; i--) {
+            if (++hash_block[i - 1] != 0) {
                 break;
-
-        if( use_salt != 0 )
-        {
-            // salt_block += B
-            c = 0;
-            for( i = v; i > 0; i-- )
-            {
-                j = salt_block[i - 1] + hash_block[i - 1] + c;
-                c = MBEDTLS_BYTE_1( j );
-                salt_block[i - 1] = MBEDTLS_BYTE_0( j );
             }
         }
 
-        if( use_password != 0 )
-        {
+        if (use_salt != 0) {
+            // salt_block += B
+            c = 0;
+            for (i = v; i > 0; i--) {
+                j = salt_block[i - 1] + hash_block[i - 1] + c;
+                c = MBEDTLS_BYTE_1(j);
+                salt_block[i - 1] = MBEDTLS_BYTE_0(j);
+            }
+        }
+
+        if (use_password != 0) {
             // pwd_block  += B
             c = 0;
-            for( i = v; i > 0; i-- )
-            {
+            for (i = v; i > 0; i--) {
                 j = pwd_block[i - 1] + hash_block[i - 1] + c;
-                c = MBEDTLS_BYTE_1( j );
-                pwd_block[i - 1] = MBEDTLS_BYTE_0( j );
+                c = MBEDTLS_BYTE_1(j);
+                pwd_block[i - 1] = MBEDTLS_BYTE_0(j);
             }
         }
     }
@@ -391,14 +443,12 @@
     ret = 0;
 
 exit:
-    mbedtls_platform_zeroize( salt_block, sizeof( salt_block ) );
-    mbedtls_platform_zeroize( pwd_block, sizeof( pwd_block ) );
-    mbedtls_platform_zeroize( hash_block, sizeof( hash_block ) );
-    mbedtls_platform_zeroize( hash_output, sizeof( hash_output ) );
+    mbedtls_platform_zeroize(salt_block, sizeof(salt_block));
+    mbedtls_platform_zeroize(pwd_block, sizeof(pwd_block));
+    mbedtls_platform_zeroize(hash_block, sizeof(hash_block));
+    mbedtls_platform_zeroize(hash_output, sizeof(hash_output));
 
-    mbedtls_md_free( &md_ctx );
-
-    return( ret );
+    return ret;
 }
 
 #endif /* MBEDTLS_PKCS12_C */
diff --git a/lib/libmbedtls/mbedtls/library/pkcs5.c b/lib/libmbedtls/mbedtls/library/pkcs5.c
index 2b014d9..f471b63 100644
--- a/lib/libmbedtls/mbedtls/library/pkcs5.c
+++ b/lib/libmbedtls/mbedtls/library/pkcs5.c
@@ -42,26 +42,31 @@
 
 #include <string.h>
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
+
+#include "hash_info.h"
+#include "mbedtls/psa_util.h"
+
+#if !defined(MBEDTLS_MD_C)
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_md_errors,              \
+                                                           psa_generic_status_to_mbedtls)
 #endif
 
 #if defined(MBEDTLS_ASN1_PARSE_C)
-static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params,
-                                      mbedtls_asn1_buf *salt, int *iterations,
-                                      int *keylen, mbedtls_md_type_t *md_type )
+static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params,
+                                     mbedtls_asn1_buf *salt, int *iterations,
+                                     int *keylen, mbedtls_md_type_t *md_type)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_asn1_buf prf_alg_oid;
     unsigned char *p = params->p;
     const unsigned char *end = params->p + params->len;
 
-    if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
+    if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
+    }
     /*
      *  PBKDF2-params ::= SEQUENCE {
      *    salt              OCTET STRING,
@@ -71,45 +76,52 @@
      *  }
      *
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len,
-                                      MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &salt->len,
+                                    MBEDTLS_ASN1_OCTET_STRING)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
+    }
 
     salt->p = p;
     p += salt->len;
 
-    if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
-
-    if( p == end )
-        return( 0 );
-
-    if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 )
-    {
-        if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_int(&p, end, iterations)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
     }
 
-    if( p == end )
-        return( 0 );
+    if (p == end) {
+        return 0;
+    }
 
-    if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_int(&p, end, keylen)) != 0) {
+        if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
+        }
+    }
 
-    if( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 )
-        return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
+    if (p == end) {
+        return 0;
+    }
 
-    if( p != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if ((ret = mbedtls_asn1_get_alg_null(&p, end, &prf_alg_oid)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
+    }
 
-    return( 0 );
+    if (mbedtls_oid_get_md_hmac(&prf_alg_oid, md_type) != 0) {
+        return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
+    }
+
+    if (p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+
+    return 0;
 }
 
-int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode,
-                 const unsigned char *pwd,  size_t pwdlen,
-                 const unsigned char *data, size_t datalen,
-                 unsigned char *output )
+int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode,
+                        const unsigned char *pwd,  size_t pwdlen,
+                        const unsigned char *data, size_t datalen,
+                        unsigned char *output)
 {
     int ret, iterations = 0, keylen = 0;
     unsigned char *p, *end;
@@ -118,9 +130,7 @@
     mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;
     unsigned char key[32], iv[32];
     size_t olen = 0;
-    const mbedtls_md_info_t *md_info;
     const mbedtls_cipher_info_t *cipher_info;
-    mbedtls_md_context_t md_ctx;
     mbedtls_cipher_type_t cipher_alg;
     mbedtls_cipher_context_t cipher_ctx;
 
@@ -133,42 +143,41 @@
      *    encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}
      *  }
      */
-    if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
+    if (pbe_params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
+    }
 
-    if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid,
-                                      &kdf_alg_params ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_alg(&p, end, &kdf_alg_oid,
+                                    &kdf_alg_params)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
+    }
 
     // Only PBKDF2 supported at the moment
     //
-    if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 )
-        return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
-
-    if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params,
-                                           &salt, &iterations, &keylen,
-                                           &md_type ) ) != 0 )
-    {
-        return( ret );
+    if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid) != 0) {
+        return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
     }
 
-    md_info = mbedtls_md_info_from_type( md_type );
-    if( md_info == NULL )
-        return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
-
-    if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid,
-                              &enc_scheme_params ) ) != 0 )
-    {
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
+    if ((ret = pkcs5_parse_pbkdf2_params(&kdf_alg_params,
+                                         &salt, &iterations, &keylen,
+                                         &md_type)) != 0) {
+        return ret;
     }
 
-    if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 )
-        return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
+    if ((ret = mbedtls_asn1_get_alg(&p, end, &enc_scheme_oid,
+                                    &enc_scheme_params)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
+    }
 
-    cipher_info = mbedtls_cipher_info_from_type( cipher_alg );
-    if( cipher_info == NULL )
-        return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
+    if (mbedtls_oid_get_cipher_alg(&enc_scheme_oid, &cipher_alg) != 0) {
+        return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
+    }
+
+    cipher_info = mbedtls_cipher_info_from_type(cipher_alg);
+    if (cipher_info == NULL) {
+        return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
+    }
 
     /*
      * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored
@@ -176,143 +185,300 @@
      */
     keylen = cipher_info->key_bitlen / 8;
 
-    if( enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING ||
-        enc_scheme_params.len != cipher_info->iv_size )
-    {
-        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT );
+    if (enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING ||
+        enc_scheme_params.len != cipher_info->iv_size) {
+        return MBEDTLS_ERR_PKCS5_INVALID_FORMAT;
     }
 
-    mbedtls_md_init( &md_ctx );
-    mbedtls_cipher_init( &cipher_ctx );
+    mbedtls_cipher_init(&cipher_ctx);
 
-    memcpy( iv, enc_scheme_params.p, enc_scheme_params.len );
+    memcpy(iv, enc_scheme_params.p, enc_scheme_params.len);
 
-    if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
-        goto exit;
-
-    if( ( ret = mbedtls_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len,
-                                   iterations, keylen, key ) ) != 0 )
-    {
+    if ((ret = mbedtls_pkcs5_pbkdf2_hmac_ext(md_type, pwd, pwdlen, salt.p,
+                                             salt.len, iterations, keylen,
+                                             key)) != 0) {
         goto exit;
     }
 
-    if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 )
+    if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0) {
         goto exit;
+    }
 
-    if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen,
-                                       (mbedtls_operation_t) mode ) ) != 0 )
+    if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen,
+                                     (mbedtls_operation_t) mode)) != 0) {
         goto exit;
+    }
 
-    if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len,
-                              data, datalen, output, &olen ) ) != 0 )
+    if ((ret = mbedtls_cipher_crypt(&cipher_ctx, iv, enc_scheme_params.len,
+                                    data, datalen, output, &olen)) != 0) {
         ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH;
+    }
 
 exit:
-    mbedtls_md_free( &md_ctx );
-    mbedtls_cipher_free( &cipher_ctx );
+    mbedtls_cipher_free(&cipher_ctx);
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_ASN1_PARSE_C */
 
-int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx,
-                       const unsigned char *password,
-                       size_t plen, const unsigned char *salt, size_t slen,
-                       unsigned int iteration_count,
-                       uint32_t key_length, unsigned char *output )
+#if defined(MBEDTLS_MD_C)
+static int pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx,
+                             const unsigned char *password,
+                             size_t plen, const unsigned char *salt, size_t slen,
+                             unsigned int iteration_count,
+                             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];
-    unsigned char md_size = mbedtls_md_get_size( ctx->md_info );
+    unsigned char md_size = mbedtls_md_get_size(ctx->md_info);
     size_t use_len;
     unsigned char *out_p = output;
     unsigned char counter[4];
 
-    memset( counter, 0, 4 );
+    memset(counter, 0, 4);
     counter[3] = 1;
 
 #if UINT_MAX > 0xFFFFFFFF
-    if( iteration_count > 0xFFFFFFFF )
-        return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA );
+    if (iteration_count > 0xFFFFFFFF) {
+        return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA;
+    }
 #endif
 
-    if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 )
-        return( ret );
-    while( key_length )
-    {
+    if ((ret = mbedtls_md_hmac_starts(ctx, password, plen)) != 0) {
+        return ret;
+    }
+    while (key_length) {
         // U1 ends up in work
         //
-        if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 )
+        if ((ret = mbedtls_md_hmac_update(ctx, salt, slen)) != 0) {
             goto cleanup;
+        }
 
-        if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 )
+        if ((ret = mbedtls_md_hmac_update(ctx, counter, 4)) != 0) {
             goto cleanup;
+        }
 
-        if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 )
+        if ((ret = mbedtls_md_hmac_finish(ctx, work)) != 0) {
             goto cleanup;
+        }
 
-        if( ( ret = mbedtls_md_hmac_reset( ctx ) ) != 0 )
+        if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) {
             goto cleanup;
+        }
 
-        memcpy( md1, work, md_size );
+        memcpy(md1, work, md_size);
 
-        for( i = 1; i < iteration_count; i++ )
-        {
+        for (i = 1; i < iteration_count; i++) {
             // U2 ends up in md1
             //
-            if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 )
+            if ((ret = mbedtls_md_hmac_update(ctx, md1, md_size)) != 0) {
                 goto cleanup;
+            }
 
-            if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 )
+            if ((ret = mbedtls_md_hmac_finish(ctx, md1)) != 0) {
                 goto cleanup;
+            }
 
-            if( ( ret = mbedtls_md_hmac_reset( ctx ) ) != 0 )
+            if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) {
                 goto cleanup;
+            }
 
             // 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;
-        memcpy( out_p, work, use_len );
+        use_len = (key_length < md_size) ? key_length : md_size;
+        memcpy(out_p, work, use_len);
 
         key_length -= (uint32_t) use_len;
         out_p += use_len;
 
-        for( i = 4; i > 0; i-- )
-            if( ++counter[i - 1] != 0 )
+        for (i = 4; i > 0; i--) {
+            if (++counter[i - 1] != 0) {
                 break;
+            }
+        }
     }
 
 cleanup:
     /* Zeroise buffers to clear sensitive data from memory. */
-    mbedtls_platform_zeroize( work, MBEDTLS_MD_MAX_SIZE );
-    mbedtls_platform_zeroize( md1, MBEDTLS_MD_MAX_SIZE );
+    mbedtls_platform_zeroize(work, MBEDTLS_MD_MAX_SIZE);
+    mbedtls_platform_zeroize(md1, MBEDTLS_MD_MAX_SIZE);
 
-    return( ret );
+    return ret;
+}
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+int mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx,
+                              const unsigned char *password,
+                              size_t plen, const unsigned char *salt, size_t slen,
+                              unsigned int iteration_count,
+                              uint32_t key_length, unsigned char *output)
+{
+    return pkcs5_pbkdf2_hmac(ctx, password, plen, salt, slen, iteration_count,
+                             key_length, output);
+}
+#endif
+#endif /* MBEDTLS_MD_C */
+
+int mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg,
+                                  const unsigned char *password,
+                                  size_t plen, const unsigned char *salt, size_t slen,
+                                  unsigned int iteration_count,
+                                  uint32_t key_length, unsigned char *output)
+{
+#if defined(MBEDTLS_MD_C)
+    mbedtls_md_context_t md_ctx;
+    const mbedtls_md_info_t *md_info = NULL;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    md_info = mbedtls_md_info_from_type(md_alg);
+    if (md_info == NULL) {
+        return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
+    }
+
+    mbedtls_md_init(&md_ctx);
+
+    if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) {
+        goto exit;
+    }
+    ret = pkcs5_pbkdf2_hmac(&md_ctx, password, plen, salt, slen,
+                            iteration_count, key_length, output);
+exit:
+    mbedtls_md_free(&md_ctx);
+    return ret;
+#else
+    unsigned int i;
+    unsigned char md1[PSA_HASH_MAX_SIZE];
+    unsigned char work[PSA_HASH_MAX_SIZE];
+    const unsigned char md_size = mbedtls_hash_info_get_size(md_alg);
+    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t status_destruction = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t use_len, out_len;
+    unsigned char *out_p = output;
+    unsigned char counter[4];
+    mbedtls_svc_key_id_t psa_hmac_key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    const psa_algorithm_t alg = PSA_ALG_HMAC(mbedtls_hash_info_psa_from_md(md_alg));
+    const size_t out_size = PSA_MAC_LENGTH(PSA_KEY_TYPE_HMAC, 0, alg);
+
+    memset(counter, 0, sizeof(counter));
+    counter[3] = 1;
+
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
+    psa_set_key_algorithm(&attributes,  alg);
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
+
+    if (key_length == 0) {
+        return 0;
+    }
+    if ((status = psa_import_key(&attributes,
+                                 password, plen,
+                                 &psa_hmac_key)) != PSA_SUCCESS) {
+        return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA;
+    }
+
+#if UINT_MAX > 0xFFFFFFFF
+    if (iteration_count > 0xFFFFFFFF) {
+        return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA;
+    }
+#endif
+
+    while (key_length) {
+        status = psa_mac_sign_setup(&operation, psa_hmac_key,
+                                    PSA_ALG_HMAC(alg));
+        if (status != PSA_SUCCESS) {
+            goto cleanup;
+        }
+        // U1 ends up in work
+        if ((status = psa_mac_update(&operation, salt, slen)) != PSA_SUCCESS) {
+            goto cleanup;
+        }
+
+        if ((status = psa_mac_update(&operation, counter, sizeof(counter))) != PSA_SUCCESS) {
+            goto cleanup;
+        }
+
+        if ((status = psa_mac_sign_finish(&operation, work, out_size, &out_len))
+            != PSA_SUCCESS) {
+            goto cleanup;
+        }
+
+        memcpy(md1, work, out_len);
+
+        for (i = 1; i < iteration_count; i++) {
+            // U2 ends up in md1
+            //
+            status = psa_mac_sign_setup(&operation, psa_hmac_key,
+                                        PSA_ALG_HMAC(alg));
+            if (status != PSA_SUCCESS) {
+                goto cleanup;
+            }
+            if ((status = psa_mac_update(&operation, md1, md_size)) != PSA_SUCCESS) {
+                goto cleanup;
+            }
+            if ((status =
+                     psa_mac_sign_finish(&operation, md1, out_size, &out_len)) != PSA_SUCCESS) {
+                goto cleanup;
+            }
+
+            // U1 xor U2
+            //
+            mbedtls_xor(work, work, md1, md_size);
+        }
+
+        use_len = (key_length < md_size) ? key_length : md_size;
+        memcpy(out_p, work, use_len);
+
+        key_length -= (uint32_t) use_len;
+        out_p += use_len;
+
+        for (i = 4; i > 0; i--) {
+            if (++counter[i - 1] != 0) {
+                break;
+            }
+        }
+    }
+
+cleanup:
+    /* Zeroise buffers to clear sensitive data from memory. */
+    mbedtls_platform_zeroize(work, PSA_HASH_MAX_SIZE);
+    mbedtls_platform_zeroize(md1, PSA_HASH_MAX_SIZE);
+    status_destruction = psa_destroy_key(psa_hmac_key);
+    if (status == PSA_SUCCESS && status_destruction != PSA_SUCCESS) {
+        status = status_destruction;
+    }
+    status_destruction = psa_mac_abort(&operation);
+    if (status == PSA_SUCCESS && status_destruction != PSA_SUCCESS) {
+        status = status_destruction;
+    }
+
+    return PSA_TO_MBEDTLS_ERR(status);
+#endif /* !MBEDTLS_MD_C */
 }
 
 #if defined(MBEDTLS_SELF_TEST)
 
-#if !defined(MBEDTLS_SHA1_C)
-int mbedtls_pkcs5_self_test( int verbose )
+#if !defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA)
+int mbedtls_pkcs5_self_test(int verbose)
 {
-    if( verbose != 0 )
-        mbedtls_printf( "  PBKDF2 (SHA1): skipped\n\n" );
+    if (verbose != 0) {
+        mbedtls_printf("  PBKDF2 (SHA1): skipped\n\n");
+    }
 
-    return( 0 );
+    return 0;
 }
 #else
 
 #define MAX_TESTS   6
 
 static const size_t plen_test_data[MAX_TESTS] =
-    { 8, 8, 8, 24, 9 };
+{ 8, 8, 8, 24, 9 };
 
 static const unsigned char password_test_data[MAX_TESTS][32] =
 {
@@ -324,7 +490,7 @@
 };
 
 static const size_t slen_test_data[MAX_TESTS] =
-    { 4, 4, 4, 36, 5 };
+{ 4, 4, 4, 36, 5 };
 
 static const unsigned char salt_test_data[MAX_TESTS][40] =
 {
@@ -336,10 +502,10 @@
 };
 
 static const uint32_t it_cnt_test_data[MAX_TESTS] =
-    { 1, 2, 4096, 4096, 4096 };
+{ 1, 2, 4096, 4096, 4096 };
 
 static const uint32_t key_len_test_data[MAX_TESTS] =
-    { 20, 20, 20, 25, 16 };
+{ 20, 20, 20, 25, 16 };
 
 static const unsigned char result_key_test_data[MAX_TESTS][32] =
 {
@@ -360,60 +526,43 @@
       0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 },
 };
 
-int mbedtls_pkcs5_self_test( int verbose )
+int mbedtls_pkcs5_self_test(int verbose)
 {
-    mbedtls_md_context_t sha1_ctx;
-    const mbedtls_md_info_t *info_sha1;
     int ret, i;
     unsigned char key[64];
 
-    mbedtls_md_init( &sha1_ctx );
+    for (i = 0; i < MAX_TESTS; i++) {
+        if (verbose != 0) {
+            mbedtls_printf("  PBKDF2 (SHA1) #%d: ", i);
+        }
 
-    info_sha1 = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
-    if( info_sha1 == NULL )
-    {
-        ret = 1;
-        goto exit;
-    }
-
-    if( ( ret = mbedtls_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 )
-    {
-        ret = 1;
-        goto exit;
-    }
-
-    for( i = 0; i < MAX_TESTS; i++ )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "  PBKDF2 (SHA1) #%d: ", i );
-
-        ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password_test_data[i],
-                                         plen_test_data[i], salt_test_data[i],
-                                         slen_test_data[i], it_cnt_test_data[i],
-                                         key_len_test_data[i], key );
-        if( ret != 0 ||
-            memcmp( result_key_test_data[i], key, key_len_test_data[i] ) != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "failed\n" );
+        ret = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, password_test_data[i],
+                                            plen_test_data[i], salt_test_data[i],
+                                            slen_test_data[i], it_cnt_test_data[i],
+                                            key_len_test_data[i], key);
+        if (ret != 0 ||
+            memcmp(result_key_test_data[i], key, key_len_test_data[i]) != 0) {
+            if (verbose != 0) {
+                mbedtls_printf("failed\n");
+            }
 
             ret = 1;
             goto exit;
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
 exit:
-    mbedtls_md_free( &sha1_ctx );
-
-    return( ret );
+    return ret;
 }
-#endif /* MBEDTLS_SHA1_C */
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA */
 
 #endif /* MBEDTLS_SELF_TEST */
 
diff --git a/lib/libmbedtls/mbedtls/library/pkcs7.c b/lib/libmbedtls/mbedtls/library/pkcs7.c
new file mode 100644
index 0000000..cf05afd
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/pkcs7.c
@@ -0,0 +1,785 @@
+/*
+ *  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.
+ */
+#include "common.h"
+
+#include "mbedtls/build_info.h"
+#if defined(MBEDTLS_PKCS7_C)
+#include "mbedtls/pkcs7.h"
+#include "mbedtls/x509.h"
+#include "mbedtls/asn1.h"
+#include "mbedtls/x509_crt.h"
+#include "mbedtls/x509_crl.h"
+#include "mbedtls/oid.h"
+#include "mbedtls/error.h"
+
+#if defined(MBEDTLS_FS_IO)
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+#include "mbedtls/platform.h"
+#include "mbedtls/platform_util.h"
+
+#if defined(MBEDTLS_HAVE_TIME)
+#include "mbedtls/platform_time.h"
+#endif
+#if defined(MBEDTLS_HAVE_TIME_DATE)
+#include <time.h>
+#endif
+
+/**
+ * Initializes the mbedtls_pkcs7 structure.
+ */
+void mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7)
+{
+    memset(pkcs7, 0, sizeof(*pkcs7));
+}
+
+static int pkcs7_get_next_content_len(unsigned char **p, unsigned char *end,
+                                      size_t *len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_CONSTRUCTED
+                               | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
+    if (ret != 0) {
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
+    } else if ((size_t) (end - *p) != *len) {
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO,
+                                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+
+    return ret;
+}
+
+/**
+ * version Version
+ * Version ::= INTEGER
+ **/
+static int pkcs7_get_version(unsigned char **p, unsigned char *end, int *ver)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    ret = mbedtls_asn1_get_int(p, end, ver);
+    if (ret != 0) {
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_VERSION, ret);
+    }
+
+    /* If version != 1, return invalid version */
+    if (*ver != MBEDTLS_PKCS7_SUPPORTED_VERSION) {
+        ret = MBEDTLS_ERR_PKCS7_INVALID_VERSION;
+    }
+
+    return ret;
+}
+
+/**
+ * ContentInfo ::= SEQUENCE {
+ *      contentType ContentType,
+ *      content
+ *              [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+ **/
+static int pkcs7_get_content_info_type(unsigned char **p, unsigned char *end,
+                                       unsigned char **seq_end,
+                                       mbedtls_pkcs7_buf *pkcs7)
+{
+    size_t len = 0;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *start = *p;
+
+    ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
+                               | MBEDTLS_ASN1_SEQUENCE);
+    if (ret != 0) {
+        *p = start;
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
+    }
+    *seq_end = *p + len;
+    ret = mbedtls_asn1_get_tag(p, *seq_end, &len, MBEDTLS_ASN1_OID);
+    if (ret != 0) {
+        *p = start;
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
+    }
+
+    pkcs7->tag = MBEDTLS_ASN1_OID;
+    pkcs7->len = len;
+    pkcs7->p = *p;
+    *p += len;
+
+    return ret;
+}
+
+/**
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * This is from x509.h
+ **/
+static int pkcs7_get_digest_algorithm(unsigned char **p, unsigned char *end,
+                                      mbedtls_x509_buf *alg)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) {
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
+    }
+
+    return ret;
+}
+
+/**
+ * DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier
+ **/
+static int pkcs7_get_digest_algorithm_set(unsigned char **p,
+                                          unsigned char *end,
+                                          mbedtls_x509_buf *alg)
+{
+    size_t len = 0;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
+                               | MBEDTLS_ASN1_SET);
+    if (ret != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
+    }
+
+    end = *p + len;
+
+    ret = mbedtls_asn1_get_alg_null(p, end, alg);
+    if (ret != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
+    }
+
+    /** For now, it assumes there is only one digest algorithm specified **/
+    if (*p != end) {
+        return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
+    }
+
+    return 0;
+}
+
+/**
+ * certificates :: SET OF ExtendedCertificateOrCertificate,
+ * ExtendedCertificateOrCertificate ::= CHOICE {
+ *      certificate Certificate -- x509,
+ *      extendedCertificate[0] IMPLICIT ExtendedCertificate }
+ * Return number of certificates added to the signed data,
+ * 0 or higher is valid.
+ * Return negative error code for failure.
+ **/
+static int pkcs7_get_certificates(unsigned char **p, unsigned char *end,
+                                  mbedtls_x509_crt *certs)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t len1 = 0;
+    size_t len2 = 0;
+    unsigned char *end_set, *end_cert, *start;
+
+    ret = mbedtls_asn1_get_tag(p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED
+                               | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
+    if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
+        return 0;
+    }
+    if (ret != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
+    }
+    start = *p;
+    end_set = *p + len1;
+
+    ret = mbedtls_asn1_get_tag(p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED
+                               | MBEDTLS_ASN1_SEQUENCE);
+    if (ret != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CERT, ret);
+    }
+
+    end_cert = *p + len2;
+
+    /*
+     * This is to verify that there is only one signer certificate. It seems it is
+     * not easy to differentiate between the chain vs different signer's certificate.
+     * So, we support only the root certificate and the single signer.
+     * The behaviour would be improved with addition of multiple signer support.
+     */
+    if (end_cert != end_set) {
+        return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
+    }
+
+    if ((ret = mbedtls_x509_crt_parse_der(certs, start, len1)) < 0) {
+        return MBEDTLS_ERR_PKCS7_INVALID_CERT;
+    }
+
+    *p = end_cert;
+
+    /*
+     * Since in this version we strictly support single certificate, and reaching
+     * here implies we have parsed successfully, we return 1.
+     */
+    return 1;
+}
+
+/**
+ * EncryptedDigest ::= OCTET STRING
+ **/
+static int pkcs7_get_signature(unsigned char **p, unsigned char *end,
+                               mbedtls_pkcs7_buf *signature)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t len = 0;
+
+    ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
+    if (ret != 0) {
+        return ret;
+    }
+
+    signature->tag = MBEDTLS_ASN1_OCTET_STRING;
+    signature->len = len;
+    signature->p = *p;
+
+    *p = *p + len;
+
+    return 0;
+}
+
+static void pkcs7_free_signer_info(mbedtls_pkcs7_signer_info *signer)
+{
+    mbedtls_x509_name *name_cur;
+    mbedtls_x509_name *name_prv;
+
+    if (signer == NULL) {
+        return;
+    }
+
+    name_cur = signer->issuer.next;
+    while (name_cur != NULL) {
+        name_prv = name_cur;
+        name_cur = name_cur->next;
+        mbedtls_free(name_prv);
+    }
+    signer->issuer.next = NULL;
+}
+
+/**
+ * SignerInfo ::= SEQUENCE {
+ *      version Version;
+ *      issuerAndSerialNumber   IssuerAndSerialNumber,
+ *      digestAlgorithm DigestAlgorithmIdentifier,
+ *      authenticatedAttributes
+ *              [0] IMPLICIT Attributes OPTIONAL,
+ *      digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+ *      encryptedDigest EncryptedDigest,
+ *      unauthenticatedAttributes
+ *              [1] IMPLICIT Attributes OPTIONAL,
+ * Returns 0 if the signerInfo is valid.
+ * Return negative error code for failure.
+ * Structure must not contain vales for authenticatedAttributes
+ * and unauthenticatedAttributes.
+ **/
+static int pkcs7_get_signer_info(unsigned char **p, unsigned char *end,
+                                 mbedtls_pkcs7_signer_info *signer,
+                                 mbedtls_x509_buf *alg)
+{
+    unsigned char *end_signer, *end_issuer_and_sn;
+    int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t len = 0;
+
+    asn1_ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
+                                    | MBEDTLS_ASN1_SEQUENCE);
+    if (asn1_ret != 0) {
+        goto out;
+    }
+
+    end_signer = *p + len;
+
+    ret = pkcs7_get_version(p, end_signer, &signer->version);
+    if (ret != 0) {
+        goto out;
+    }
+
+    asn1_ret = mbedtls_asn1_get_tag(p, end_signer, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+    if (asn1_ret != 0) {
+        goto out;
+    }
+
+    end_issuer_and_sn = *p + len;
+    /* Parsing IssuerAndSerialNumber */
+    signer->issuer_raw.p = *p;
+
+    asn1_ret = mbedtls_asn1_get_tag(p, end_issuer_and_sn, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+    if (asn1_ret != 0) {
+        goto out;
+    }
+
+    ret  = mbedtls_x509_get_name(p, *p + len, &signer->issuer);
+    if (ret != 0) {
+        goto out;
+    }
+
+    signer->issuer_raw.len =  *p - signer->issuer_raw.p;
+
+    ret = mbedtls_x509_get_serial(p, end_issuer_and_sn, &signer->serial);
+    if (ret != 0) {
+        goto out;
+    }
+
+    /* ensure no extra or missing bytes */
+    if (*p != end_issuer_and_sn) {
+        ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
+        goto out;
+    }
+
+    ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->alg_identifier);
+    if (ret != 0) {
+        goto out;
+    }
+
+    /* Check that the digest algorithm used matches the one provided earlier */
+    if (signer->alg_identifier.tag != alg->tag ||
+        signer->alg_identifier.len != alg->len ||
+        memcmp(signer->alg_identifier.p, alg->p, alg->len) != 0) {
+        ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
+        goto out;
+    }
+
+    /* Assume authenticatedAttributes is nonexistent */
+    ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->sig_alg_identifier);
+    if (ret != 0) {
+        goto out;
+    }
+
+    ret = pkcs7_get_signature(p, end_signer, &signer->sig);
+    if (ret != 0) {
+        goto out;
+    }
+
+    /* Do not permit any unauthenticated attributes */
+    if (*p != end_signer) {
+        ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
+    }
+
+out:
+    if (asn1_ret != 0 || ret != 0) {
+        pkcs7_free_signer_info(signer);
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO,
+                                asn1_ret);
+    }
+
+    return ret;
+}
+
+/**
+ * SignerInfos ::= SET of SignerInfo
+ * Return number of signers added to the signed data,
+ * 0 or higher is valid.
+ * Return negative error code for failure.
+ **/
+static int pkcs7_get_signers_info_set(unsigned char **p, unsigned char *end,
+                                      mbedtls_pkcs7_signer_info *signers_set,
+                                      mbedtls_x509_buf *digest_alg)
+{
+    unsigned char *end_set;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    int count = 0;
+    size_t len = 0;
+
+    ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
+                               | MBEDTLS_ASN1_SET);
+    if (ret != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret);
+    }
+
+    /* Detect zero signers */
+    if (len == 0) {
+        return 0;
+    }
+
+    end_set = *p + len;
+
+    ret = pkcs7_get_signer_info(p, end_set, signers_set, digest_alg);
+    if (ret != 0) {
+        return ret;
+    }
+    count++;
+
+    mbedtls_pkcs7_signer_info *prev = signers_set;
+    while (*p != end_set) {
+        mbedtls_pkcs7_signer_info *signer =
+            mbedtls_calloc(1, sizeof(mbedtls_pkcs7_signer_info));
+        if (!signer) {
+            ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
+            goto cleanup;
+        }
+
+        ret = pkcs7_get_signer_info(p, end_set, signer, digest_alg);
+        if (ret != 0) {
+            mbedtls_free(signer);
+            goto cleanup;
+        }
+        prev->next = signer;
+        prev = signer;
+        count++;
+    }
+
+    return count;
+
+cleanup:
+    pkcs7_free_signer_info(signers_set);
+    mbedtls_pkcs7_signer_info *signer = signers_set->next;
+    while (signer != NULL) {
+        prev = signer;
+        signer = signer->next;
+        pkcs7_free_signer_info(prev);
+        mbedtls_free(prev);
+    }
+    signers_set->next = NULL;
+    return ret;
+}
+
+/**
+ * SignedData ::= SEQUENCE {
+ *      version Version,
+ *      digestAlgorithms DigestAlgorithmIdentifiers,
+ *      contentInfo ContentInfo,
+ *      certificates
+ *              [0] IMPLICIT ExtendedCertificatesAndCertificates
+ *                  OPTIONAL,
+ *      crls
+ *              [0] IMPLICIT CertificateRevocationLists OPTIONAL,
+ *      signerInfos SignerInfos }
+ */
+static int pkcs7_get_signed_data(unsigned char *buf, size_t buflen,
+                                 mbedtls_pkcs7_signed_data *signed_data)
+{
+    unsigned char *p = buf;
+    unsigned char *end = buf + buflen;
+    unsigned char *end_content_info = NULL;
+    size_t len = 0;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_md_type_t md_alg;
+
+    ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
+                               | MBEDTLS_ASN1_SEQUENCE);
+    if (ret != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
+    }
+
+    if (p + len != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+
+    /* Get version of signed data */
+    ret = pkcs7_get_version(&p, end, &signed_data->version);
+    if (ret != 0) {
+        return ret;
+    }
+
+    /* Get digest algorithm */
+    ret = pkcs7_get_digest_algorithm_set(&p, end,
+                                         &signed_data->digest_alg_identifiers);
+    if (ret != 0) {
+        return ret;
+    }
+
+    ret = mbedtls_oid_get_md_alg(&signed_data->digest_alg_identifiers, &md_alg);
+    if (ret != 0) {
+        return MBEDTLS_ERR_PKCS7_INVALID_ALG;
+    }
+
+    mbedtls_pkcs7_buf content_type;
+    memset(&content_type, 0, sizeof(content_type));
+    ret = pkcs7_get_content_info_type(&p, end, &end_content_info, &content_type);
+    if (ret != 0) {
+        return ret;
+    }
+    if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_DATA, &content_type)) {
+        return MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO;
+    }
+
+    if (p != end_content_info) {
+        /* Determine if valid content is present */
+        ret = mbedtls_asn1_get_tag(&p,
+                                   end_content_info,
+                                   &len,
+                                   MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
+        if (ret != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
+        }
+        p += len;
+        if (p != end_content_info) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
+        }
+        /* Valid content is present - this is not supported */
+        return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
+    }
+
+    /* Look for certificates, there may or may not be any */
+    mbedtls_x509_crt_init(&signed_data->certs);
+    ret = pkcs7_get_certificates(&p, end, &signed_data->certs);
+    if (ret < 0) {
+        return ret;
+    }
+
+    signed_data->no_of_certs = ret;
+
+    /*
+     * Currently CRLs are not supported. If CRL exist, the parsing will fail
+     * at next step of getting signers info and return error as invalid
+     * signer info.
+     */
+
+    signed_data->no_of_crls = 0;
+
+    /* Get signers info */
+    ret = pkcs7_get_signers_info_set(&p,
+                                     end,
+                                     &signed_data->signers,
+                                     &signed_data->digest_alg_identifiers);
+    if (ret < 0) {
+        return ret;
+    }
+
+    signed_data->no_of_signers = ret;
+
+    /* Don't permit trailing data */
+    if (p != end) {
+        return MBEDTLS_ERR_PKCS7_INVALID_FORMAT;
+    }
+
+    return 0;
+}
+
+int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
+                            const size_t buflen)
+{
+    unsigned char *p;
+    unsigned char *end;
+    size_t len = 0;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if (pkcs7 == NULL) {
+        return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
+    }
+
+    /* make an internal copy of the buffer for parsing */
+    pkcs7->raw.p = p = mbedtls_calloc(1, buflen);
+    if (pkcs7->raw.p == NULL) {
+        ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
+        goto out;
+    }
+    memcpy(p, buf, buflen);
+    pkcs7->raw.len = buflen;
+    end = p + buflen;
+
+    ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
+                               | MBEDTLS_ASN1_SEQUENCE);
+    if (ret != 0) {
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
+        goto out;
+    }
+
+    if ((size_t) (end - p) != len) {
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT,
+                                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+        goto out;
+    }
+
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {
+        if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
+            goto out;
+        }
+        p = pkcs7->raw.p;
+        len = buflen;
+        goto try_data;
+    }
+
+    if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_DATA, p, len)) {
+        /* OID is not MBEDTLS_OID_PKCS7_SIGNED_DATA, which is the only supported feature */
+        if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DATA, p, len)
+            || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, p, len)
+            || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENVELOPED_DATA, p, len)
+            || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, p, len)
+            || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DIGESTED_DATA, p, len)) {
+            /* OID is valid according to the spec, but unsupported */
+            ret =  MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
+        } else {
+            /* OID is invalid according to the spec */
+            ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
+        }
+        goto out;
+    }
+
+    p += len;
+
+    ret = pkcs7_get_next_content_len(&p, end, &len);
+    if (ret != 0) {
+        goto out;
+    }
+
+    /* ensure no extra/missing data */
+    if (p + len != end) {
+        ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
+        goto out;
+    }
+
+try_data:
+    ret = pkcs7_get_signed_data(p, len, &pkcs7->signed_data);
+    if (ret != 0) {
+        goto out;
+    }
+
+    ret = MBEDTLS_PKCS7_SIGNED_DATA;
+
+out:
+    if (ret < 0) {
+        mbedtls_pkcs7_free(pkcs7);
+    }
+
+    return ret;
+}
+
+static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7,
+                                             const mbedtls_x509_crt *cert,
+                                             const unsigned char *data,
+                                             size_t datalen,
+                                             const int is_data_hash)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *hash;
+    mbedtls_pk_context pk_cxt = cert->pk;
+    const mbedtls_md_info_t *md_info;
+    mbedtls_md_type_t md_alg;
+    mbedtls_pkcs7_signer_info *signer;
+
+    if (pkcs7->signed_data.no_of_signers == 0) {
+        return MBEDTLS_ERR_PKCS7_INVALID_CERT;
+    }
+
+    if (mbedtls_x509_time_is_past(&cert->valid_to) ||
+        mbedtls_x509_time_is_future(&cert->valid_from)) {
+        return MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID;
+    }
+
+    ret = mbedtls_oid_get_md_alg(&pkcs7->signed_data.digest_alg_identifiers, &md_alg);
+    if (ret != 0) {
+        return ret;
+    }
+
+    md_info = mbedtls_md_info_from_type(md_alg);
+    if (md_info == NULL) {
+        return MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
+    }
+
+    hash = mbedtls_calloc(mbedtls_md_get_size(md_info), 1);
+    if (hash == NULL) {
+        return MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
+    }
+
+    /* BEGIN must free hash before jumping out */
+    if (is_data_hash) {
+        if (datalen != mbedtls_md_get_size(md_info)) {
+            ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
+        } else {
+            memcpy(hash, data, datalen);
+        }
+    } else {
+        ret = mbedtls_md(md_info, data, datalen, hash);
+    }
+    if (ret != 0) {
+        mbedtls_free(hash);
+        return MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
+    }
+
+    /* assume failure */
+    ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
+
+    /*
+     * Potential TODOs
+     * Currently we iterate over all signers and return success if any of them
+     * verify.
+     *
+     * However, we could make this better by checking against the certificate's
+     * identification and SignerIdentifier fields first. That would also allow
+     * us to distinguish between 'no signature for key' and 'signature for key
+     * failed to validate'.
+     */
+    for (signer = &pkcs7->signed_data.signers; signer; signer = signer->next) {
+        ret = mbedtls_pk_verify(&pk_cxt, md_alg, hash,
+                                mbedtls_md_get_size(md_info),
+                                signer->sig.p, signer->sig.len);
+
+        if (ret == 0) {
+            break;
+        }
+    }
+
+    mbedtls_free(hash);
+    /* END must free hash before jumping out */
+    return ret;
+}
+
+int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7,
+                                     const mbedtls_x509_crt *cert,
+                                     const unsigned char *data,
+                                     size_t datalen)
+{
+    if (data == NULL) {
+        return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
+    }
+    return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, data, datalen, 0);
+}
+
+int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7,
+                                     const mbedtls_x509_crt *cert,
+                                     const unsigned char *hash,
+                                     size_t hashlen)
+{
+    if (hash == NULL) {
+        return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
+    }
+    return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, hash, hashlen, 1);
+}
+
+/*
+ * Unallocate all pkcs7 data
+ */
+void mbedtls_pkcs7_free(mbedtls_pkcs7 *pkcs7)
+{
+    mbedtls_pkcs7_signer_info *signer_cur;
+    mbedtls_pkcs7_signer_info *signer_prev;
+
+    if (pkcs7 == NULL || pkcs7->raw.p == NULL) {
+        return;
+    }
+
+    mbedtls_free(pkcs7->raw.p);
+
+    mbedtls_x509_crt_free(&pkcs7->signed_data.certs);
+    mbedtls_x509_crl_free(&pkcs7->signed_data.crl);
+
+    signer_cur = pkcs7->signed_data.signers.next;
+    pkcs7_free_signer_info(&pkcs7->signed_data.signers);
+    while (signer_cur != NULL) {
+        signer_prev = signer_cur;
+        signer_cur = signer_prev->next;
+        pkcs7_free_signer_info(signer_prev);
+        mbedtls_free(signer_prev);
+    }
+
+    pkcs7->raw.p = NULL;
+}
+
+#endif
diff --git a/lib/libmbedtls/mbedtls/library/pkparse.c b/lib/libmbedtls/mbedtls/library/pkparse.c
index ea5c6b6..ccca692 100644
--- a/lib/libmbedtls/mbedtls/library/pkparse.c
+++ b/lib/libmbedtls/mbedtls/library/pkparse.c
@@ -48,19 +48,7 @@
 #include "mbedtls/pkcs12.h"
 #endif
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free       free
-#endif
-
-/* Parameter validation macros based on platform_util.h */
-#define PK_VALIDATE_RET( cond )    \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA )
-#define PK_VALIDATE( cond )        \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
 
 #if defined(MBEDTLS_FS_IO)
 /*
@@ -70,104 +58,100 @@
  * A terminating null byte is always appended. It is included in the announced
  * length only if the data looks like it is PEM encoded.
  */
-int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n )
+int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n)
 {
     FILE *f;
     long size;
 
-    PK_VALIDATE_RET( path != NULL );
-    PK_VALIDATE_RET( buf != NULL );
-    PK_VALIDATE_RET( n != NULL );
-
-    if( ( f = fopen( path, "rb" ) ) == NULL )
-        return( MBEDTLS_ERR_PK_FILE_IO_ERROR );
-
-    fseek( f, 0, SEEK_END );
-    if( ( size = ftell( f ) ) == -1 )
-    {
-        fclose( f );
-        return( MBEDTLS_ERR_PK_FILE_IO_ERROR );
+    if ((f = fopen(path, "rb")) == NULL) {
+        return MBEDTLS_ERR_PK_FILE_IO_ERROR;
     }
-    fseek( f, 0, SEEK_SET );
+
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf(f, NULL);
+
+    fseek(f, 0, SEEK_END);
+    if ((size = ftell(f)) == -1) {
+        fclose(f);
+        return MBEDTLS_ERR_PK_FILE_IO_ERROR;
+    }
+    fseek(f, 0, SEEK_SET);
 
     *n = (size_t) size;
 
-    if( *n + 1 == 0 ||
-        ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
-    {
-        fclose( f );
-        return( MBEDTLS_ERR_PK_ALLOC_FAILED );
+    if (*n + 1 == 0 ||
+        (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
+        fclose(f);
+        return MBEDTLS_ERR_PK_ALLOC_FAILED;
     }
 
-    if( fread( *buf, 1, *n, f ) != *n )
-    {
-        fclose( f );
+    if (fread(*buf, 1, *n, f) != *n) {
+        fclose(f);
 
-        mbedtls_platform_zeroize( *buf, *n );
-        mbedtls_free( *buf );
+        mbedtls_platform_zeroize(*buf, *n);
+        mbedtls_free(*buf);
 
-        return( MBEDTLS_ERR_PK_FILE_IO_ERROR );
+        return MBEDTLS_ERR_PK_FILE_IO_ERROR;
     }
 
-    fclose( f );
+    fclose(f);
 
     (*buf)[*n] = '\0';
 
-    if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
+    if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
         ++*n;
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Load and parse a private key
  */
-int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx,
-                      const char *path, const char *pwd )
+int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx,
+                             const char *path, const char *pwd,
+                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
     unsigned char *buf;
 
-    PK_VALIDATE_RET( ctx != NULL );
-    PK_VALIDATE_RET( path != NULL );
+    if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
+        return ret;
+    }
 
-    if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
-        return( ret );
+    if (pwd == NULL) {
+        ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng);
+    } else {
+        ret = mbedtls_pk_parse_key(ctx, buf, n,
+                                   (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng);
+    }
 
-    if( pwd == NULL )
-        ret = mbedtls_pk_parse_key( ctx, buf, n, NULL, 0 );
-    else
-        ret = mbedtls_pk_parse_key( ctx, buf, n,
-                (const unsigned char *) pwd, strlen( pwd ) );
+    mbedtls_platform_zeroize(buf, n);
+    mbedtls_free(buf);
 
-    mbedtls_platform_zeroize( buf, n );
-    mbedtls_free( buf );
-
-    return( ret );
+    return ret;
 }
 
 /*
  * Load and parse a public key
  */
-int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path )
+int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
     unsigned char *buf;
 
-    PK_VALIDATE_RET( ctx != NULL );
-    PK_VALIDATE_RET( path != NULL );
+    if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
+        return ret;
+    }
 
-    if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
-        return( ret );
+    ret = mbedtls_pk_parse_public_key(ctx, buf, n);
 
-    ret = mbedtls_pk_parse_public_key( ctx, buf, n );
+    mbedtls_platform_zeroize(buf, n);
+    mbedtls_free(buf);
 
-    mbedtls_platform_zeroize( buf, n );
-    mbedtls_free( buf );
-
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_FS_IO */
 
@@ -180,40 +164,40 @@
  *   -- implicitCurve   NULL
  * }
  */
-static int pk_get_ecparams( unsigned char **p, const unsigned char *end,
-                            mbedtls_asn1_buf *params )
+static int pk_get_ecparams(unsigned char **p, const unsigned char *end,
+                           mbedtls_asn1_buf *params)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if ( end - *p < 1 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA ) );
+    if (end - *p < 1) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
+    }
 
     /* Tag may be either OID or SEQUENCE */
     params->tag = **p;
-    if( params->tag != MBEDTLS_ASN1_OID
+    if (params->tag != MBEDTLS_ASN1_OID
 #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
-            && params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE )
+        && params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)
 #endif
-            )
-    {
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
+        ) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
     }
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &params->len, params->tag ) ) != 0 )
-    {
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &params->len, params->tag)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
     }
 
     params->p = *p;
     *p += params->len;
 
-    if( *p != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (*p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
-    return( 0 );
+    return 0;
 }
 
 #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
@@ -236,7 +220,7 @@
  *
  * We only support prime-field as field type, and ignore hash and cofactor.
  */
-static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp )
+static int pk_group_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *p = params->p;
@@ -246,11 +230,13 @@
     int ver;
 
     /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */
-    if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_int(&p, end, &ver)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
+    }
 
-    if( ver < 1 || ver > 3 )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
+    if (ver < 1 || ver > 3) {
+        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
+    }
 
     /*
      * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field
@@ -258,9 +244,10 @@
      *       parameters FIELD-ID.&Type({IOSet}{@fieldType})
      * }
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return ret;
+    }
 
     end_field = p + len;
 
@@ -272,26 +259,28 @@
      * }
      * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_asn1_get_tag(&p, end_field, &len, MBEDTLS_ASN1_OID)) != 0) {
+        return ret;
+    }
 
-    if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) ||
-        memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 )
-    {
-        return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
+    if (len != MBEDTLS_OID_SIZE(MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD) ||
+        memcmp(p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len) != 0) {
+        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
     }
 
     p += len;
 
     /* Prime-p ::= INTEGER -- Field of size p. */
-    if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_mpi(&p, end_field, &grp->P)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
+    }
 
-    grp->pbits = mbedtls_mpi_bitlen( &grp->P );
+    grp->pbits = mbedtls_mpi_bitlen(&grp->P);
 
-    if( p != end_field )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (p != end_field) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
     /*
      * Curve ::= SEQUENCE {
@@ -302,9 +291,10 @@
      *       -- with version equal to ecdpVer2 or ecdpVer3
      * }
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return ret;
+    }
 
     end_curve = p + len;
 
@@ -312,51 +302,50 @@
      * FieldElement ::= OCTET STRING
      * containing an integer in the case of a prime field
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ||
-        ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 )
-    {
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 ||
+        (ret = mbedtls_mpi_read_binary(&grp->A, p, len)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
     }
 
     p += len;
 
-    if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ||
-        ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 )
-    {
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 ||
+        (ret = mbedtls_mpi_read_binary(&grp->B, p, len)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
     }
 
     p += len;
 
     /* Ignore seed BIT STRING OPTIONAL */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 )
+    if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING)) == 0) {
         p += len;
+    }
 
-    if( p != end_curve )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (p != end_curve) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
     /*
      * ECPoint ::= OCTET STRING
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
+    }
 
-    if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G,
-                                      ( const unsigned char *) p, len ) ) != 0 )
-    {
+    if ((ret = mbedtls_ecp_point_read_binary(grp, &grp->G,
+                                             (const unsigned char *) p, len)) != 0) {
         /*
          * If we can't read the point because it's compressed, cheat by
          * reading only the X coordinate and the parity bit of Y.
          */
-        if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ||
-            ( p[0] != 0x02 && p[0] != 0x03 ) ||
-            len != mbedtls_mpi_size( &grp->P ) + 1 ||
-            mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 ||
-            mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 ||
-            mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 )
-        {
-            return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
+        if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ||
+            (p[0] != 0x02 && p[0] != 0x03) ||
+            len != mbedtls_mpi_size(&grp->P) + 1 ||
+            mbedtls_mpi_read_binary(&grp->G.X, p + 1, len - 1) != 0 ||
+            mbedtls_mpi_lset(&grp->G.Y, p[0] - 2) != 0 ||
+            mbedtls_mpi_lset(&grp->G.Z, 1) != 0) {
+            return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
         }
     }
 
@@ -365,83 +354,95 @@
     /*
      * order INTEGER
      */
-    if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_mpi(&p, end, &grp->N)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
+    }
 
-    grp->nbits = mbedtls_mpi_bitlen( &grp->N );
+    grp->nbits = mbedtls_mpi_bitlen(&grp->N);
 
     /*
      * Allow optional elements by purposefully not enforcing p == end here.
      */
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Find the group id associated with an (almost filled) group as generated by
  * pk_group_from_specified(), or return an error if unknown.
  */
-static int pk_group_id_from_group( const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id )
+static int pk_group_id_from_group(const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id)
 {
     int ret = 0;
     mbedtls_ecp_group ref;
     const mbedtls_ecp_group_id *id;
 
-    mbedtls_ecp_group_init( &ref );
+    mbedtls_ecp_group_init(&ref);
 
-    for( id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++ )
-    {
+    for (id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++) {
         /* Load the group associated to that id */
-        mbedtls_ecp_group_free( &ref );
-        MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ref, *id ) );
+        mbedtls_ecp_group_free(&ref);
+        MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ref, *id));
 
         /* Compare to the group we were given, starting with easy tests */
-        if( grp->pbits == ref.pbits && grp->nbits == ref.nbits &&
-            mbedtls_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 &&
-            mbedtls_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 &&
-            mbedtls_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 &&
-            mbedtls_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 &&
-            mbedtls_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 &&
-            mbedtls_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 &&
+        if (grp->pbits == ref.pbits && grp->nbits == ref.nbits &&
+            mbedtls_mpi_cmp_mpi(&grp->P, &ref.P) == 0 &&
+            mbedtls_mpi_cmp_mpi(&grp->A, &ref.A) == 0 &&
+            mbedtls_mpi_cmp_mpi(&grp->B, &ref.B) == 0 &&
+            mbedtls_mpi_cmp_mpi(&grp->N, &ref.N) == 0 &&
+            mbedtls_mpi_cmp_mpi(&grp->G.X, &ref.G.X) == 0 &&
+            mbedtls_mpi_cmp_mpi(&grp->G.Z, &ref.G.Z) == 0 &&
             /* For Y we may only know the parity bit, so compare only that */
-            mbedtls_mpi_get_bit( &grp->G.Y, 0 ) == mbedtls_mpi_get_bit( &ref.G.Y, 0 ) )
-        {
+            mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) {
             break;
         }
 
     }
 
 cleanup:
-    mbedtls_ecp_group_free( &ref );
+    mbedtls_ecp_group_free(&ref);
 
     *grp_id = *id;
 
-    if( ret == 0 && *id == MBEDTLS_ECP_DP_NONE )
+    if (ret == 0 && *id == MBEDTLS_ECP_DP_NONE) {
         ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+    }
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID
  */
-static int pk_group_id_from_specified( const mbedtls_asn1_buf *params,
-                                       mbedtls_ecp_group_id *grp_id )
+static int pk_group_id_from_specified(const mbedtls_asn1_buf *params,
+                                      mbedtls_ecp_group_id *grp_id)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecp_group grp;
 
-    mbedtls_ecp_group_init( &grp );
+    mbedtls_ecp_group_init(&grp);
 
-    if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 )
+    if ((ret = pk_group_from_specified(params, &grp)) != 0) {
         goto cleanup;
+    }
 
-    ret = pk_group_id_from_group( &grp, grp_id );
+    ret = pk_group_id_from_group(&grp, grp_id);
 
 cleanup:
-    mbedtls_ecp_group_free( &grp );
+    /* The API respecting lifecycle for mbedtls_ecp_group struct is
+     * _init(), _load() and _free(). In pk_group_id_from_specified() the
+     * temporary grp breaks that flow and it's members are populated
+     * by pk_group_id_from_group(). As such mbedtls_ecp_group_free()
+     * which is assuming a group populated by _setup() may not clean-up
+     * properly -> Manually free it's members.
+     */
+    mbedtls_mpi_free(&grp.N);
+    mbedtls_mpi_free(&grp.P);
+    mbedtls_mpi_free(&grp.A);
+    mbedtls_mpi_free(&grp.B);
+    mbedtls_ecp_point_free(&grp.G);
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */
 
@@ -453,36 +454,37 @@
  *   specifiedCurve     SpecifiedECDomain -- = SEQUENCE { ... }
  *   -- implicitCurve   NULL
  */
-static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp )
+static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecp_group_id grp_id;
 
-    if( params->tag == MBEDTLS_ASN1_OID )
-    {
-        if( mbedtls_oid_get_ec_grp( params, &grp_id ) != 0 )
-            return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE );
-    }
-    else
-    {
+    if (params->tag == MBEDTLS_ASN1_OID) {
+        if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0) {
+            return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE;
+        }
+    } else {
 #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
-        if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 )
-            return( ret );
+        if ((ret = pk_group_id_from_specified(params, &grp_id)) != 0) {
+            return ret;
+        }
 #else
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
+        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
 #endif
     }
 
     /*
      * grp may already be initialized; if so, make sure IDs match
      */
-    if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
+    if (grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id) {
+        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
+    }
 
-    if( ( ret = mbedtls_ecp_group_load( grp, grp_id ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_ecp_group_load(grp, grp_id)) != 0) {
+        return ret;
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -492,15 +494,14 @@
  * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE
  * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state.
  */
-static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end,
-                            mbedtls_ecp_keypair *key )
+static int pk_get_ecpubkey(unsigned char **p, const unsigned char *end,
+                           mbedtls_ecp_keypair *key)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q,
-                    (const unsigned char *) *p, end - *p ) ) == 0 )
-    {
-        ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q );
+    if ((ret = mbedtls_ecp_point_read_binary(&key->grp, &key->Q,
+                                             (const unsigned char *) *p, end - *p)) == 0) {
+        ret = mbedtls_ecp_check_pubkey(&key->grp, &key->Q);
     }
 
     /*
@@ -508,7 +509,7 @@
      */
     *p = (unsigned char *) end;
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_ECP_C */
 
@@ -519,52 +520,58 @@
  *      publicExponent    INTEGER   -- e
  *  }
  */
-static int pk_get_rsapubkey( unsigned char **p,
-                             const unsigned char *end,
-                             mbedtls_rsa_context *rsa )
+static int pk_get_rsapubkey(unsigned char **p,
+                            const unsigned char *end,
+                            mbedtls_rsa_context *rsa)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
+    }
 
-    if( *p + len != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (*p + len != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
     /* Import N */
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
+    }
 
-    if( ( ret = mbedtls_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0,
-                                        NULL, 0, NULL, 0 ) ) != 0 )
-        return( MBEDTLS_ERR_PK_INVALID_PUBKEY );
+    if ((ret = mbedtls_rsa_import_raw(rsa, *p, len, NULL, 0, NULL, 0,
+                                      NULL, 0, NULL, 0)) != 0) {
+        return MBEDTLS_ERR_PK_INVALID_PUBKEY;
+    }
 
     *p += len;
 
     /* Import E */
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
+    }
 
-    if( ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
-                                        NULL, 0, *p, len ) ) != 0 )
-        return( MBEDTLS_ERR_PK_INVALID_PUBKEY );
+    if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0,
+                                      NULL, 0, *p, len)) != 0) {
+        return MBEDTLS_ERR_PK_INVALID_PUBKEY;
+    }
 
     *p += len;
 
-    if( mbedtls_rsa_complete( rsa ) != 0 ||
-        mbedtls_rsa_check_pubkey( rsa ) != 0 )
-    {
-        return( MBEDTLS_ERR_PK_INVALID_PUBKEY );
+    if (mbedtls_rsa_complete(rsa) != 0 ||
+        mbedtls_rsa_check_pubkey(rsa) != 0) {
+        return MBEDTLS_ERR_PK_INVALID_PUBKEY;
     }
 
-    if( *p != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (*p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_RSA_C */
 
@@ -574,32 +581,33 @@
  *       algorithm               OBJECT IDENTIFIER,
  *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
  */
-static int pk_get_pk_alg( unsigned char **p,
-                          const unsigned char *end,
-                          mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params )
+static int pk_get_pk_alg(unsigned char **p,
+                         const unsigned char *end,
+                         mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_asn1_buf alg_oid;
 
-    memset( params, 0, sizeof(mbedtls_asn1_buf) );
+    memset(params, 0, sizeof(mbedtls_asn1_buf));
 
-    if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_ALG, ret ) );
+    if ((ret = mbedtls_asn1_get_alg(p, end, &alg_oid, params)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret);
+    }
 
-    if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 )
-        return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
+    if (mbedtls_oid_get_pk_alg(&alg_oid, pk_alg) != 0) {
+        return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
+    }
 
     /*
      * No parameters with RSA (only for EC)
      */
-    if( *pk_alg == MBEDTLS_PK_RSA &&
-            ( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) ||
-                params->len != 0 ) )
-    {
-        return( MBEDTLS_ERR_PK_INVALID_ALG );
+    if (*pk_alg == MBEDTLS_PK_RSA &&
+        ((params->tag != MBEDTLS_ASN1_NULL && params->tag != 0) ||
+         params->len != 0)) {
+        return MBEDTLS_ERR_PK_INVALID_ALG;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -607,8 +615,8 @@
  *       algorithm            AlgorithmIdentifier,
  *       subjectPublicKey     BIT STRING }
  */
-int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
-                        mbedtls_pk_context *pk )
+int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end,
+                               mbedtls_pk_context *pk)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
@@ -616,59 +624,59 @@
     mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
     const mbedtls_pk_info_t *pk_info;
 
-    PK_VALIDATE_RET( p != NULL );
-    PK_VALIDATE_RET( *p != NULL );
-    PK_VALIDATE_RET( end != NULL );
-    PK_VALIDATE_RET( pk != NULL );
-
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
     }
 
     end = *p + len;
 
-    if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 )
-        return( ret );
+    if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params)) != 0) {
+        return ret;
+    }
 
-    if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) );
+    if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
+    }
 
-    if( *p + len != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (*p + len != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
-    if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL )
-        return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
+    if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) {
+        return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
+    }
 
-    if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) {
+        return ret;
+    }
 
 #if defined(MBEDTLS_RSA_C)
-    if( pk_alg == MBEDTLS_PK_RSA )
-    {
-        ret = pk_get_rsapubkey( p, end, mbedtls_pk_rsa( *pk ) );
+    if (pk_alg == MBEDTLS_PK_RSA) {
+        ret = pk_get_rsapubkey(p, end, mbedtls_pk_rsa(*pk));
     } else
 #endif /* MBEDTLS_RSA_C */
 #if defined(MBEDTLS_ECP_C)
-    if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY )
-    {
-        ret = pk_use_ecparams( &alg_params, &mbedtls_pk_ec( *pk )->grp );
-        if( ret == 0 )
-            ret = pk_get_ecpubkey( p, end, mbedtls_pk_ec( *pk ) );
+    if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) {
+        ret = pk_use_ecparams(&alg_params, &mbedtls_pk_ec(*pk)->grp);
+        if (ret == 0) {
+            ret = pk_get_ecpubkey(p, end, mbedtls_pk_ec(*pk));
+        }
     } else
 #endif /* MBEDTLS_ECP_C */
-        ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
+    ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
 
-    if( ret == 0 && *p != end )
-        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY,
-              MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+    if (ret == 0 && *p != end) {
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
+                                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
-    if( ret != 0 )
-        mbedtls_pk_free( pk );
+    if (ret != 0) {
+        mbedtls_pk_free(pk);
+    }
 
-    return( ret );
+    return ret;
 }
 
 #if defined(MBEDTLS_RSA_C)
@@ -682,35 +690,37 @@
  * Since values can't be omitted in PKCS#1, passing a zero value to
  * rsa_complete() would be incorrect, so reject zero values early.
  */
-static int asn1_get_nonzero_mpi( unsigned char **p,
-                                 const unsigned char *end,
-                                 mbedtls_mpi *X )
+static int asn1_get_nonzero_mpi(unsigned char **p,
+                                const unsigned char *end,
+                                mbedtls_mpi *X)
 {
     int ret;
 
-    ret = mbedtls_asn1_get_mpi( p, end, X );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_asn1_get_mpi(p, end, X);
+    if (ret != 0) {
+        return ret;
+    }
 
-    if( mbedtls_mpi_cmp_int( X, 0 ) == 0 )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
+    if (mbedtls_mpi_cmp_int(X, 0) == 0) {
+        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Parse a PKCS#1 encoded private RSA key
  */
-static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa,
-                                   const unsigned char *key,
-                                   size_t keylen )
+static int pk_parse_key_pkcs1_der(mbedtls_rsa_context *rsa,
+                                  const unsigned char *key,
+                                  size_t keylen)
 {
     int ret, version;
     size_t len;
     unsigned char *p, *end;
 
     mbedtls_mpi T;
-    mbedtls_mpi_init( &T );
+    mbedtls_mpi_init(&T);
 
     p = (unsigned char *) key;
     end = p + keylen;
@@ -731,87 +741,93 @@
      *      otherPrimeInfos   OtherPrimeInfos OPTIONAL
      *  }
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
     }
 
     end = p + len;
 
-    if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 )
-    {
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
     }
 
-    if( version != 0 )
-    {
-        return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION );
+    if (version != 0) {
+        return MBEDTLS_ERR_PK_KEY_INVALID_VERSION;
     }
 
     /* Import N */
-    if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
-        ( ret = mbedtls_rsa_import( rsa, &T, NULL, NULL,
-                                        NULL, NULL ) ) != 0 )
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL,
+                                  NULL, NULL)) != 0) {
         goto cleanup;
+    }
 
     /* Import E */
-    if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
-        ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL,
-                                        NULL, &T ) ) != 0 )
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
+                                  NULL, &T)) != 0) {
         goto cleanup;
+    }
 
     /* Import D */
-    if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
-        ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL,
-                                        &T, NULL ) ) != 0 )
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
+                                  &T, NULL)) != 0) {
         goto cleanup;
+    }
 
     /* Import P */
-    if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
-        ( ret = mbedtls_rsa_import( rsa, NULL, &T, NULL,
-                                        NULL, NULL ) ) != 0 )
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL,
+                                  NULL, NULL)) != 0) {
         goto cleanup;
+    }
 
     /* Import Q */
-    if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
-        ( ret = mbedtls_rsa_import( rsa, NULL, NULL, &T,
-                                        NULL, NULL ) ) != 0 )
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T,
+                                  NULL, NULL)) != 0) {
         goto cleanup;
+    }
 
 #if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT)
     /*
-    * The RSA CRT parameters DP, DQ and QP are nominally redundant, in
-    * that they can be easily recomputed from D, P and Q. However by
-    * parsing them from the PKCS1 structure it is possible to avoid
-    * recalculating them which both reduces the overhead of loading
-    * RSA private keys into memory and also avoids side channels which
-    * can arise when computing those values, since all of D, P, and Q
-    * are secret. See https://eprint.iacr.org/2020/055 for a
-    * description of one such attack.
-    */
+     * The RSA CRT parameters DP, DQ and QP are nominally redundant, in
+     * that they can be easily recomputed from D, P and Q. However by
+     * parsing them from the PKCS1 structure it is possible to avoid
+     * recalculating them which both reduces the overhead of loading
+     * RSA private keys into memory and also avoids side channels which
+     * can arise when computing those values, since all of D, P, and Q
+     * are secret. See https://eprint.iacr.org/2020/055 for a
+     * description of one such attack.
+     */
 
     /* Import DP */
-    if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
-        ( ret = mbedtls_mpi_copy( &rsa->DP, &T ) ) != 0 )
-       goto cleanup;
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) {
+        goto cleanup;
+    }
 
     /* Import DQ */
-    if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
-        ( ret = mbedtls_mpi_copy( &rsa->DQ, &T ) ) != 0 )
-       goto cleanup;
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) {
+        goto cleanup;
+    }
 
     /* Import QP */
-    if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
-        ( ret = mbedtls_mpi_copy( &rsa->QP, &T ) ) != 0 )
-       goto cleanup;
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) {
+        goto cleanup;
+    }
 
 #else
     /* Verify existence of the CRT params */
-    if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
-        ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
-        ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 )
-       goto cleanup;
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) {
+        goto cleanup;
+    }
 #endif
 
     /* rsa_complete() doesn't complete anything with the default
@@ -823,34 +839,32 @@
      * Furthermore, we also check the public part for consistency with
      * mbedtls_pk_parse_pubkey(), as it includes size minima for example.
      */
-    if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 ||
-        ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 )
-    {
+    if ((ret = mbedtls_rsa_complete(rsa)) != 0 ||
+        (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) {
         goto cleanup;
     }
 
-    if( p != end )
-    {
-        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
-              MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+    if (p != end) {
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+                                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
     }
 
 cleanup:
 
-    mbedtls_mpi_free( &T );
+    mbedtls_mpi_free(&T);
 
-    if( ret != 0 )
-    {
+    if (ret != 0) {
         /* Wrap error code if it's coming from a lower level */
-        if( ( ret & 0xff80 ) == 0 )
-            ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret );
-        else
+        if ((ret & 0xff80) == 0) {
+            ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
+        } else {
             ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
+        }
 
-        mbedtls_rsa_free( rsa );
+        mbedtls_rsa_free(rsa);
     }
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_RSA_C */
 
@@ -858,14 +872,14 @@
 /*
  * Parse a SEC1 encoded private EC key
  */
-static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck,
-                                  const unsigned char *key,
-                                  size_t keylen )
+static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck,
+                                 const unsigned char *key, size_t keylen,
+                                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     int version, pubkey_done;
     size_t len;
-    mbedtls_asn1_buf params;
+    mbedtls_asn1_buf params = { 0, 0, NULL };
     unsigned char *p = (unsigned char *) key;
     unsigned char *end = p + keylen;
     unsigned char *end2;
@@ -880,106 +894,100 @@
      *      publicKey  [1] BIT STRING OPTIONAL
      *    }
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
     }
 
     end = p + len;
 
-    if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
+    }
 
-    if( version != 1 )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION );
+    if (version != 1) {
+        return MBEDTLS_ERR_PK_KEY_INVALID_VERSION;
+    }
 
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
+    }
 
-    if( ( ret = mbedtls_mpi_read_binary( &eck->d, p, len ) ) != 0 )
-    {
-        mbedtls_ecp_keypair_free( eck );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_mpi_read_binary(&eck->d, p, len)) != 0) {
+        mbedtls_ecp_keypair_free(eck);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
     }
 
     p += len;
 
     pubkey_done = 0;
-    if( p != end )
-    {
+    if (p != end) {
         /*
          * Is 'parameters' present?
          */
-        if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-                        MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 )
-        {
-            if( ( ret = pk_get_ecparams( &p, p + len, &params) ) != 0 ||
-                ( ret = pk_use_ecparams( &params, &eck->grp )  ) != 0 )
-            {
-                mbedtls_ecp_keypair_free( eck );
-                return( ret );
+        if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                        MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
+                                        0)) == 0) {
+            if ((ret = pk_get_ecparams(&p, p + len, &params)) != 0 ||
+                (ret = pk_use_ecparams(&params, &eck->grp)) != 0) {
+                mbedtls_ecp_keypair_free(eck);
+                return ret;
             }
-        }
-        else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-        {
-            mbedtls_ecp_keypair_free( eck );
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+        } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
+            mbedtls_ecp_keypair_free(eck);
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
         }
     }
 
-    if( p != end )
-    {
+    if (p != end) {
         /*
          * Is 'publickey' present? If not, or if we can't read it (eg because it
          * is compressed), create it from the private key.
          */
-        if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-                        MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 )
-        {
+        if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                        MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
+                                        1)) == 0) {
             end2 = p + len;
 
-            if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 )
-                return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+            if ((ret = mbedtls_asn1_get_bitstring_null(&p, end2, &len)) != 0) {
+                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
+            }
 
-            if( p + len != end2 )
-                return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
-                        MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+            if (p + len != end2) {
+                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+                                         MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+            }
 
-            if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 )
+            if ((ret = pk_get_ecpubkey(&p, end2, eck)) == 0) {
                 pubkey_done = 1;
-            else
-            {
+            } else {
                 /*
                  * The only acceptable failure mode of pk_get_ecpubkey() above
                  * is if the point format is not recognized.
                  */
-                if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE )
-                    return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
+                if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) {
+                    return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
+                }
             }
-        }
-        else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-        {
-            mbedtls_ecp_keypair_free( eck );
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+        } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
+            mbedtls_ecp_keypair_free(eck);
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
         }
     }
 
-    if( ! pubkey_done &&
-        ( ret = mbedtls_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G,
-                                                      NULL, NULL ) ) != 0 )
-    {
-        mbedtls_ecp_keypair_free( eck );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if (!pubkey_done &&
+        (ret = mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G,
+                               f_rng, p_rng)) != 0) {
+        mbedtls_ecp_keypair_free(eck);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
     }
 
-    if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 )
-    {
-        mbedtls_ecp_keypair_free( eck );
-        return( ret );
+    if ((ret = mbedtls_ecp_check_privkey(&eck->grp, &eck->d)) != 0) {
+        mbedtls_ecp_keypair_free(eck);
+        return ret;
     }
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_ECP_C */
 
@@ -997,9 +1005,9 @@
  *
  */
 static int pk_parse_key_pkcs8_unencrypted_der(
-                                    mbedtls_pk_context *pk,
-                                    const unsigned char* key,
-                                    size_t keylen )
+    mbedtls_pk_context *pk,
+    const unsigned char *key, size_t keylen,
+    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
     int ret, version;
     size_t len;
@@ -1009,6 +1017,11 @@
     mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
     const mbedtls_pk_info_t *pk_info;
 
+#if !defined(MBEDTLS_ECP_C)
+    (void) f_rng;
+    (void) p_rng;
+#endif
+
     /*
      * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208)
      *
@@ -1025,62 +1038,62 @@
      *  The PrivateKey OCTET STRING is a SEC1 ECPrivateKey
      */
 
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
     }
 
     end = p + len;
 
-    if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
-
-    if( version != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret ) );
-
-    if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, &params ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
     }
 
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if (version != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret);
+    }
 
-    if( len < 1 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA ) );
+    if ((ret = pk_get_pk_alg(&p, end, &pk_alg, &params)) != 0) {
+        return ret;
+    }
 
-    if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL )
-        return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
+    }
 
-    if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 )
-        return( ret );
+    if (len < 1) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
+    }
+
+    if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) {
+        return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
+    }
+
+    if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) {
+        return ret;
+    }
 
 #if defined(MBEDTLS_RSA_C)
-    if( pk_alg == MBEDTLS_PK_RSA )
-    {
-        if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 )
-        {
-            mbedtls_pk_free( pk );
-            return( ret );
+    if (pk_alg == MBEDTLS_PK_RSA) {
+        if ((ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), p, len)) != 0) {
+            mbedtls_pk_free(pk);
+            return ret;
         }
     } else
 #endif /* MBEDTLS_RSA_C */
 #if defined(MBEDTLS_ECP_C)
-    if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH )
-    {
-        if( ( ret = pk_use_ecparams( &params, &mbedtls_pk_ec( *pk )->grp ) ) != 0 ||
-            ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len )  ) != 0 )
-        {
-            mbedtls_pk_free( pk );
-            return( ret );
+    if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) {
+        if ((ret = pk_use_ecparams(&params, &mbedtls_pk_ec(*pk)->grp)) != 0 ||
+            (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), p, len, f_rng, p_rng)) != 0) {
+            mbedtls_pk_free(pk);
+            return ret;
         }
     } else
 #endif /* MBEDTLS_ECP_C */
-        return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
+    return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -1094,9 +1107,10 @@
  */
 #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
 static int pk_parse_key_pkcs8_encrypted_der(
-                                    mbedtls_pk_context *pk,
-                                    unsigned char *key, size_t keylen,
-                                    const unsigned char *pwd, size_t pwdlen )
+    mbedtls_pk_context *pk,
+    unsigned char *key, size_t keylen,
+    const unsigned char *pwd, size_t pwdlen,
+    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
     int ret, decrypted = 0;
     size_t len;
@@ -1111,8 +1125,9 @@
     p = key;
     end = p + keylen;
 
-    if( pwdlen == 0 )
-        return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED );
+    if (pwdlen == 0) {
+        return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
+    }
 
     /*
      * This function parses the EncryptedPrivateKeyInfo object (PKCS#8)
@@ -1129,19 +1144,20 @@
      *  The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo
      *
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
     }
 
     end = p + len;
 
-    if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
+    }
 
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
+    }
 
     buf = p;
 
@@ -1149,73 +1165,53 @@
      * Decrypt EncryptedData with appropriate PBE
      */
 #if defined(MBEDTLS_PKCS12_C)
-    if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 )
-    {
-        if( ( ret = mbedtls_pkcs12_pbe( &pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT,
-                                cipher_alg, md_alg,
-                                pwd, pwdlen, p, len, buf ) ) != 0 )
-        {
-            if( ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH )
-                return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH );
+    if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) {
+        if ((ret = mbedtls_pkcs12_pbe(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT,
+                                      cipher_alg, md_alg,
+                                      pwd, pwdlen, p, len, buf)) != 0) {
+            if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) {
+                return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
+            }
 
-            return( ret );
+            return ret;
         }
 
         decrypted = 1;
-    }
-    else if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) == 0 )
-    {
-        if( ( ret = mbedtls_pkcs12_pbe_sha1_rc4_128( &pbe_params,
-                                             MBEDTLS_PKCS12_PBE_DECRYPT,
-                                             pwd, pwdlen,
-                                             p, len, buf ) ) != 0 )
-        {
-            return( ret );
-        }
-
-        // Best guess for password mismatch when using RC4. If first tag is
-        // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE
-        //
-        if( *buf != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
-            return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH );
-
-        decrypted = 1;
-    }
-    else
+    } else
 #endif /* MBEDTLS_PKCS12_C */
 #if defined(MBEDTLS_PKCS5_C)
-    if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 )
-    {
-        if( ( ret = mbedtls_pkcs5_pbes2( &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen,
-                                  p, len, buf ) ) != 0 )
-        {
-            if( ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH )
-                return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH );
+    if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) {
+        if ((ret = mbedtls_pkcs5_pbes2(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen,
+                                       p, len, buf)) != 0) {
+            if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) {
+                return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
+            }
 
-            return( ret );
+            return ret;
         }
 
         decrypted = 1;
-    }
-    else
+    } else
 #endif /* MBEDTLS_PKCS5_C */
     {
         ((void) pwd);
     }
 
-    if( decrypted == 0 )
-        return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
+    if (decrypted == 0) {
+        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+    }
 
-    return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) );
+    return pk_parse_key_pkcs8_unencrypted_der(pk, buf, len, f_rng, p_rng);
 }
 #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
 
 /*
  * Parse a private key
  */
-int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
-                  const unsigned char *key, size_t keylen,
-                  const unsigned char *pwd, size_t pwdlen )
+int mbedtls_pk_parse_key(mbedtls_pk_context *pk,
+                         const unsigned char *key, size_t keylen,
+                         const unsigned char *pwd, size_t pwdlen,
+                         int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const mbedtls_pk_info_t *pk_info;
@@ -1224,121 +1220,116 @@
     mbedtls_pem_context pem;
 #endif
 
-    PK_VALIDATE_RET( pk != NULL );
-    if( keylen == 0 )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
-    PK_VALIDATE_RET( key != NULL );
+    if (keylen == 0) {
+        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
+    }
 
 #if defined(MBEDTLS_PEM_PARSE_C)
-   mbedtls_pem_init( &pem );
+    mbedtls_pem_init(&pem);
 
 #if defined(MBEDTLS_RSA_C)
     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
-    if( key[keylen - 1] != '\0' )
+    if (key[keylen - 1] != '\0') {
         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
-    else
-        ret = mbedtls_pem_read_buffer( &pem,
-                               "-----BEGIN RSA PRIVATE KEY-----",
-                               "-----END RSA PRIVATE KEY-----",
-                               key, pwd, pwdlen, &len );
+    } else {
+        ret = mbedtls_pem_read_buffer(&pem,
+                                      "-----BEGIN RSA PRIVATE KEY-----",
+                                      "-----END RSA PRIVATE KEY-----",
+                                      key, pwd, pwdlen, &len);
+    }
 
-    if( ret == 0 )
-    {
-        pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA );
-        if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
-            ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ),
-                                            pem.buf, pem.buflen ) ) != 0 )
-        {
-            mbedtls_pk_free( pk );
+    if (ret == 0) {
+        pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
+        if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
+            (ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk),
+                                          pem.buf, pem.buflen)) != 0) {
+            mbedtls_pk_free(pk);
         }
 
-        mbedtls_pem_free( &pem );
-        return( ret );
+        mbedtls_pem_free(&pem);
+        return ret;
+    } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {
+        return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
+    } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {
+        return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
+    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
+        return ret;
     }
-    else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH )
-        return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH );
-    else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED )
-        return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED );
-    else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-        return( ret );
 #endif /* MBEDTLS_RSA_C */
 
 #if defined(MBEDTLS_ECP_C)
     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
-    if( key[keylen - 1] != '\0' )
+    if (key[keylen - 1] != '\0') {
         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
-    else
-        ret = mbedtls_pem_read_buffer( &pem,
-                               "-----BEGIN EC PRIVATE KEY-----",
-                               "-----END EC PRIVATE KEY-----",
-                               key, pwd, pwdlen, &len );
-    if( ret == 0 )
-    {
-        pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY );
+    } else {
+        ret = mbedtls_pem_read_buffer(&pem,
+                                      "-----BEGIN EC PRIVATE KEY-----",
+                                      "-----END EC PRIVATE KEY-----",
+                                      key, pwd, pwdlen, &len);
+    }
+    if (ret == 0) {
+        pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
 
-        if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
-            ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ),
-                                           pem.buf, pem.buflen ) ) != 0 )
-        {
-            mbedtls_pk_free( pk );
+        if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
+            (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk),
+                                         pem.buf, pem.buflen,
+                                         f_rng, p_rng)) != 0) {
+            mbedtls_pk_free(pk);
         }
 
-        mbedtls_pem_free( &pem );
-        return( ret );
+        mbedtls_pem_free(&pem);
+        return ret;
+    } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) {
+        return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
+    } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) {
+        return MBEDTLS_ERR_PK_PASSWORD_REQUIRED;
+    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
+        return ret;
     }
-    else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH )
-        return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH );
-    else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED )
-        return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED );
-    else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-        return( ret );
 #endif /* MBEDTLS_ECP_C */
 
     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
-    if( key[keylen - 1] != '\0' )
+    if (key[keylen - 1] != '\0') {
         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
-    else
-        ret = mbedtls_pem_read_buffer( &pem,
-                               "-----BEGIN PRIVATE KEY-----",
-                               "-----END PRIVATE KEY-----",
-                               key, NULL, 0, &len );
-    if( ret == 0 )
-    {
-        if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk,
-                                                pem.buf, pem.buflen ) ) != 0 )
-        {
-            mbedtls_pk_free( pk );
+    } else {
+        ret = mbedtls_pem_read_buffer(&pem,
+                                      "-----BEGIN PRIVATE KEY-----",
+                                      "-----END PRIVATE KEY-----",
+                                      key, NULL, 0, &len);
+    }
+    if (ret == 0) {
+        if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk,
+                                                      pem.buf, pem.buflen, f_rng, p_rng)) != 0) {
+            mbedtls_pk_free(pk);
         }
 
-        mbedtls_pem_free( &pem );
-        return( ret );
+        mbedtls_pem_free(&pem);
+        return ret;
+    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
+        return ret;
     }
-    else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-        return( ret );
 
 #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
-    if( key[keylen - 1] != '\0' )
+    if (key[keylen - 1] != '\0') {
         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
-    else
-        ret = mbedtls_pem_read_buffer( &pem,
-                               "-----BEGIN ENCRYPTED PRIVATE KEY-----",
-                               "-----END ENCRYPTED PRIVATE KEY-----",
-                               key, NULL, 0, &len );
-    if( ret == 0 )
-    {
-        if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk,
-                                                      pem.buf, pem.buflen,
-                                                      pwd, pwdlen ) ) != 0 )
-        {
-            mbedtls_pk_free( pk );
+    } else {
+        ret = mbedtls_pem_read_buffer(&pem,
+                                      "-----BEGIN ENCRYPTED PRIVATE KEY-----",
+                                      "-----END ENCRYPTED PRIVATE KEY-----",
+                                      key, NULL, 0, &len);
+    }
+    if (ret == 0) {
+        if ((ret = pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen,
+                                                    pwd, pwdlen, f_rng, p_rng)) != 0) {
+            mbedtls_pk_free(pk);
         }
 
-        mbedtls_pem_free( &pem );
-        return( ret );
+        mbedtls_pem_free(&pem);
+        return ret;
+    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
+        return ret;
     }
-    else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-        return( ret );
 #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
 #else
     ((void) pwd);
@@ -1353,64 +1344,62 @@
      * error
      */
 #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
-    {
+    if (pwdlen != 0) {
         unsigned char *key_copy;
 
-        if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL )
-            return( MBEDTLS_ERR_PK_ALLOC_FAILED );
+        if ((key_copy = mbedtls_calloc(1, keylen)) == NULL) {
+            return MBEDTLS_ERR_PK_ALLOC_FAILED;
+        }
 
-        memcpy( key_copy, key, keylen );
+        memcpy(key_copy, key, keylen);
 
-        ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen,
-                                                pwd, pwdlen );
+        ret = pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen,
+                                               pwd, pwdlen, f_rng, p_rng);
 
-        mbedtls_platform_zeroize( key_copy, keylen );
-        mbedtls_free( key_copy );
+        mbedtls_platform_zeroize(key_copy, keylen);
+        mbedtls_free(key_copy);
     }
 
-    if( ret == 0 )
-        return( 0 );
+    if (ret == 0) {
+        return 0;
+    }
 
-    mbedtls_pk_free( pk );
-    mbedtls_pk_init( pk );
+    mbedtls_pk_free(pk);
+    mbedtls_pk_init(pk);
 
-    if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH )
-    {
-        return( ret );
+    if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) {
+        return ret;
     }
 #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
 
-    ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen );
-    if( ret == 0 )
-    {
-        return( 0 );
+    ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen, f_rng, p_rng);
+    if (ret == 0) {
+        return 0;
     }
 
-    mbedtls_pk_free( pk );
-    mbedtls_pk_init( pk );
+    mbedtls_pk_free(pk);
+    mbedtls_pk_init(pk);
 
 #if defined(MBEDTLS_RSA_C)
 
-    pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA );
-    if( mbedtls_pk_setup( pk, pk_info ) == 0 &&
-        pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 )
-    {
-        return( 0 );
+    pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
+    if (mbedtls_pk_setup(pk, pk_info) == 0 &&
+        pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), key, keylen) == 0) {
+        return 0;
     }
 
-    mbedtls_pk_free( pk );
-    mbedtls_pk_init( pk );
+    mbedtls_pk_free(pk);
+    mbedtls_pk_init(pk);
 #endif /* MBEDTLS_RSA_C */
 
 #if defined(MBEDTLS_ECP_C)
-    pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY );
-    if( mbedtls_pk_setup( pk, pk_info ) == 0 &&
-        pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ),
-                               key, keylen ) == 0 )
-    {
-        return( 0 );
+    pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
+    if (mbedtls_pk_setup(pk, pk_info) == 0 &&
+        pk_parse_key_sec1_der(mbedtls_pk_ec(*pk),
+                              key, keylen, f_rng, p_rng) == 0) {
+        return 0;
     }
-    mbedtls_pk_free( pk );
+    mbedtls_pk_free(pk);
 #endif /* MBEDTLS_ECP_C */
 
     /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't,
@@ -1423,14 +1412,14 @@
      * also ok and in line with the mbedtls_pk_free() calls
      * on failed PEM parsing attempts. */
 
-    return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
+    return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
 }
 
 /*
  * Parse a public key
  */
-int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx,
-                         const unsigned char *key, size_t keylen )
+int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,
+                                const unsigned char *key, size_t keylen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *p;
@@ -1442,104 +1431,98 @@
     mbedtls_pem_context pem;
 #endif
 
-    PK_VALIDATE_RET( ctx != NULL );
-    if( keylen == 0 )
-        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
-    PK_VALIDATE_RET( key != NULL || keylen == 0 );
+    if (keylen == 0) {
+        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
+    }
 
 #if defined(MBEDTLS_PEM_PARSE_C)
-    mbedtls_pem_init( &pem );
+    mbedtls_pem_init(&pem);
 #if defined(MBEDTLS_RSA_C)
     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
-    if( key[keylen - 1] != '\0' )
+    if (key[keylen - 1] != '\0') {
         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
-    else
-        ret = mbedtls_pem_read_buffer( &pem,
-                               "-----BEGIN RSA PUBLIC KEY-----",
-                               "-----END RSA PUBLIC KEY-----",
-                               key, NULL, 0, &len );
-
-    if( ret == 0 )
-    {
-        p = pem.buf;
-        if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL )
-        {
-            mbedtls_pem_free( &pem );
-            return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
-        }
-
-        if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 )
-        {
-            mbedtls_pem_free( &pem );
-            return( ret );
-        }
-
-        if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedtls_pk_rsa( *ctx ) ) ) != 0 )
-            mbedtls_pk_free( ctx );
-
-        mbedtls_pem_free( &pem );
-        return( ret );
+    } else {
+        ret = mbedtls_pem_read_buffer(&pem,
+                                      "-----BEGIN RSA PUBLIC KEY-----",
+                                      "-----END RSA PUBLIC KEY-----",
+                                      key, NULL, 0, &len);
     }
-    else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-    {
-        mbedtls_pem_free( &pem );
-        return( ret );
+
+    if (ret == 0) {
+        p = pem.buf;
+        if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) {
+            mbedtls_pem_free(&pem);
+            return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
+        }
+
+        if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) {
+            mbedtls_pem_free(&pem);
+            return ret;
+        }
+
+        if ((ret = pk_get_rsapubkey(&p, p + pem.buflen, mbedtls_pk_rsa(*ctx))) != 0) {
+            mbedtls_pk_free(ctx);
+        }
+
+        mbedtls_pem_free(&pem);
+        return ret;
+    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
+        mbedtls_pem_free(&pem);
+        return ret;
     }
 #endif /* MBEDTLS_RSA_C */
 
     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
-    if( key[keylen - 1] != '\0' )
+    if (key[keylen - 1] != '\0') {
         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
-    else
-        ret = mbedtls_pem_read_buffer( &pem,
-                "-----BEGIN PUBLIC KEY-----",
-                "-----END PUBLIC KEY-----",
-                key, NULL, 0, &len );
+    } else {
+        ret = mbedtls_pem_read_buffer(&pem,
+                                      "-----BEGIN PUBLIC KEY-----",
+                                      "-----END PUBLIC KEY-----",
+                                      key, NULL, 0, &len);
+    }
 
-    if( ret == 0 )
-    {
+    if (ret == 0) {
         /*
          * Was PEM encoded
          */
         p = pem.buf;
 
-        ret = mbedtls_pk_parse_subpubkey( &p,  p + pem.buflen, ctx );
-        mbedtls_pem_free( &pem );
-        return( ret );
+        ret = mbedtls_pk_parse_subpubkey(&p,  p + pem.buflen, ctx);
+        mbedtls_pem_free(&pem);
+        return ret;
+    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
+        mbedtls_pem_free(&pem);
+        return ret;
     }
-    else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-    {
-        mbedtls_pem_free( &pem );
-        return( ret );
-    }
-    mbedtls_pem_free( &pem );
+    mbedtls_pem_free(&pem);
 #endif /* MBEDTLS_PEM_PARSE_C */
 
 #if defined(MBEDTLS_RSA_C)
-    if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL )
-        return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
-
-    if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 )
-        return( ret );
-
-    p = (unsigned char *)key;
-    ret = pk_get_rsapubkey( &p, p + keylen, mbedtls_pk_rsa( *ctx ) );
-    if( ret == 0 )
-    {
-        return( ret );
+    if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) {
+        return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
     }
-    mbedtls_pk_free( ctx );
-    if( ret != ( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY,
-                                    MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) )
-    {
-        return( ret );
+
+    if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) {
+        return ret;
+    }
+
+    p = (unsigned char *) key;
+    ret = pk_get_rsapubkey(&p, p + keylen, mbedtls_pk_rsa(*ctx));
+    if (ret == 0) {
+        return ret;
+    }
+    mbedtls_pk_free(ctx);
+    if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
+                                  MBEDTLS_ERR_ASN1_UNEXPECTED_TAG))) {
+        return ret;
     }
 #endif /* MBEDTLS_RSA_C */
     p = (unsigned char *) key;
 
-    ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx );
+    ret = mbedtls_pk_parse_subpubkey(&p, p + keylen, ctx);
 
-    return( ret );
+    return ret;
 }
 
 #endif /* MBEDTLS_PK_PARSE_C */
diff --git a/lib/libmbedtls/mbedtls/library/pkwrite.c b/lib/libmbedtls/mbedtls/library/pkwrite.c
index 566153d..2194c97 100644
--- a/lib/libmbedtls/mbedtls/library/pkwrite.c
+++ b/lib/libmbedtls/mbedtls/library/pkwrite.c
@@ -37,6 +37,9 @@
 #include "mbedtls/ecp.h"
 #include "mbedtls/platform_util.h"
 #endif
+#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C)
+#include "pkwrite.h"
+#endif
 #if defined(MBEDTLS_ECDSA_C)
 #include "mbedtls/ecdsa.h"
 #endif
@@ -48,19 +51,7 @@
 #include "psa/crypto.h"
 #include "mbedtls/psa_util.h"
 #endif
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free       free
-#endif
-
-/* Parameter validation macros based on platform_util.h */
-#define PK_VALIDATE_RET( cond )    \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA )
-#define PK_VALIDATE( cond )        \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
 
 #if defined(MBEDTLS_RSA_C)
 /*
@@ -69,38 +60,41 @@
  *      publicExponent    INTEGER   -- e
  *  }
  */
-static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
-                                mbedtls_rsa_context *rsa )
+static int pk_write_rsa_pubkey(unsigned char **p, unsigned char *start,
+                               mbedtls_rsa_context *rsa)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
     mbedtls_mpi T;
 
-    mbedtls_mpi_init( &T );
+    mbedtls_mpi_init(&T);
 
     /* Export E */
-    if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 ||
-         ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 )
+    if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||
+        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
         goto end_of_export;
+    }
     len += ret;
 
     /* Export N */
-    if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 ||
-         ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 )
+    if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||
+        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
         goto end_of_export;
+    }
     len += ret;
 
 end_of_export:
 
-    mbedtls_mpi_free( &T );
-    if( ret < 0 )
-        return( ret );
+    mbedtls_mpi_free(&T);
+    if (ret < 0) {
+        return ret;
+    }
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
-                                                 MBEDTLS_ASN1_SEQUENCE ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED |
+                                                     MBEDTLS_ASN1_SEQUENCE));
 
-    return( (int) len );
+    return (int) len;
 }
 #endif /* MBEDTLS_RSA_C */
 
@@ -108,27 +102,27 @@
 /*
  * EC public key is an EC point
  */
-static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
-                               mbedtls_ecp_keypair *ec )
+static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
+                              mbedtls_ecp_keypair *ec)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
     unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN];
 
-    if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q,
-                                        MBEDTLS_ECP_PF_UNCOMPRESSED,
-                                        &len, buf, sizeof( buf ) ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q,
+                                              MBEDTLS_ECP_PF_UNCOMPRESSED,
+                                              &len, buf, sizeof(buf))) != 0) {
+        return ret;
     }
 
-    if( *p < start || (size_t)( *p - start ) < len )
-        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    if (*p < start || (size_t) (*p - start) < len) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    }
 
     *p -= len;
-    memcpy( *p, buf, len );
+    memcpy(*p, buf, len);
 
-    return( (int) len );
+    return (int) len;
 }
 
 /*
@@ -136,93 +130,86 @@
  *   namedCurve         OBJECT IDENTIFIER
  * }
  */
-static int pk_write_ec_param( unsigned char **p, unsigned char *start,
-                              mbedtls_ecp_keypair *ec )
+static int pk_write_ec_param(unsigned char **p, unsigned char *start,
+                             mbedtls_ecp_keypair *ec)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
     const char *oid;
     size_t oid_len;
 
-    if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_oid_get_oid_by_ec_grp(ec->grp.id, &oid, &oid_len)) != 0) {
+        return ret;
+    }
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
 
-    return( (int) len );
+    return (int) len;
 }
 
 /*
  * privateKey  OCTET STRING -- always of length ceil(log2(n)/8)
  */
-static int pk_write_ec_private( unsigned char **p, unsigned char *start,
-                                mbedtls_ecp_keypair *ec )
+static int pk_write_ec_private(unsigned char **p, unsigned char *start,
+                               mbedtls_ecp_keypair *ec)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t byte_length = ( ec->grp.pbits + 7 ) / 8;
+    size_t byte_length = (ec->grp.pbits + 7) / 8;
     unsigned char tmp[MBEDTLS_ECP_MAX_BYTES];
 
-    ret = mbedtls_ecp_write_key( ec, tmp, byte_length );
-    if( ret != 0 )
+    ret = mbedtls_ecp_write_key(ec, tmp, byte_length);
+    if (ret != 0) {
         goto exit;
-    ret = mbedtls_asn1_write_octet_string( p, start, tmp, byte_length );
+    }
+    ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
 
 exit:
-    mbedtls_platform_zeroize( tmp, byte_length );
-    return( ret );
+    mbedtls_platform_zeroize(tmp, byte_length);
+    return ret;
 }
 #endif /* MBEDTLS_ECP_C */
 
-int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,
-                             const mbedtls_pk_context *key )
+int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,
+                            const mbedtls_pk_context *key)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
-    PK_VALIDATE_RET( p != NULL );
-    PK_VALIDATE_RET( *p != NULL );
-    PK_VALIDATE_RET( start != NULL );
-    PK_VALIDATE_RET( key != NULL );
-
 #if defined(MBEDTLS_RSA_C)
-    if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
-        MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) );
-    else
+    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
+        MBEDTLS_ASN1_CHK_ADD(len, pk_write_rsa_pubkey(p, start, mbedtls_pk_rsa(*key)));
+    } else
 #endif
 #if defined(MBEDTLS_ECP_C)
-    if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
-        MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) );
-    else
+    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
+        MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, mbedtls_pk_ec(*key)));
+    } else
 #endif
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_OPAQUE )
-    {
+    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) {
         size_t buffer_size;
-        psa_key_id_t* key_id = (psa_key_id_t*) key->pk_ctx;
+        mbedtls_svc_key_id_t *key_id = (mbedtls_svc_key_id_t *) key->pk_ctx;
 
-        if ( *p < start )
-            return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
-
-        buffer_size = (size_t)( *p - start );
-        if ( psa_export_public_key( *key_id, start, buffer_size, &len )
-             != PSA_SUCCESS )
-        {
-            return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+        if (*p < start) {
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
         }
-        else
-        {
+
+        buffer_size = (size_t) (*p - start);
+        if (psa_export_public_key(*key_id, start, buffer_size, &len)
+            != PSA_SUCCESS) {
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+        } else {
             *p -= len;
-            memmove( *p, start, len );
+            memmove(*p, start, len);
         }
-    }
-    else
+    } else
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
-        return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
 
-    return( (int) len );
+    return (int) len;
 }
 
-int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )
+int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *c;
@@ -230,17 +217,17 @@
     mbedtls_pk_type_t pk_type;
     const char *oid;
 
-    PK_VALIDATE_RET( key != NULL );
-    if( size == 0 )
-        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
-    PK_VALIDATE_RET( buf != NULL );
+    if (size == 0) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    }
 
     c = buf + size;
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key));
 
-    if( c - buf < 1 )
-        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    if (c - buf < 1) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    }
 
     /*
      *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
@@ -250,162 +237,176 @@
     *--c = 0;
     len += 1;
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));
 
-    pk_type = mbedtls_pk_get_type( key );
+    pk_type = mbedtls_pk_get_type(key);
 #if defined(MBEDTLS_ECP_C)
-    if( pk_type == MBEDTLS_PK_ECKEY )
-    {
-        MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) );
+    if (pk_type == MBEDTLS_PK_ECKEY) {
+        MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, mbedtls_pk_ec(*key)));
     }
 #endif
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( pk_type == MBEDTLS_PK_OPAQUE )
-    {
+    if (pk_type == MBEDTLS_PK_OPAQUE) {
         psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
         psa_key_type_t key_type;
-        psa_key_id_t key_id;
+        mbedtls_svc_key_id_t key_id;
         psa_ecc_family_t curve;
         size_t bits;
 
-        key_id = *((psa_key_id_t*) key->pk_ctx );
-        if( PSA_SUCCESS != psa_get_key_attributes( key_id, &attributes ) )
-            return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
-        key_type = psa_get_key_type( &attributes );
-        bits = psa_get_key_bits( &attributes );
-        psa_reset_key_attributes( &attributes );
+        key_id = *((mbedtls_svc_key_id_t *) key->pk_ctx);
+        if (PSA_SUCCESS != psa_get_key_attributes(key_id, &attributes)) {
+            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+        }
+        key_type = psa_get_key_type(&attributes);
+        bits = psa_get_key_bits(&attributes);
+        psa_reset_key_attributes(&attributes);
 
-        curve = PSA_KEY_TYPE_ECC_GET_FAMILY( key_type );
-        if( curve == 0 )
-            return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
+        if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) {
+            curve = PSA_KEY_TYPE_ECC_GET_FAMILY(key_type);
+            if (curve == 0) {
+                return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+            }
 
-        ret = mbedtls_psa_get_ecc_oid_from_id( curve, bits, &oid, &oid_len );
-        if( ret != 0 )
-            return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
+            ret = mbedtls_psa_get_ecc_oid_from_id(curve, bits,
+                                                  &oid, &oid_len);
+            if (ret != 0) {
+                return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+            }
 
-        /* Write EC algorithm parameters; that's akin
-         * to pk_write_ec_param() above. */
-        MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_oid( &c, buf,
-                                                               oid, oid_len ) );
+            /* Write EC algorithm parameters; that's akin
+             * to pk_write_ec_param() above. */
+            MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_oid(&c, buf,
+                                                                 oid,
+                                                                 oid_len));
 
-        /* The rest of the function works as for legacy EC contexts. */
-        pk_type = MBEDTLS_PK_ECKEY;
+            /* The rest of the function works as for legacy EC contexts. */
+            pk_type = MBEDTLS_PK_ECKEY;
+        } else if (PSA_KEY_TYPE_IS_RSA(key_type)) {
+            /* The rest of the function works as for legacy RSA contexts. */
+            pk_type = MBEDTLS_PK_RSA;
+        } else {
+            return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+        }
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-    if( ( ret = mbedtls_oid_get_oid_by_pk_alg( pk_type, &oid,
-                                               &oid_len ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid,
+                                             &oid_len)) != 0) {
+        return ret;
     }
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len,
-                                                        par_len ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier(&c, buf, oid, oid_len,
+                                                                      par_len));
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
-                                                MBEDTLS_ASN1_SEQUENCE ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
+                                                     MBEDTLS_ASN1_SEQUENCE));
 
-    return( (int) len );
+    return (int) len;
 }
 
-int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )
+int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *c;
     size_t len = 0;
 
-    PK_VALIDATE_RET( key != NULL );
-    if( size == 0 )
-        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
-    PK_VALIDATE_RET( buf != NULL );
+    if (size == 0) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    }
 
     c = buf + size;
 
 #if defined(MBEDTLS_RSA_C)
-    if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
-    {
+    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
         mbedtls_mpi T; /* Temporary holding the exported parameters */
-        mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key );
+        mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*key);
 
         /*
          * Export the parameters one after another to avoid simultaneous copies.
          */
 
-        mbedtls_mpi_init( &T );
+        mbedtls_mpi_init(&T);
 
         /* Export QP */
-        if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 ||
-            ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
+        if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 ||
+            (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
             goto end_of_export;
+        }
         len += ret;
 
         /* Export DQ */
-        if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 ||
-            ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
+        if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 ||
+            (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
             goto end_of_export;
+        }
         len += ret;
 
         /* Export DP */
-        if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 ||
-            ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
+        if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 ||
+            (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
             goto end_of_export;
+        }
         len += ret;
 
         /* Export Q */
-        if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
-                                         &T, NULL, NULL ) ) != 0 ||
-             ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
+        if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
+                                      &T, NULL, NULL)) != 0 ||
+            (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
             goto end_of_export;
+        }
         len += ret;
 
         /* Export P */
-        if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T,
-                                         NULL, NULL, NULL ) ) != 0 ||
-             ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
+        if ((ret = mbedtls_rsa_export(rsa, NULL, &T,
+                                      NULL, NULL, NULL)) != 0 ||
+            (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
             goto end_of_export;
+        }
         len += ret;
 
         /* Export D */
-        if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
-                                         NULL, &T, NULL ) ) != 0 ||
-             ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
+        if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
+                                      NULL, &T, NULL)) != 0 ||
+            (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
             goto end_of_export;
+        }
         len += ret;
 
         /* Export E */
-        if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
-                                         NULL, NULL, &T ) ) != 0 ||
-             ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
+        if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
+                                      NULL, NULL, &T)) != 0 ||
+            (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
             goto end_of_export;
+        }
         len += ret;
 
         /* Export N */
-        if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL,
-                                         NULL, NULL, NULL ) ) != 0 ||
-             ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
+        if ((ret = mbedtls_rsa_export(rsa, &T, NULL,
+                                      NULL, NULL, NULL)) != 0 ||
+            (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
             goto end_of_export;
+        }
         len += ret;
 
-    end_of_export:
+end_of_export:
 
-        mbedtls_mpi_free( &T );
-        if( ret < 0 )
-            return( ret );
+        mbedtls_mpi_free(&T);
+        if (ret < 0) {
+            return ret;
+        }
 
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) );
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c,
-                                               buf, MBEDTLS_ASN1_CONSTRUCTED |
-                                               MBEDTLS_ASN1_SEQUENCE ) );
-    }
-    else
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0));
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c,
+                                                         buf, MBEDTLS_ASN1_CONSTRUCTED |
+                                                         MBEDTLS_ASN1_SEQUENCE));
+    } else
 #endif /* MBEDTLS_RSA_C */
 #if defined(MBEDTLS_ECP_C)
-    if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
-    {
-        mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key );
+    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
+        mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*key);
         size_t pub_len = 0, par_len = 0;
 
         /*
@@ -420,44 +421,46 @@
          */
 
         /* publicKey */
-        MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) );
+        MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(&c, buf, ec));
 
-        if( c - buf < 1 )
-            return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+        if (c - buf < 1) {
+            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+        }
         *--c = 0;
         pub_len += 1;
 
-        MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) );
-        MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) );
+        MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len));
+        MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));
 
-        MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) );
-        MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf,
-                            MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) );
+        MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len));
+        MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(&c, buf,
+                                                             MBEDTLS_ASN1_CONTEXT_SPECIFIC |
+                                                             MBEDTLS_ASN1_CONSTRUCTED | 1));
         len += pub_len;
 
         /* parameters */
-        MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) );
+        MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec));
 
-        MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) );
-        MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf,
-                            MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
+        MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(&c, buf, par_len));
+        MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(&c, buf,
+                                                             MBEDTLS_ASN1_CONTEXT_SPECIFIC |
+                                                             MBEDTLS_ASN1_CONSTRUCTED | 0));
         len += par_len;
 
         /* privateKey */
-        MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_private( &c, buf, ec ) );
+        MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(&c, buf, ec));
 
         /* version */
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) );
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 1));
 
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
-                                                    MBEDTLS_ASN1_SEQUENCE ) );
-    }
-    else
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
+                                                         MBEDTLS_ASN1_SEQUENCE));
+    } else
 #endif /* MBEDTLS_ECP_C */
-        return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
 
-    return( (int) len );
+    return (int) len;
 }
 
 #if defined(MBEDTLS_PEM_WRITE_C)
@@ -470,153 +473,65 @@
 #define PEM_BEGIN_PRIVATE_KEY_EC    "-----BEGIN EC PRIVATE KEY-----\n"
 #define PEM_END_PRIVATE_KEY_EC      "-----END EC PRIVATE KEY-----\n"
 
-/*
- * Max sizes of key per types. Shown as tag + len (+ content).
- */
+#define PUB_DER_MAX_BYTES                                                   \
+    (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \
+     MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES)
+#define PRV_DER_MAX_BYTES                                                   \
+    (MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \
+     MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES)
 
-#if defined(MBEDTLS_RSA_C)
-/*
- * RSA public keys:
- *  SubjectPublicKeyInfo  ::=  SEQUENCE  {          1 + 3
- *       algorithm            AlgorithmIdentifier,  1 + 1 (sequence)
- *                                                + 1 + 1 + 9 (rsa oid)
- *                                                + 1 + 1 (params null)
- *       subjectPublicKey     BIT STRING }          1 + 3 + (1 + below)
- *  RSAPublicKey ::= SEQUENCE {                     1 + 3
- *      modulus           INTEGER,  -- n            1 + 3 + MPI_MAX + 1
- *      publicExponent    INTEGER   -- e            1 + 3 + MPI_MAX + 1
- *  }
- */
-#define RSA_PUB_DER_MAX_BYTES   ( 38 + 2 * MBEDTLS_MPI_MAX_SIZE )
-
-/*
- * RSA private keys:
- *  RSAPrivateKey ::= SEQUENCE {                    1 + 3
- *      version           Version,                  1 + 1 + 1
- *      modulus           INTEGER,                  1 + 3 + MPI_MAX + 1
- *      publicExponent    INTEGER,                  1 + 3 + MPI_MAX + 1
- *      privateExponent   INTEGER,                  1 + 3 + MPI_MAX + 1
- *      prime1            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
- *      prime2            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
- *      exponent1         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
- *      exponent2         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
- *      coefficient       INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
- *      otherPrimeInfos   OtherPrimeInfos OPTIONAL  0 (not supported)
- *  }
- */
-#define MPI_MAX_SIZE_2          ( MBEDTLS_MPI_MAX_SIZE / 2 + \
-                                  MBEDTLS_MPI_MAX_SIZE % 2 )
-#define RSA_PRV_DER_MAX_BYTES   ( 47 + 3 * MBEDTLS_MPI_MAX_SIZE \
-                                   + 5 * MPI_MAX_SIZE_2 )
-
-#else /* MBEDTLS_RSA_C */
-
-#define RSA_PUB_DER_MAX_BYTES   0
-#define RSA_PRV_DER_MAX_BYTES   0
-
-#endif /* MBEDTLS_RSA_C */
-
-#if defined(MBEDTLS_ECP_C)
-/*
- * EC public keys:
- *  SubjectPublicKeyInfo  ::=  SEQUENCE  {      1 + 2
- *    algorithm         AlgorithmIdentifier,    1 + 1 (sequence)
- *                                            + 1 + 1 + 7 (ec oid)
- *                                            + 1 + 1 + 9 (namedCurve oid)
- *    subjectPublicKey  BIT STRING              1 + 2 + 1               [1]
- *                                            + 1 (point format)        [1]
- *                                            + 2 * ECP_MAX (coords)    [1]
- *  }
- */
-#define ECP_PUB_DER_MAX_BYTES   ( 30 + 2 * MBEDTLS_ECP_MAX_BYTES )
-
-/*
- * EC private keys:
- * ECPrivateKey ::= SEQUENCE {                  1 + 2
- *      version        INTEGER ,                1 + 1 + 1
- *      privateKey     OCTET STRING,            1 + 1 + ECP_MAX
- *      parameters [0] ECParameters OPTIONAL,   1 + 1 + (1 + 1 + 9)
- *      publicKey  [1] BIT STRING OPTIONAL      1 + 2 + [1] above
- *    }
- */
-#define ECP_PRV_DER_MAX_BYTES   ( 29 + 3 * MBEDTLS_ECP_MAX_BYTES )
-
-#else /* MBEDTLS_ECP_C */
-
-#define ECP_PUB_DER_MAX_BYTES   0
-#define ECP_PRV_DER_MAX_BYTES   0
-
-#endif /* MBEDTLS_ECP_C */
-
-#define PUB_DER_MAX_BYTES   ( RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
-                              RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES )
-#define PRV_DER_MAX_BYTES   ( RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \
-                              RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES )
-
-int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
+int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char output_buf[PUB_DER_MAX_BYTES];
     size_t olen = 0;
 
-    PK_VALIDATE_RET( key != NULL );
-    PK_VALIDATE_RET( buf != NULL || size == 0 );
-
-    if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf,
-                                     sizeof(output_buf) ) ) < 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf,
+                                           sizeof(output_buf))) < 0) {
+        return ret;
     }
 
-    if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
-                                  output_buf + sizeof(output_buf) - ret,
-                                  ret, buf, size, &olen ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
+                                        output_buf + sizeof(output_buf) - ret,
+                                        ret, buf, size, &olen)) != 0) {
+        return ret;
     }
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
+int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char output_buf[PRV_DER_MAX_BYTES];
     const char *begin, *end;
     size_t olen = 0;
 
-    PK_VALIDATE_RET( key != NULL );
-    PK_VALIDATE_RET( buf != NULL || size == 0 );
-
-    if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 )
-        return( ret );
+    if ((ret = mbedtls_pk_write_key_der(key, output_buf, sizeof(output_buf))) < 0) {
+        return ret;
+    }
 
 #if defined(MBEDTLS_RSA_C)
-    if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
-    {
+    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
         begin = PEM_BEGIN_PRIVATE_KEY_RSA;
         end = PEM_END_PRIVATE_KEY_RSA;
-    }
-    else
+    } else
 #endif
 #if defined(MBEDTLS_ECP_C)
-    if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
-    {
+    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
         begin = PEM_BEGIN_PRIVATE_KEY_EC;
         end = PEM_END_PRIVATE_KEY_EC;
-    }
-    else
+    } else
 #endif
-        return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
 
-    if( ( ret = mbedtls_pem_write_buffer( begin, end,
-                                  output_buf + sizeof(output_buf) - ret,
-                                  ret, buf, size, &olen ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_pem_write_buffer(begin, end,
+                                        output_buf + sizeof(output_buf) - ret,
+                                        ret, buf, size, &olen)) != 0) {
+        return ret;
     }
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_PEM_WRITE_C */
 
diff --git a/lib/libmbedtls/mbedtls/library/pkwrite.h b/lib/libmbedtls/mbedtls/library/pkwrite.h
new file mode 100644
index 0000000..8aebd0c
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/pkwrite.h
@@ -0,0 +1,108 @@
+/**
+ * \file pkwrite.h
+ *
+ * \brief Internal defines shared by the PK write module
+ */
+/*
+ *  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_PK_WRITE_H
+#define MBEDTLS_PK_WRITE_H
+
+#include "mbedtls/build_info.h"
+
+#include "mbedtls/pk.h"
+
+/*
+ * Max sizes of key per types. Shown as tag + len (+ content).
+ */
+
+#if defined(MBEDTLS_RSA_C)
+/*
+ * RSA public keys:
+ *  SubjectPublicKeyInfo  ::=  SEQUENCE  {          1 + 3
+ *       algorithm            AlgorithmIdentifier,  1 + 1 (sequence)
+ *                                                + 1 + 1 + 9 (rsa oid)
+ *                                                + 1 + 1 (params null)
+ *       subjectPublicKey     BIT STRING }          1 + 3 + (1 + below)
+ *  RSAPublicKey ::= SEQUENCE {                     1 + 3
+ *      modulus           INTEGER,  -- n            1 + 3 + MPI_MAX + 1
+ *      publicExponent    INTEGER   -- e            1 + 3 + MPI_MAX + 1
+ *  }
+ */
+#define MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES    (38 + 2 * MBEDTLS_MPI_MAX_SIZE)
+
+/*
+ * RSA private keys:
+ *  RSAPrivateKey ::= SEQUENCE {                    1 + 3
+ *      version           Version,                  1 + 1 + 1
+ *      modulus           INTEGER,                  1 + 3 + MPI_MAX + 1
+ *      publicExponent    INTEGER,                  1 + 3 + MPI_MAX + 1
+ *      privateExponent   INTEGER,                  1 + 3 + MPI_MAX + 1
+ *      prime1            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
+ *      prime2            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
+ *      exponent1         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
+ *      exponent2         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
+ *      coefficient       INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
+ *      otherPrimeInfos   OtherPrimeInfos OPTIONAL  0 (not supported)
+ *  }
+ */
+#define MBEDTLS_MPI_MAX_SIZE_2  (MBEDTLS_MPI_MAX_SIZE / 2 + \
+                                 MBEDTLS_MPI_MAX_SIZE % 2)
+#define MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES    (47 + 3 * MBEDTLS_MPI_MAX_SIZE \
+                                             + 5 * MBEDTLS_MPI_MAX_SIZE_2)
+
+#else /* MBEDTLS_RSA_C */
+
+#define MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES   0
+#define MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES   0
+
+#endif /* MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_ECP_C)
+/*
+ * EC public keys:
+ *  SubjectPublicKeyInfo  ::=  SEQUENCE  {      1 + 2
+ *    algorithm         AlgorithmIdentifier,    1 + 1 (sequence)
+ *                                            + 1 + 1 + 7 (ec oid)
+ *                                            + 1 + 1 + 9 (namedCurve oid)
+ *    subjectPublicKey  BIT STRING              1 + 2 + 1               [1]
+ *                                            + 1 (point format)        [1]
+ *                                            + 2 * ECP_MAX (coords)    [1]
+ *  }
+ */
+#define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES    (30 + 2 * MBEDTLS_ECP_MAX_BYTES)
+
+/*
+ * EC private keys:
+ * ECPrivateKey ::= SEQUENCE {                  1 + 2
+ *      version        INTEGER ,                1 + 1 + 1
+ *      privateKey     OCTET STRING,            1 + 1 + ECP_MAX
+ *      parameters [0] ECParameters OPTIONAL,   1 + 1 + (1 + 1 + 9)
+ *      publicKey  [1] BIT STRING OPTIONAL      1 + 2 + [1] above
+ *    }
+ */
+#define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES    (29 + 3 * MBEDTLS_ECP_MAX_BYTES)
+
+#else /* MBEDTLS_ECP_C */
+
+#define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES   0
+#define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES   0
+
+#endif /* MBEDTLS_ECP_C */
+
+#endif /* MBEDTLS_PK_WRITE_H */
diff --git a/lib/libmbedtls/mbedtls/library/platform.c b/lib/libmbedtls/mbedtls/library/platform.c
index e742fde..b15b7b2 100644
--- a/lib/libmbedtls/mbedtls/library/platform.c
+++ b/lib/libmbedtls/mbedtls/library/platform.c
@@ -30,22 +30,22 @@
  * configuration via mbedtls_platform_set_calloc_free(). So, omit everything
  * related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */
 #if defined(MBEDTLS_PLATFORM_MEMORY) &&                 \
-    !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&        \
-       defined(MBEDTLS_PLATFORM_FREE_MACRO) )
+    !(defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&        \
+    defined(MBEDTLS_PLATFORM_FREE_MACRO))
 
 #if !defined(MBEDTLS_PLATFORM_STD_CALLOC)
-static void *platform_calloc_uninit( size_t n, size_t size )
+static void *platform_calloc_uninit(size_t n, size_t size)
 {
     ((void) n);
     ((void) size);
-    return( NULL );
+    return NULL;
 }
 
 #define MBEDTLS_PLATFORM_STD_CALLOC   platform_calloc_uninit
 #endif /* !MBEDTLS_PLATFORM_STD_CALLOC */
 
 #if !defined(MBEDTLS_PLATFORM_STD_FREE)
-static void platform_free_uninit( void *ptr )
+static void platform_free_uninit(void *ptr)
 {
     ((void) ptr);
 }
@@ -53,25 +53,25 @@
 #define MBEDTLS_PLATFORM_STD_FREE     platform_free_uninit
 #endif /* !MBEDTLS_PLATFORM_STD_FREE */
 
-static void * (*mbedtls_calloc_func)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC;
-static void (*mbedtls_free_func)( void * ) = MBEDTLS_PLATFORM_STD_FREE;
+static void * (*mbedtls_calloc_func)(size_t, size_t) = MBEDTLS_PLATFORM_STD_CALLOC;
+static void (*mbedtls_free_func)(void *) = MBEDTLS_PLATFORM_STD_FREE;
 
-void * mbedtls_calloc( size_t nmemb, size_t size )
+void *mbedtls_calloc(size_t nmemb, size_t size)
 {
-    return (*mbedtls_calloc_func)( nmemb, size );
+    return (*mbedtls_calloc_func)(nmemb, size);
 }
 
-void mbedtls_free( void * ptr )
+void mbedtls_free(void *ptr)
 {
-    (*mbedtls_free_func)( ptr );
+    (*mbedtls_free_func)(ptr);
 }
 
-int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ),
-                              void (*free_func)( void * ) )
+int mbedtls_platform_set_calloc_free(void *(*calloc_func)(size_t, size_t),
+                                     void (*free_func)(void *))
 {
     mbedtls_calloc_func = calloc_func;
     mbedtls_free_func = free_func;
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_PLATFORM_MEMORY &&
           !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&
@@ -79,16 +79,16 @@
 
 #if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF)
 #include <stdarg.h>
-int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... )
+int mbedtls_platform_win32_snprintf(char *s, size_t n, const char *fmt, ...)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     va_list argp;
 
-    va_start( argp, fmt );
-    ret = mbedtls_vsnprintf( s, n, fmt, argp );
-    va_end( argp );
+    va_start(argp, fmt);
+    ret = mbedtls_vsnprintf(s, n, fmt, argp);
+    va_end(argp);
 
-    return( ret );
+    return ret;
 }
 #endif
 
@@ -97,53 +97,53 @@
 /*
  * Make dummy function to prevent NULL pointer dereferences
  */
-static int platform_snprintf_uninit( char * s, size_t n,
-                                     const char * format, ... )
+static int platform_snprintf_uninit(char *s, size_t n,
+                                    const char *format, ...)
 {
     ((void) s);
     ((void) n);
     ((void) format);
-    return( 0 );
+    return 0;
 }
 
 #define MBEDTLS_PLATFORM_STD_SNPRINTF    platform_snprintf_uninit
 #endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */
 
-int (*mbedtls_snprintf)( char * s, size_t n,
-                          const char * format,
-                          ... ) = MBEDTLS_PLATFORM_STD_SNPRINTF;
+int (*mbedtls_snprintf)(char *s, size_t n,
+                        const char *format,
+                        ...) = MBEDTLS_PLATFORM_STD_SNPRINTF;
 
-int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n,
-                                                 const char * format,
-                                                 ... ) )
+int mbedtls_platform_set_snprintf(int (*snprintf_func)(char *s, size_t n,
+                                                       const char *format,
+                                                       ...))
 {
     mbedtls_snprintf = snprintf_func;
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
 
 #if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF)
 #include <stdarg.h>
-int mbedtls_platform_win32_vsnprintf( char *s, size_t n, const char *fmt, va_list arg )
+int mbedtls_platform_win32_vsnprintf(char *s, size_t n, const char *fmt, va_list arg)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     /* Avoid calling the invalid parameter handler by checking ourselves */
-    if( s == NULL || n == 0 || fmt == NULL )
-        return( -1 );
+    if (s == NULL || n == 0 || fmt == NULL) {
+        return -1;
+    }
 
 #if defined(_TRUNCATE)
-    ret = vsnprintf_s( s, n, _TRUNCATE, fmt, arg );
+    ret = vsnprintf_s(s, n, _TRUNCATE, fmt, arg);
 #else
-    ret = vsnprintf( s, n, fmt, arg );
-    if( ret < 0 || (size_t) ret == n )
-    {
+    ret = vsnprintf(s, n, fmt, arg);
+    if (ret < 0 || (size_t) ret == n) {
         s[n-1] = '\0';
         ret = -1;
     }
 #endif
 
-    return( ret );
+    return ret;
 }
 #endif
 
@@ -152,29 +152,29 @@
 /*
  * Make dummy function to prevent NULL pointer dereferences
  */
-static int platform_vsnprintf_uninit( char * s, size_t n,
-                                     const char * format, va_list arg )
+static int platform_vsnprintf_uninit(char *s, size_t n,
+                                     const char *format, va_list arg)
 {
     ((void) s);
     ((void) n);
     ((void) format);
     ((void) arg);
-    return( -1 );
+    return -1;
 }
 
 #define MBEDTLS_PLATFORM_STD_VSNPRINTF    platform_vsnprintf_uninit
 #endif /* !MBEDTLS_PLATFORM_STD_VSNPRINTF */
 
-int (*mbedtls_vsnprintf)( char * s, size_t n,
-                          const char * format,
-                          va_list arg ) = MBEDTLS_PLATFORM_STD_VSNPRINTF;
+int (*mbedtls_vsnprintf)(char *s, size_t n,
+                         const char *format,
+                         va_list arg) = MBEDTLS_PLATFORM_STD_VSNPRINTF;
 
-int mbedtls_platform_set_vsnprintf( int (*vsnprintf_func)( char * s, size_t n,
-                                                 const char * format,
-                                                 va_list arg ) )
+int mbedtls_platform_set_vsnprintf(int (*vsnprintf_func)(char *s, size_t n,
+                                                         const char *format,
+                                                         va_list arg))
 {
     mbedtls_vsnprintf = vsnprintf_func;
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */
 
@@ -183,21 +183,21 @@
 /*
  * Make dummy function to prevent NULL pointer dereferences
  */
-static int platform_printf_uninit( const char *format, ... )
+static int platform_printf_uninit(const char *format, ...)
 {
     ((void) format);
-    return( 0 );
+    return 0;
 }
 
 #define MBEDTLS_PLATFORM_STD_PRINTF    platform_printf_uninit
 #endif /* !MBEDTLS_PLATFORM_STD_PRINTF */
 
-int (*mbedtls_printf)( const char *, ... ) = MBEDTLS_PLATFORM_STD_PRINTF;
+int (*mbedtls_printf)(const char *, ...) = MBEDTLS_PLATFORM_STD_PRINTF;
 
-int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) )
+int mbedtls_platform_set_printf(int (*printf_func)(const char *, ...))
 {
     mbedtls_printf = printf_func;
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_PLATFORM_PRINTF_ALT */
 
@@ -206,32 +206,54 @@
 /*
  * Make dummy function to prevent NULL pointer dereferences
  */
-static int platform_fprintf_uninit( FILE *stream, const char *format, ... )
+static int platform_fprintf_uninit(FILE *stream, const char *format, ...)
 {
     ((void) stream);
     ((void) format);
-    return( 0 );
+    return 0;
 }
 
 #define MBEDTLS_PLATFORM_STD_FPRINTF   platform_fprintf_uninit
 #endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */
 
-int (*mbedtls_fprintf)( FILE *, const char *, ... ) =
-                                        MBEDTLS_PLATFORM_STD_FPRINTF;
+int (*mbedtls_fprintf)(FILE *, const char *, ...) =
+    MBEDTLS_PLATFORM_STD_FPRINTF;
 
-int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) )
+int mbedtls_platform_set_fprintf(int (*fprintf_func)(FILE *, const char *, ...))
 {
     mbedtls_fprintf = fprintf_func;
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */
 
+#if defined(MBEDTLS_PLATFORM_SETBUF_ALT)
+#if !defined(MBEDTLS_PLATFORM_STD_SETBUF)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static void platform_setbuf_uninit(FILE *stream, char *buf)
+{
+    ((void) stream);
+    ((void) buf);
+}
+
+#define MBEDTLS_PLATFORM_STD_SETBUF   platform_setbuf_uninit
+#endif /* !MBEDTLS_PLATFORM_STD_SETBUF */
+void (*mbedtls_setbuf)(FILE *stream, char *buf) = MBEDTLS_PLATFORM_STD_SETBUF;
+
+int mbedtls_platform_set_setbuf(void (*setbuf_func)(FILE *stream, char *buf))
+{
+    mbedtls_setbuf = setbuf_func;
+    return 0;
+}
+#endif /* MBEDTLS_PLATFORM_SETBUF_ALT */
+
 #if defined(MBEDTLS_PLATFORM_EXIT_ALT)
 #if !defined(MBEDTLS_PLATFORM_STD_EXIT)
 /*
  * Make dummy function to prevent NULL pointer dereferences
  */
-static void platform_exit_uninit( int status )
+static void platform_exit_uninit(int status)
 {
     ((void) status);
 }
@@ -239,12 +261,12 @@
 #define MBEDTLS_PLATFORM_STD_EXIT   platform_exit_uninit
 #endif /* !MBEDTLS_PLATFORM_STD_EXIT */
 
-void (*mbedtls_exit)( int status ) = MBEDTLS_PLATFORM_STD_EXIT;
+void (*mbedtls_exit)(int status) = MBEDTLS_PLATFORM_STD_EXIT;
 
-int mbedtls_platform_set_exit( void (*exit_func)( int status ) )
+int mbedtls_platform_set_exit(void (*exit_func)(int status))
 {
     mbedtls_exit = exit_func;
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_PLATFORM_EXIT_ALT */
 
@@ -255,21 +277,21 @@
 /*
  * Make dummy function to prevent NULL pointer dereferences
  */
-static mbedtls_time_t platform_time_uninit( mbedtls_time_t* timer )
+static mbedtls_time_t platform_time_uninit(mbedtls_time_t *timer)
 {
     ((void) timer);
-    return( 0 );
+    return 0;
 }
 
 #define MBEDTLS_PLATFORM_STD_TIME   platform_time_uninit
 #endif /* !MBEDTLS_PLATFORM_STD_TIME */
 
-mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* timer ) = MBEDTLS_PLATFORM_STD_TIME;
+mbedtls_time_t (*mbedtls_time)(mbedtls_time_t *timer) = MBEDTLS_PLATFORM_STD_TIME;
 
-int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* timer ) )
+int mbedtls_platform_set_time(mbedtls_time_t (*time_func)(mbedtls_time_t *timer))
 {
     mbedtls_time = time_func;
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_PLATFORM_TIME_ALT */
 
@@ -280,41 +302,47 @@
 /* Default implementations for the platform independent seed functions use
  * standard libc file functions to read from and write to a pre-defined filename
  */
-int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len )
+int mbedtls_platform_std_nv_seed_read(unsigned char *buf, size_t buf_len)
 {
     FILE *file;
     size_t n;
 
-    if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL )
-        return( -1 );
-
-    if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len )
-    {
-        fclose( file );
-        mbedtls_platform_zeroize( buf, buf_len );
-        return( -1 );
+    if ((file = fopen(MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb")) == NULL) {
+        return -1;
     }
 
-    fclose( file );
-    return( (int)n );
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf(file, NULL);
+
+    if ((n = fread(buf, 1, buf_len, file)) != buf_len) {
+        fclose(file);
+        mbedtls_platform_zeroize(buf, buf_len);
+        return -1;
+    }
+
+    fclose(file);
+    return (int) n;
 }
 
-int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len )
+int mbedtls_platform_std_nv_seed_write(unsigned char *buf, size_t buf_len)
 {
     FILE *file;
     size_t n;
 
-    if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL )
-        return -1;
-
-    if( ( n = fwrite( buf, 1, buf_len, file ) ) != buf_len )
-    {
-        fclose( file );
+    if ((file = fopen(MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w")) == NULL) {
         return -1;
     }
 
-    fclose( file );
-    return( (int)n );
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf(file, NULL);
+
+    if ((n = fwrite(buf, 1, buf_len, file)) != buf_len) {
+        fclose(file);
+        return -1;
+    }
+
+    fclose(file);
+    return (int) n;
 }
 #endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */
 
@@ -323,11 +351,11 @@
 /*
  * Make dummy function to prevent NULL pointer dereferences
  */
-static int platform_nv_seed_read_uninit( unsigned char *buf, size_t buf_len )
+static int platform_nv_seed_read_uninit(unsigned char *buf, size_t buf_len)
 {
     ((void) buf);
     ((void) buf_len);
-    return( -1 );
+    return -1;
 }
 
 #define MBEDTLS_PLATFORM_STD_NV_SEED_READ   platform_nv_seed_read_uninit
@@ -337,28 +365,28 @@
 /*
  * Make dummy function to prevent NULL pointer dereferences
  */
-static int platform_nv_seed_write_uninit( unsigned char *buf, size_t buf_len )
+static int platform_nv_seed_write_uninit(unsigned char *buf, size_t buf_len)
 {
     ((void) buf);
     ((void) buf_len);
-    return( -1 );
+    return -1;
 }
 
 #define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE   platform_nv_seed_write_uninit
 #endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */
 
-int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ) =
-            MBEDTLS_PLATFORM_STD_NV_SEED_READ;
-int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ) =
-            MBEDTLS_PLATFORM_STD_NV_SEED_WRITE;
+int (*mbedtls_nv_seed_read)(unsigned char *buf, size_t buf_len) =
+    MBEDTLS_PLATFORM_STD_NV_SEED_READ;
+int (*mbedtls_nv_seed_write)(unsigned char *buf, size_t buf_len) =
+    MBEDTLS_PLATFORM_STD_NV_SEED_WRITE;
 
 int mbedtls_platform_set_nv_seed(
-        int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ),
-        int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) )
+    int (*nv_seed_read_func)(unsigned char *buf, size_t buf_len),
+    int (*nv_seed_write_func)(unsigned char *buf, size_t buf_len))
 {
     mbedtls_nv_seed_read = nv_seed_read_func;
     mbedtls_nv_seed_write = nv_seed_write_func;
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */
 #endif /* MBEDTLS_ENTROPY_NV_SEED */
@@ -367,19 +395,19 @@
 /*
  * Placeholder platform setup that does nothing by default
  */
-int mbedtls_platform_setup( mbedtls_platform_context *ctx )
+int mbedtls_platform_setup(mbedtls_platform_context *ctx)
 {
-    (void)ctx;
+    (void) ctx;
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Placeholder platform teardown that does nothing by default
  */
-void mbedtls_platform_teardown( mbedtls_platform_context *ctx )
+void mbedtls_platform_teardown(mbedtls_platform_context *ctx)
 {
-    (void)ctx;
+    (void) ctx;
 }
 #endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */
 
diff --git a/lib/libmbedtls/mbedtls/library/platform_util.c b/lib/libmbedtls/mbedtls/library/platform_util.c
index 98fe5de..f891cd4 100644
--- a/lib/libmbedtls/mbedtls/library/platform_util.c
+++ b/lib/libmbedtls/mbedtls/library/platform_util.c
@@ -20,12 +20,18 @@
 
 /*
  * Ensure gmtime_r is available even with -std=c99; must be defined before
- * config.h, which pulls in glibc's features.h. Harmless on other platforms.
+ * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms
+ * except OpenBSD, where it stops us accessing explicit_bzero.
  */
-#if !defined(_POSIX_C_SOURCE)
+#if !defined(_POSIX_C_SOURCE) && !defined(__OpenBSD__)
 #define _POSIX_C_SOURCE 200112L
 #endif
 
+#if !defined(_GNU_SOURCE)
+/* Clang requires this to get support for explicit_bzero */
+#define _GNU_SOURCE
+#endif
+
 #include "common.h"
 
 #include "mbedtls/platform_util.h"
@@ -33,11 +39,40 @@
 #include "mbedtls/threading.h"
 
 #include <stddef.h>
+
+#ifndef __STDC_WANT_LIB_EXT1__
+#define __STDC_WANT_LIB_EXT1__ 1 /* Ask for the C11 gmtime_s() and memset_s() if available */
+#endif
 #include <string.h>
 
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
+// Detect platforms known to support explicit_bzero()
+#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25)
+#define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1
+#elif (defined(__FreeBSD__) && (__FreeBSD_version >= 1100037)) || defined(__OpenBSD__)
+#define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1
+#endif
+
 #if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT)
+
+#undef HAVE_MEMORY_SANITIZER
+#if defined(__has_feature)
+#if __has_feature(memory_sanitizer)
+#include <sanitizer/msan_interface.h>
+#define HAVE_MEMORY_SANITIZER
+#endif
+#endif
+
 /*
- * This implementation should never be optimized out by the compiler
+ * Where possible, we try to detect the presence of a platform-provided
+ * secure memset, such as explicit_bzero(), that is safe against being optimized
+ * out, and use that.
+ *
+ * For other platforms, we provide an implementation that aims not to be
+ * optimized out by the compiler.
  *
  * This implementation for mbedtls_platform_zeroize() was inspired from Colin
  * Percival's blog article at:
@@ -52,24 +87,45 @@
  * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for
  * details), optimizations of the following form are still possible:
  *
- * if( memset_func != memset )
- *     memset_func( buf, 0, len );
+ * if (memset_func != memset)
+ *     memset_func(buf, 0, len);
  *
  * Note that it is extremely difficult to guarantee that
- * mbedtls_platform_zeroize() will not be optimized out by aggressive compilers
+ * the memset() call will not be optimized out by aggressive compilers
  * in a portable way. For this reason, Mbed TLS also provides the configuration
  * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure
  * mbedtls_platform_zeroize() to use a suitable implementation for their
  * platform and needs.
  */
-static void * (* const volatile memset_func)( void *, int, size_t ) = memset;
+#if !defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO) && !defined(__STDC_LIB_EXT1__) \
+    && !defined(_WIN32)
+static void *(*const volatile memset_func)(void *, int, size_t) = memset;
+#endif
 
-void mbedtls_platform_zeroize( void *buf, size_t len )
+void mbedtls_platform_zeroize(void *buf, size_t len)
 {
-    MBEDTLS_INTERNAL_VALIDATE( len == 0 || buf != NULL );
+    MBEDTLS_INTERNAL_VALIDATE(len == 0 || buf != NULL);
 
-    if( len > 0 )
-        memset_func( buf, 0, len );
+    if (len > 0) {
+#if defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO)
+        explicit_bzero(buf, len);
+#if defined(HAVE_MEMORY_SANITIZER)
+        /* You'd think that Msan would recognize explicit_bzero() as
+         * equivalent to bzero(), but it actually doesn't on several
+         * platforms, including Linux (Ubuntu 20.04).
+         * https://github.com/google/sanitizers/issues/1507
+         * https://github.com/openssh/openssh-portable/commit/74433a19bb6f4cef607680fa4d1d7d81ca3826aa
+         */
+        __msan_unpoison(buf, len);
+#endif
+#elif defined(__STDC_LIB_EXT1__)
+        memset_s(buf, len, 0, len);
+#elif defined(_WIN32)
+        SecureZeroMemory(buf, len);
+#else
+        memset_func(buf, 0, len);
+#endif
+    }
 }
 #endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */
 
@@ -82,9 +138,9 @@
 #endif /* !_WIN32 && (unix || __unix || __unix__ ||
         * (__APPLE__ && __MACH__)) */
 
-#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) ||     \
-       ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) &&                     \
-         _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) )
+#if !((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) ||     \
+    (defined(_POSIX_THREAD_SAFE_FUNCTIONS) &&                     \
+    _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L))
 /*
  * This is a convenience shorthand macro to avoid checking the long
  * preprocessor conditions above. Ideally, we could expose this macro in
@@ -92,42 +148,74 @@
  * threading.h. However, this macro is not part of the Mbed TLS public API, so
  * we keep it private by only defining it in this file
  */
-#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) )
+#if !(defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)) || \
+    (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
 #define PLATFORM_UTIL_USE_GMTIME
-#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */
+#endif
 
-#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) ||     \
-             ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) &&                     \
+#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \
+             ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \
                 _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */
 
-struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt,
-                                      struct tm *tm_buf )
+struct tm *mbedtls_platform_gmtime_r(const mbedtls_time_t *tt,
+                                     struct tm *tm_buf)
 {
-#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
-    return( ( gmtime_s( tm_buf, tt ) == 0 ) ? tm_buf : NULL );
+#if defined(_WIN32) && !defined(PLATFORM_UTIL_USE_GMTIME)
+#if defined(__STDC_LIB_EXT1__)
+    return (gmtime_s(tt, tm_buf) == 0) ? NULL : tm_buf;
+#else
+    /* MSVC and mingw64 argument order and return value are inconsistent with the C11 standard */
+    return (gmtime_s(tm_buf, tt) == 0) ? tm_buf : NULL;
+#endif
 #elif !defined(PLATFORM_UTIL_USE_GMTIME)
-    return( gmtime_r( tt, tm_buf ) );
+    return gmtime_r(tt, tm_buf);
 #else
     struct tm *lt;
 
 #if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 )
-        return( NULL );
+    if (mbedtls_mutex_lock(&mbedtls_threading_gmtime_mutex) != 0) {
+        return NULL;
+    }
 #endif /* MBEDTLS_THREADING_C */
 
-    lt = gmtime( tt );
+    lt = gmtime(tt);
 
-    if( lt != NULL )
-    {
-        memcpy( tm_buf, lt, sizeof( struct tm ) );
+    if (lt != NULL) {
+        memcpy(tm_buf, lt, sizeof(struct tm));
     }
 
 #if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 )
-        return( NULL );
+    if (mbedtls_mutex_unlock(&mbedtls_threading_gmtime_mutex) != 0) {
+        return NULL;
+    }
 #endif /* MBEDTLS_THREADING_C */
 
-    return( ( lt == NULL ) ? NULL : tm_buf );
+    return (lt == NULL) ? NULL : tm_buf;
 #endif /* _WIN32 && !EFIX64 && !EFI32 */
 }
 #endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */
+
+#if defined(MBEDTLS_TEST_HOOKS)
+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/lib/libmbedtls/mbedtls/library/poly1305.c b/lib/libmbedtls/mbedtls/library/poly1305.c
index 7375a0c..f4e1d3f 100644
--- a/lib/libmbedtls/mbedtls/library/poly1305.c
+++ b/lib/libmbedtls/mbedtls/library/poly1305.c
@@ -28,36 +28,18 @@
 
 #include <string.h>
 
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
 
 #if !defined(MBEDTLS_POLY1305_ALT)
 
-#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
-    !defined(inline) && !defined(__cplusplus)
-#define inline __inline
-#endif
-
-/* Parameter validation macros */
-#define POLY1305_VALIDATE_RET( cond )                                       \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA )
-#define POLY1305_VALIDATE( cond )                                           \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
-
-#define POLY1305_BLOCK_SIZE_BYTES ( 16U )
+#define POLY1305_BLOCK_SIZE_BYTES (16U)
 
 /*
  * Our implementation is tuned for 32-bit platforms with a 64-bit multiplier.
  * However we provided an alternative for platforms without such a multiplier.
  */
 #if defined(MBEDTLS_NO_64BIT_MULTIPLICATION)
-static uint64_t mul64( uint32_t a, uint32_t b )
+static uint64_t mul64(uint32_t a, uint32_t b)
 {
     /* a = al + 2**16 ah, b = bl + 2**16 bh */
     const uint16_t al = (uint16_t) a;
@@ -67,15 +49,15 @@
 
     /* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */
     const uint32_t lo = (uint32_t) al * bl;
-    const uint64_t me = (uint64_t)( (uint32_t) ah * bl ) + (uint32_t) al * bh;
+    const uint64_t me = (uint64_t) ((uint32_t) ah * bl) + (uint32_t) al * bh;
     const uint32_t hi = (uint32_t) ah * bh;
 
-    return( lo + ( me << 16 ) + ( (uint64_t) hi << 32 ) );
+    return lo + (me << 16) + ((uint64_t) hi << 32);
 }
 #else
-static inline uint64_t mul64( uint32_t a, uint32_t b )
+static inline uint64_t mul64(uint32_t a, uint32_t b)
 {
-    return( (uint64_t) a * b );
+    return (uint64_t) a * b;
 }
 #endif
 
@@ -91,10 +73,10 @@
  *                          applied to the input data before calling this
  *                          function.  Otherwise, set this parameter to 1.
  */
-static void poly1305_process( mbedtls_poly1305_context *ctx,
-                              size_t nblocks,
-                              const unsigned char *input,
-                              uint32_t needs_padding )
+static void poly1305_process(mbedtls_poly1305_context *ctx,
+                             size_t nblocks,
+                             const unsigned char *input,
+                             uint32_t needs_padding)
 {
     uint64_t d0, d1, d2, d3;
     uint32_t acc0, acc1, acc2, acc3, acc4;
@@ -108,9 +90,9 @@
     r2 = ctx->r[2];
     r3 = ctx->r[3];
 
-    rs1 = r1 + ( r1 >> 2U );
-    rs2 = r2 + ( r2 >> 2U );
-    rs3 = r3 + ( r3 >> 2U );
+    rs1 = r1 + (r1 >> 2U);
+    rs2 = r2 + (r2 >> 2U);
+    rs3 = r3 + (r3 >> 2U);
 
     acc0 = ctx->acc[0];
     acc1 = ctx->acc[1];
@@ -119,67 +101,66 @@
     acc4 = ctx->acc[4];
 
     /* Process full blocks */
-    for( i = 0U; i < nblocks; i++ )
-    {
+    for (i = 0U; i < nblocks; i++) {
         /* The input block is treated as a 128-bit little-endian integer */
-        d0   = MBEDTLS_GET_UINT32_LE( input, offset + 0  );
-        d1   = MBEDTLS_GET_UINT32_LE( input, offset + 4  );
-        d2   = MBEDTLS_GET_UINT32_LE( input, offset + 8  );
-        d3   = MBEDTLS_GET_UINT32_LE( input, offset + 12 );
+        d0   = MBEDTLS_GET_UINT32_LE(input, offset + 0);
+        d1   = MBEDTLS_GET_UINT32_LE(input, offset + 4);
+        d2   = MBEDTLS_GET_UINT32_LE(input, offset + 8);
+        d3   = MBEDTLS_GET_UINT32_LE(input, offset + 12);
 
         /* Compute: acc += (padded) block as a 130-bit integer */
         d0  += (uint64_t) acc0;
-        d1  += (uint64_t) acc1 + ( d0 >> 32U );
-        d2  += (uint64_t) acc2 + ( d1 >> 32U );
-        d3  += (uint64_t) acc3 + ( d2 >> 32U );
+        d1  += (uint64_t) acc1 + (d0 >> 32U);
+        d2  += (uint64_t) acc2 + (d1 >> 32U);
+        d3  += (uint64_t) acc3 + (d2 >> 32U);
         acc0 = (uint32_t) d0;
         acc1 = (uint32_t) d1;
         acc2 = (uint32_t) d2;
         acc3 = (uint32_t) d3;
-        acc4 += (uint32_t) ( d3 >> 32U ) + needs_padding;
+        acc4 += (uint32_t) (d3 >> 32U) + needs_padding;
 
         /* Compute: acc *= r */
-        d0 = mul64( acc0, r0  ) +
-             mul64( acc1, rs3 ) +
-             mul64( acc2, rs2 ) +
-             mul64( acc3, rs1 );
-        d1 = mul64( acc0, r1  ) +
-             mul64( acc1, r0  ) +
-             mul64( acc2, rs3 ) +
-             mul64( acc3, rs2 ) +
-             mul64( acc4, rs1 );
-        d2 = mul64( acc0, r2  ) +
-             mul64( acc1, r1  ) +
-             mul64( acc2, r0  ) +
-             mul64( acc3, rs3 ) +
-             mul64( acc4, rs2 );
-        d3 = mul64( acc0, r3  ) +
-             mul64( acc1, r2  ) +
-             mul64( acc2, r1  ) +
-             mul64( acc3, r0  ) +
-             mul64( acc4, rs3 );
+        d0 = mul64(acc0, r0) +
+             mul64(acc1, rs3) +
+             mul64(acc2, rs2) +
+             mul64(acc3, rs1);
+        d1 = mul64(acc0, r1) +
+             mul64(acc1, r0) +
+             mul64(acc2, rs3) +
+             mul64(acc3, rs2) +
+             mul64(acc4, rs1);
+        d2 = mul64(acc0, r2) +
+             mul64(acc1, r1) +
+             mul64(acc2, r0) +
+             mul64(acc3, rs3) +
+             mul64(acc4, rs2);
+        d3 = mul64(acc0, r3) +
+             mul64(acc1, r2) +
+             mul64(acc2, r1) +
+             mul64(acc3, r0) +
+             mul64(acc4, rs3);
         acc4 *= r0;
 
         /* Compute: acc %= (2^130 - 5) (partial remainder) */
-        d1 += ( d0 >> 32 );
-        d2 += ( d1 >> 32 );
-        d3 += ( d2 >> 32 );
+        d1 += (d0 >> 32);
+        d2 += (d1 >> 32);
+        d3 += (d2 >> 32);
         acc0 = (uint32_t) d0;
         acc1 = (uint32_t) d1;
         acc2 = (uint32_t) d2;
         acc3 = (uint32_t) d3;
-        acc4 = (uint32_t) ( d3 >> 32 ) + acc4;
+        acc4 = (uint32_t) (d3 >> 32) + acc4;
 
-        d0 = (uint64_t) acc0 + ( acc4 >> 2 ) + ( acc4 & 0xFFFFFFFCU );
+        d0 = (uint64_t) acc0 + (acc4 >> 2) + (acc4 & 0xFFFFFFFCU);
         acc4 &= 3U;
         acc0 = (uint32_t) d0;
-        d0 = (uint64_t) acc1 + ( d0 >> 32U );
+        d0 = (uint64_t) acc1 + (d0 >> 32U);
         acc1 = (uint32_t) d0;
-        d0 = (uint64_t) acc2 + ( d0 >> 32U );
+        d0 = (uint64_t) acc2 + (d0 >> 32U);
         acc2 = (uint32_t) d0;
-        d0 = (uint64_t) acc3 + ( d0 >> 32U );
+        d0 = (uint64_t) acc3 + (d0 >> 32U);
         acc3 = (uint32_t) d0;
-        d0 = (uint64_t) acc4 + ( d0 >> 32U );
+        d0 = (uint64_t) acc4 + (d0 >> 32U);
         acc4 = (uint32_t) d0;
 
         offset    += POLY1305_BLOCK_SIZE_BYTES;
@@ -199,8 +180,8 @@
  * \param mac               The buffer to where the MAC is written. Must be
  *                          big enough to contain the 16-byte MAC.
  */
-static void poly1305_compute_mac( const mbedtls_poly1305_context *ctx,
-                                  unsigned char mac[16] )
+static void poly1305_compute_mac(const mbedtls_poly1305_context *ctx,
+                                 unsigned char mac[16])
 {
     uint64_t d;
     uint32_t g0, g1, g2, g3, g4;
@@ -220,73 +201,69 @@
      */
 
     /* Calculate acc + -(2^130 - 5) */
-    d  = ( (uint64_t) acc0 + 5U );
+    d  = ((uint64_t) acc0 + 5U);
     g0 = (uint32_t) d;
-    d  = ( (uint64_t) acc1 + ( d >> 32 ) );
+    d  = ((uint64_t) acc1 + (d >> 32));
     g1 = (uint32_t) d;
-    d  = ( (uint64_t) acc2 + ( d >> 32 ) );
+    d  = ((uint64_t) acc2 + (d >> 32));
     g2 = (uint32_t) d;
-    d  = ( (uint64_t) acc3 + ( d >> 32 ) );
+    d  = ((uint64_t) acc3 + (d >> 32));
     g3 = (uint32_t) d;
-    g4 = acc4 + (uint32_t) ( d >> 32U );
+    g4 = acc4 + (uint32_t) (d >> 32U);
 
     /* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */
-    mask = (uint32_t) 0U - ( g4 >> 2U );
+    mask = (uint32_t) 0U - (g4 >> 2U);
     mask_inv = ~mask;
 
     /* If 131st bit is set then acc=g, otherwise, acc is unmodified */
-    acc0 = ( acc0 & mask_inv ) | ( g0 & mask );
-    acc1 = ( acc1 & mask_inv ) | ( g1 & mask );
-    acc2 = ( acc2 & mask_inv ) | ( g2 & mask );
-    acc3 = ( acc3 & mask_inv ) | ( g3 & mask );
+    acc0 = (acc0 & mask_inv) | (g0 & mask);
+    acc1 = (acc1 & mask_inv) | (g1 & mask);
+    acc2 = (acc2 & mask_inv) | (g2 & mask);
+    acc3 = (acc3 & mask_inv) | (g3 & mask);
 
     /* Add 's' */
     d = (uint64_t) acc0 + ctx->s[0];
     acc0 = (uint32_t) d;
-    d = (uint64_t) acc1 + ctx->s[1] + ( d >> 32U );
+    d = (uint64_t) acc1 + ctx->s[1] + (d >> 32U);
     acc1 = (uint32_t) d;
-    d = (uint64_t) acc2 + ctx->s[2] + ( d >> 32U );
+    d = (uint64_t) acc2 + ctx->s[2] + (d >> 32U);
     acc2 = (uint32_t) d;
-    acc3 += ctx->s[3] + (uint32_t) ( d >> 32U );
+    acc3 += ctx->s[3] + (uint32_t) (d >> 32U);
 
     /* Compute MAC (128 least significant bits of the accumulator) */
-    MBEDTLS_PUT_UINT32_LE( acc0, mac,  0 );
-    MBEDTLS_PUT_UINT32_LE( acc1, mac,  4 );
-    MBEDTLS_PUT_UINT32_LE( acc2, mac,  8 );
-    MBEDTLS_PUT_UINT32_LE( acc3, mac, 12 );
+    MBEDTLS_PUT_UINT32_LE(acc0, mac,  0);
+    MBEDTLS_PUT_UINT32_LE(acc1, mac,  4);
+    MBEDTLS_PUT_UINT32_LE(acc2, mac,  8);
+    MBEDTLS_PUT_UINT32_LE(acc3, mac, 12);
 }
 
-void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx )
+void mbedtls_poly1305_init(mbedtls_poly1305_context *ctx)
 {
-    POLY1305_VALIDATE( ctx != NULL );
-
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_poly1305_context));
 }
 
-void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx )
+void mbedtls_poly1305_free(mbedtls_poly1305_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_poly1305_context));
 }
 
-int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx,
-                             const unsigned char key[32] )
+int mbedtls_poly1305_starts(mbedtls_poly1305_context *ctx,
+                            const unsigned char key[32])
 {
-    POLY1305_VALIDATE_RET( ctx != NULL );
-    POLY1305_VALIDATE_RET( key != NULL );
-
     /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */
-    ctx->r[0] = MBEDTLS_GET_UINT32_LE( key, 0 )  & 0x0FFFFFFFU;
-    ctx->r[1] = MBEDTLS_GET_UINT32_LE( key, 4 )  & 0x0FFFFFFCU;
-    ctx->r[2] = MBEDTLS_GET_UINT32_LE( key, 8 )  & 0x0FFFFFFCU;
-    ctx->r[3] = MBEDTLS_GET_UINT32_LE( key, 12 ) & 0x0FFFFFFCU;
+    ctx->r[0] = MBEDTLS_GET_UINT32_LE(key, 0)  & 0x0FFFFFFFU;
+    ctx->r[1] = MBEDTLS_GET_UINT32_LE(key, 4)  & 0x0FFFFFFCU;
+    ctx->r[2] = MBEDTLS_GET_UINT32_LE(key, 8)  & 0x0FFFFFFCU;
+    ctx->r[3] = MBEDTLS_GET_UINT32_LE(key, 12) & 0x0FFFFFFCU;
 
-    ctx->s[0] = MBEDTLS_GET_UINT32_LE( key, 16 );
-    ctx->s[1] = MBEDTLS_GET_UINT32_LE( key, 20 );
-    ctx->s[2] = MBEDTLS_GET_UINT32_LE( key, 24 );
-    ctx->s[3] = MBEDTLS_GET_UINT32_LE( key, 28 );
+    ctx->s[0] = MBEDTLS_GET_UINT32_LE(key, 16);
+    ctx->s[1] = MBEDTLS_GET_UINT32_LE(key, 20);
+    ctx->s[2] = MBEDTLS_GET_UINT32_LE(key, 24);
+    ctx->s[3] = MBEDTLS_GET_UINT32_LE(key, 28);
 
     /* Initial accumulator state */
     ctx->acc[0] = 0U;
@@ -296,129 +273,116 @@
     ctx->acc[4] = 0U;
 
     /* Queue initially empty */
-    mbedtls_platform_zeroize( ctx->queue, sizeof( ctx->queue ) );
+    mbedtls_platform_zeroize(ctx->queue, sizeof(ctx->queue));
     ctx->queue_len = 0U;
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx,
-                             const unsigned char *input,
-                             size_t ilen )
+int mbedtls_poly1305_update(mbedtls_poly1305_context *ctx,
+                            const unsigned char *input,
+                            size_t ilen)
 {
     size_t offset    = 0U;
     size_t remaining = ilen;
     size_t queue_free_len;
     size_t nblocks;
-    POLY1305_VALIDATE_RET( ctx != NULL );
-    POLY1305_VALIDATE_RET( ilen == 0 || input != NULL );
 
-    if( ( remaining > 0U ) && ( ctx->queue_len > 0U ) )
-    {
-        queue_free_len = ( POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len );
+    if ((remaining > 0U) && (ctx->queue_len > 0U)) {
+        queue_free_len = (POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len);
 
-        if( ilen < queue_free_len )
-        {
+        if (ilen < queue_free_len) {
             /* Not enough data to complete the block.
              * Store this data with the other leftovers.
              */
-            memcpy( &ctx->queue[ctx->queue_len],
-                    input,
-                    ilen );
+            memcpy(&ctx->queue[ctx->queue_len],
+                   input,
+                   ilen);
 
             ctx->queue_len += ilen;
 
             remaining = 0U;
-        }
-        else
-        {
+        } else {
             /* Enough data to produce a complete block */
-            memcpy( &ctx->queue[ctx->queue_len],
-                    input,
-                    queue_free_len );
+            memcpy(&ctx->queue[ctx->queue_len],
+                   input,
+                   queue_free_len);
 
             ctx->queue_len = 0U;
 
-            poly1305_process( ctx, 1U, ctx->queue, 1U ); /* add padding bit */
+            poly1305_process(ctx, 1U, ctx->queue, 1U);   /* add padding bit */
 
             offset    += queue_free_len;
             remaining -= queue_free_len;
         }
     }
 
-    if( remaining >= POLY1305_BLOCK_SIZE_BYTES )
-    {
+    if (remaining >= POLY1305_BLOCK_SIZE_BYTES) {
         nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES;
 
-        poly1305_process( ctx, nblocks, &input[offset], 1U );
+        poly1305_process(ctx, nblocks, &input[offset], 1U);
 
         offset += nblocks * POLY1305_BLOCK_SIZE_BYTES;
         remaining %= POLY1305_BLOCK_SIZE_BYTES;
     }
 
-    if( remaining > 0U )
-    {
+    if (remaining > 0U) {
         /* Store partial block */
         ctx->queue_len = remaining;
-        memcpy( ctx->queue, &input[offset], remaining );
+        memcpy(ctx->queue, &input[offset], remaining);
     }
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx,
-                             unsigned char mac[16] )
+int mbedtls_poly1305_finish(mbedtls_poly1305_context *ctx,
+                            unsigned char mac[16])
 {
-    POLY1305_VALIDATE_RET( ctx != NULL );
-    POLY1305_VALIDATE_RET( mac != NULL );
-
     /* Process any leftover data */
-    if( ctx->queue_len > 0U )
-    {
+    if (ctx->queue_len > 0U) {
         /* Add padding bit */
         ctx->queue[ctx->queue_len] = 1U;
         ctx->queue_len++;
 
         /* Pad with zeroes */
-        memset( &ctx->queue[ctx->queue_len],
-                0,
-                POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len );
+        memset(&ctx->queue[ctx->queue_len],
+               0,
+               POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len);
 
-        poly1305_process( ctx, 1U,          /* Process 1 block */
-                          ctx->queue, 0U ); /* Already padded above */
+        poly1305_process(ctx, 1U,           /* Process 1 block */
+                         ctx->queue, 0U);   /* Already padded above */
     }
 
-    poly1305_compute_mac( ctx, mac );
+    poly1305_compute_mac(ctx, mac);
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_poly1305_mac( const unsigned char key[32],
-                          const unsigned char *input,
-                          size_t ilen,
-                          unsigned char mac[16] )
+int mbedtls_poly1305_mac(const unsigned char key[32],
+                         const unsigned char *input,
+                         size_t ilen,
+                         unsigned char mac[16])
 {
     mbedtls_poly1305_context ctx;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    POLY1305_VALIDATE_RET( key != NULL );
-    POLY1305_VALIDATE_RET( mac != NULL );
-    POLY1305_VALIDATE_RET( ilen == 0 || input != NULL );
 
-    mbedtls_poly1305_init( &ctx );
+    mbedtls_poly1305_init(&ctx);
 
-    ret = mbedtls_poly1305_starts( &ctx, key );
-    if( ret != 0 )
+    ret = mbedtls_poly1305_starts(&ctx, key);
+    if (ret != 0) {
         goto cleanup;
+    }
 
-    ret = mbedtls_poly1305_update( &ctx, input, ilen );
-    if( ret != 0 )
+    ret = mbedtls_poly1305_update(&ctx, input, ilen);
+    if (ret != 0) {
         goto cleanup;
+    }
 
-    ret = mbedtls_poly1305_finish( &ctx, mac );
+    ret = mbedtls_poly1305_finish(&ctx, mac);
 
 cleanup:
-    mbedtls_poly1305_free( &ctx );
-    return( ret );
+    mbedtls_poly1305_free(&ctx);
+    return ret;
 }
 
 #endif /* MBEDTLS_POLY1305_ALT */
@@ -491,46 +455,48 @@
 /* Make sure no other definition is already present. */
 #undef ASSERT
 
-#define ASSERT( cond, args )            \
+#define ASSERT(cond, args)            \
     do                                  \
     {                                   \
-        if( ! ( cond ) )                \
+        if (!(cond))                \
         {                               \
-            if( verbose != 0 )          \
-                mbedtls_printf args;    \
+            if (verbose != 0)          \
+            mbedtls_printf args;    \
                                         \
-            return( -1 );               \
+            return -1;               \
         }                               \
     }                                   \
-    while( 0 )
+    while (0)
 
-int mbedtls_poly1305_self_test( int verbose )
+int mbedtls_poly1305_self_test(int verbose)
 {
     unsigned char mac[16];
     unsigned i;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    for( i = 0U; i < 2U; i++ )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "  Poly1305 test %u ", i );
+    for (i = 0U; i < 2U; i++) {
+        if (verbose != 0) {
+            mbedtls_printf("  Poly1305 test %u ", i);
+        }
 
-        ret = mbedtls_poly1305_mac( test_keys[i],
-                                    test_data[i],
-                                    test_data_len[i],
-                                    mac );
-        ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
+        ret = mbedtls_poly1305_mac(test_keys[i],
+                                   test_data[i],
+                                   test_data_len[i],
+                                   mac);
+        ASSERT(0 == ret, ("error code: %i\n", ret));
 
-        ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), ( "failed (mac)\n" ) );
+        ASSERT(0 == memcmp(mac, test_mac[i], 16U), ("failed (mac)\n"));
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
-    return( 0 );
+    return 0;
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/lib/libmbedtls/mbedtls/library/ripemd160.c b/lib/libmbedtls/mbedtls/library/ripemd160.c
index aed7322..ba97c1f 100644
--- a/lib/libmbedtls/mbedtls/library/ripemd160.c
+++ b/lib/libmbedtls/mbedtls/library/ripemd160.c
@@ -33,32 +33,26 @@
 
 #include <string.h>
 
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
 
 #if !defined(MBEDTLS_RIPEMD160_ALT)
 
-void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx )
+void mbedtls_ripemd160_init(mbedtls_ripemd160_context *ctx)
 {
-    memset( ctx, 0, sizeof( mbedtls_ripemd160_context ) );
+    memset(ctx, 0, sizeof(mbedtls_ripemd160_context));
 }
 
-void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx )
+void mbedtls_ripemd160_free(mbedtls_ripemd160_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ripemd160_context ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ripemd160_context));
 }
 
-void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst,
-                        const mbedtls_ripemd160_context *src )
+void mbedtls_ripemd160_clone(mbedtls_ripemd160_context *dst,
+                             const mbedtls_ripemd160_context *src)
 {
     *dst = *src;
 }
@@ -66,7 +60,7 @@
 /*
  * RIPEMD-160 context setup
  */
-int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx )
+int mbedtls_ripemd160_starts(mbedtls_ripemd160_context *ctx)
 {
     ctx->total[0] = 0;
     ctx->total[1] = 0;
@@ -77,44 +71,36 @@
     ctx->state[3] = 0x10325476;
     ctx->state[4] = 0xC3D2E1F0;
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx )
-{
-    mbedtls_ripemd160_starts_ret( ctx );
-}
-#endif
-
 #if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT)
 /*
  * Process one block
  */
-int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx,
-                                        const unsigned char data[64] )
+int mbedtls_internal_ripemd160_process(mbedtls_ripemd160_context *ctx,
+                                       const unsigned char data[64])
 {
-    struct
-    {
+    struct {
         uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16];
     } local;
 
-    local.X[ 0] = MBEDTLS_GET_UINT32_LE( data,  0 );
-    local.X[ 1] = MBEDTLS_GET_UINT32_LE( data,  4 );
-    local.X[ 2] = MBEDTLS_GET_UINT32_LE( data,  8 );
-    local.X[ 3] = MBEDTLS_GET_UINT32_LE( data, 12 );
-    local.X[ 4] = MBEDTLS_GET_UINT32_LE( data, 16 );
-    local.X[ 5] = MBEDTLS_GET_UINT32_LE( data, 20 );
-    local.X[ 6] = MBEDTLS_GET_UINT32_LE( data, 24 );
-    local.X[ 7] = MBEDTLS_GET_UINT32_LE( data, 28 );
-    local.X[ 8] = MBEDTLS_GET_UINT32_LE( data, 32 );
-    local.X[ 9] = MBEDTLS_GET_UINT32_LE( data, 36 );
-    local.X[10] = MBEDTLS_GET_UINT32_LE( data, 40 );
-    local.X[11] = MBEDTLS_GET_UINT32_LE( data, 44 );
-    local.X[12] = MBEDTLS_GET_UINT32_LE( data, 48 );
-    local.X[13] = MBEDTLS_GET_UINT32_LE( data, 52 );
-    local.X[14] = MBEDTLS_GET_UINT32_LE( data, 56 );
-    local.X[15] = MBEDTLS_GET_UINT32_LE( data, 60 );
+    local.X[0] = MBEDTLS_GET_UINT32_LE(data,  0);
+    local.X[1] = MBEDTLS_GET_UINT32_LE(data,  4);
+    local.X[2] = MBEDTLS_GET_UINT32_LE(data,  8);
+    local.X[3] = MBEDTLS_GET_UINT32_LE(data, 12);
+    local.X[4] = MBEDTLS_GET_UINT32_LE(data, 16);
+    local.X[5] = MBEDTLS_GET_UINT32_LE(data, 20);
+    local.X[6] = MBEDTLS_GET_UINT32_LE(data, 24);
+    local.X[7] = MBEDTLS_GET_UINT32_LE(data, 28);
+    local.X[8] = MBEDTLS_GET_UINT32_LE(data, 32);
+    local.X[9] = MBEDTLS_GET_UINT32_LE(data, 36);
+    local.X[10] = MBEDTLS_GET_UINT32_LE(data, 40);
+    local.X[11] = MBEDTLS_GET_UINT32_LE(data, 44);
+    local.X[12] = MBEDTLS_GET_UINT32_LE(data, 48);
+    local.X[13] = MBEDTLS_GET_UINT32_LE(data, 52);
+    local.X[14] = MBEDTLS_GET_UINT32_LE(data, 56);
+    local.X[15] = MBEDTLS_GET_UINT32_LE(data, 60);
 
     local.A = local.Ap = ctx->state[0];
     local.B = local.Bp = ctx->state[1];
@@ -122,50 +108,50 @@
     local.D = local.Dp = ctx->state[3];
     local.E = local.Ep = ctx->state[4];
 
-#define F1( x, y, z )   ( (x) ^ (y) ^ (z) )
-#define F2( x, y, z )   ( ( (x) & (y) ) | ( ~(x) & (z) ) )
-#define F3( x, y, z )   ( ( (x) | ~(y) ) ^ (z) )
-#define F4( x, y, z )   ( ( (x) & (z) ) | ( (y) & ~(z) ) )
-#define F5( x, y, z )   ( (x) ^ ( (y) | ~(z) ) )
+#define F1(x, y, z)   ((x) ^ (y) ^ (z))
+#define F2(x, y, z)   (((x) & (y)) | (~(x) & (z)))
+#define F3(x, y, z)   (((x) | ~(y)) ^ (z))
+#define F4(x, y, z)   (((x) & (z)) | ((y) & ~(z)))
+#define F5(x, y, z)   ((x) ^ ((y) | ~(z)))
 
-#define S( x, n ) ( ( (x) << (n) ) | ( (x) >> (32 - (n)) ) )
+#define S(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
 
-#define P( a, b, c, d, e, r, s, f, k )                      \
+#define P(a, b, c, d, e, r, s, f, k)                      \
     do                                                      \
     {                                                       \
-        (a) += f( (b), (c), (d) ) + local.X[r] + (k);       \
-        (a) = S( (a), (s) ) + (e);                          \
-        (c) = S( (c), 10 );                                 \
-    } while( 0 )
+        (a) += f((b), (c), (d)) + local.X[r] + (k);       \
+        (a) = S((a), (s)) + (e);                          \
+        (c) = S((c), 10);                                 \
+    } while (0)
 
-#define P2( a, b, c, d, e, r, s, rp, sp )                               \
+#define P2(a, b, c, d, e, r, s, rp, sp)                               \
     do                                                                  \
     {                                                                   \
-        P( (a), (b), (c), (d), (e), (r), (s), F, K );                   \
-        P( a ## p, b ## p, c ## p, d ## p, e ## p,                      \
-           (rp), (sp), Fp, Kp );                                        \
-    } while( 0 )
+        P((a), (b), (c), (d), (e), (r), (s), F, K);                   \
+        P(a ## p, b ## p, c ## p, d ## p, e ## p,                      \
+          (rp), (sp), Fp, Kp);                                        \
+    } while (0)
 
 #define F   F1
 #define K   0x00000000
 #define Fp  F5
 #define Kp  0x50A28BE6
-    P2( local.A, local.B, local.C, local.D, local.E,  0, 11,  5,  8 );
-    P2( local.E, local.A, local.B, local.C, local.D,  1, 14, 14,  9 );
-    P2( local.D, local.E, local.A, local.B, local.C,  2, 15,  7,  9 );
-    P2( local.C, local.D, local.E, local.A, local.B,  3, 12,  0, 11 );
-    P2( local.B, local.C, local.D, local.E, local.A,  4,  5,  9, 13 );
-    P2( local.A, local.B, local.C, local.D, local.E,  5,  8,  2, 15 );
-    P2( local.E, local.A, local.B, local.C, local.D,  6,  7, 11, 15 );
-    P2( local.D, local.E, local.A, local.B, local.C,  7,  9,  4,  5 );
-    P2( local.C, local.D, local.E, local.A, local.B,  8, 11, 13,  7 );
-    P2( local.B, local.C, local.D, local.E, local.A,  9, 13,  6,  7 );
-    P2( local.A, local.B, local.C, local.D, local.E, 10, 14, 15,  8 );
-    P2( local.E, local.A, local.B, local.C, local.D, 11, 15,  8, 11 );
-    P2( local.D, local.E, local.A, local.B, local.C, 12,  6,  1, 14 );
-    P2( local.C, local.D, local.E, local.A, local.B, 13,  7, 10, 14 );
-    P2( local.B, local.C, local.D, local.E, local.A, 14,  9,  3, 12 );
-    P2( local.A, local.B, local.C, local.D, local.E, 15,  8, 12,  6 );
+    P2(local.A, local.B, local.C, local.D, local.E,  0, 11,  5,  8);
+    P2(local.E, local.A, local.B, local.C, local.D,  1, 14, 14,  9);
+    P2(local.D, local.E, local.A, local.B, local.C,  2, 15,  7,  9);
+    P2(local.C, local.D, local.E, local.A, local.B,  3, 12,  0, 11);
+    P2(local.B, local.C, local.D, local.E, local.A,  4,  5,  9, 13);
+    P2(local.A, local.B, local.C, local.D, local.E,  5,  8,  2, 15);
+    P2(local.E, local.A, local.B, local.C, local.D,  6,  7, 11, 15);
+    P2(local.D, local.E, local.A, local.B, local.C,  7,  9,  4,  5);
+    P2(local.C, local.D, local.E, local.A, local.B,  8, 11, 13,  7);
+    P2(local.B, local.C, local.D, local.E, local.A,  9, 13,  6,  7);
+    P2(local.A, local.B, local.C, local.D, local.E, 10, 14, 15,  8);
+    P2(local.E, local.A, local.B, local.C, local.D, 11, 15,  8, 11);
+    P2(local.D, local.E, local.A, local.B, local.C, 12,  6,  1, 14);
+    P2(local.C, local.D, local.E, local.A, local.B, 13,  7, 10, 14);
+    P2(local.B, local.C, local.D, local.E, local.A, 14,  9,  3, 12);
+    P2(local.A, local.B, local.C, local.D, local.E, 15,  8, 12,  6);
 #undef F
 #undef K
 #undef Fp
@@ -175,22 +161,22 @@
 #define K   0x5A827999
 #define Fp  F4
 #define Kp  0x5C4DD124
-    P2( local.E, local.A, local.B, local.C, local.D,  7,  7,  6,  9 );
-    P2( local.D, local.E, local.A, local.B, local.C,  4,  6, 11, 13 );
-    P2( local.C, local.D, local.E, local.A, local.B, 13,  8,  3, 15 );
-    P2( local.B, local.C, local.D, local.E, local.A,  1, 13,  7,  7 );
-    P2( local.A, local.B, local.C, local.D, local.E, 10, 11,  0, 12 );
-    P2( local.E, local.A, local.B, local.C, local.D,  6,  9, 13,  8 );
-    P2( local.D, local.E, local.A, local.B, local.C, 15,  7,  5,  9 );
-    P2( local.C, local.D, local.E, local.A, local.B,  3, 15, 10, 11 );
-    P2( local.B, local.C, local.D, local.E, local.A, 12,  7, 14,  7 );
-    P2( local.A, local.B, local.C, local.D, local.E,  0, 12, 15,  7 );
-    P2( local.E, local.A, local.B, local.C, local.D,  9, 15,  8, 12 );
-    P2( local.D, local.E, local.A, local.B, local.C,  5,  9, 12,  7 );
-    P2( local.C, local.D, local.E, local.A, local.B,  2, 11,  4,  6 );
-    P2( local.B, local.C, local.D, local.E, local.A, 14,  7,  9, 15 );
-    P2( local.A, local.B, local.C, local.D, local.E, 11, 13,  1, 13 );
-    P2( local.E, local.A, local.B, local.C, local.D,  8, 12,  2, 11 );
+    P2(local.E, local.A, local.B, local.C, local.D,  7,  7,  6,  9);
+    P2(local.D, local.E, local.A, local.B, local.C,  4,  6, 11, 13);
+    P2(local.C, local.D, local.E, local.A, local.B, 13,  8,  3, 15);
+    P2(local.B, local.C, local.D, local.E, local.A,  1, 13,  7,  7);
+    P2(local.A, local.B, local.C, local.D, local.E, 10, 11,  0, 12);
+    P2(local.E, local.A, local.B, local.C, local.D,  6,  9, 13,  8);
+    P2(local.D, local.E, local.A, local.B, local.C, 15,  7,  5,  9);
+    P2(local.C, local.D, local.E, local.A, local.B,  3, 15, 10, 11);
+    P2(local.B, local.C, local.D, local.E, local.A, 12,  7, 14,  7);
+    P2(local.A, local.B, local.C, local.D, local.E,  0, 12, 15,  7);
+    P2(local.E, local.A, local.B, local.C, local.D,  9, 15,  8, 12);
+    P2(local.D, local.E, local.A, local.B, local.C,  5,  9, 12,  7);
+    P2(local.C, local.D, local.E, local.A, local.B,  2, 11,  4,  6);
+    P2(local.B, local.C, local.D, local.E, local.A, 14,  7,  9, 15);
+    P2(local.A, local.B, local.C, local.D, local.E, 11, 13,  1, 13);
+    P2(local.E, local.A, local.B, local.C, local.D,  8, 12,  2, 11);
 #undef F
 #undef K
 #undef Fp
@@ -200,22 +186,22 @@
 #define K   0x6ED9EBA1
 #define Fp  F3
 #define Kp  0x6D703EF3
-    P2( local.D, local.E, local.A, local.B, local.C,  3, 11, 15,  9 );
-    P2( local.C, local.D, local.E, local.A, local.B, 10, 13,  5,  7 );
-    P2( local.B, local.C, local.D, local.E, local.A, 14,  6,  1, 15 );
-    P2( local.A, local.B, local.C, local.D, local.E,  4,  7,  3, 11 );
-    P2( local.E, local.A, local.B, local.C, local.D,  9, 14,  7,  8 );
-    P2( local.D, local.E, local.A, local.B, local.C, 15,  9, 14,  6 );
-    P2( local.C, local.D, local.E, local.A, local.B,  8, 13,  6,  6 );
-    P2( local.B, local.C, local.D, local.E, local.A,  1, 15,  9, 14 );
-    P2( local.A, local.B, local.C, local.D, local.E,  2, 14, 11, 12 );
-    P2( local.E, local.A, local.B, local.C, local.D,  7,  8,  8, 13 );
-    P2( local.D, local.E, local.A, local.B, local.C,  0, 13, 12,  5 );
-    P2( local.C, local.D, local.E, local.A, local.B,  6,  6,  2, 14 );
-    P2( local.B, local.C, local.D, local.E, local.A, 13,  5, 10, 13 );
-    P2( local.A, local.B, local.C, local.D, local.E, 11, 12,  0, 13 );
-    P2( local.E, local.A, local.B, local.C, local.D,  5,  7,  4,  7 );
-    P2( local.D, local.E, local.A, local.B, local.C, 12,  5, 13,  5 );
+    P2(local.D, local.E, local.A, local.B, local.C,  3, 11, 15,  9);
+    P2(local.C, local.D, local.E, local.A, local.B, 10, 13,  5,  7);
+    P2(local.B, local.C, local.D, local.E, local.A, 14,  6,  1, 15);
+    P2(local.A, local.B, local.C, local.D, local.E,  4,  7,  3, 11);
+    P2(local.E, local.A, local.B, local.C, local.D,  9, 14,  7,  8);
+    P2(local.D, local.E, local.A, local.B, local.C, 15,  9, 14,  6);
+    P2(local.C, local.D, local.E, local.A, local.B,  8, 13,  6,  6);
+    P2(local.B, local.C, local.D, local.E, local.A,  1, 15,  9, 14);
+    P2(local.A, local.B, local.C, local.D, local.E,  2, 14, 11, 12);
+    P2(local.E, local.A, local.B, local.C, local.D,  7,  8,  8, 13);
+    P2(local.D, local.E, local.A, local.B, local.C,  0, 13, 12,  5);
+    P2(local.C, local.D, local.E, local.A, local.B,  6,  6,  2, 14);
+    P2(local.B, local.C, local.D, local.E, local.A, 13,  5, 10, 13);
+    P2(local.A, local.B, local.C, local.D, local.E, 11, 12,  0, 13);
+    P2(local.E, local.A, local.B, local.C, local.D,  5,  7,  4,  7);
+    P2(local.D, local.E, local.A, local.B, local.C, 12,  5, 13,  5);
 #undef F
 #undef K
 #undef Fp
@@ -225,22 +211,22 @@
 #define K   0x8F1BBCDC
 #define Fp  F2
 #define Kp  0x7A6D76E9
-    P2( local.C, local.D, local.E, local.A, local.B,  1, 11,  8, 15 );
-    P2( local.B, local.C, local.D, local.E, local.A,  9, 12,  6,  5 );
-    P2( local.A, local.B, local.C, local.D, local.E, 11, 14,  4,  8 );
-    P2( local.E, local.A, local.B, local.C, local.D, 10, 15,  1, 11 );
-    P2( local.D, local.E, local.A, local.B, local.C,  0, 14,  3, 14 );
-    P2( local.C, local.D, local.E, local.A, local.B,  8, 15, 11, 14 );
-    P2( local.B, local.C, local.D, local.E, local.A, 12,  9, 15,  6 );
-    P2( local.A, local.B, local.C, local.D, local.E,  4,  8,  0, 14 );
-    P2( local.E, local.A, local.B, local.C, local.D, 13,  9,  5,  6 );
-    P2( local.D, local.E, local.A, local.B, local.C,  3, 14, 12,  9 );
-    P2( local.C, local.D, local.E, local.A, local.B,  7,  5,  2, 12 );
-    P2( local.B, local.C, local.D, local.E, local.A, 15,  6, 13,  9 );
-    P2( local.A, local.B, local.C, local.D, local.E, 14,  8,  9, 12 );
-    P2( local.E, local.A, local.B, local.C, local.D,  5,  6,  7,  5 );
-    P2( local.D, local.E, local.A, local.B, local.C,  6,  5, 10, 15 );
-    P2( local.C, local.D, local.E, local.A, local.B,  2, 12, 14,  8 );
+    P2(local.C, local.D, local.E, local.A, local.B,  1, 11,  8, 15);
+    P2(local.B, local.C, local.D, local.E, local.A,  9, 12,  6,  5);
+    P2(local.A, local.B, local.C, local.D, local.E, 11, 14,  4,  8);
+    P2(local.E, local.A, local.B, local.C, local.D, 10, 15,  1, 11);
+    P2(local.D, local.E, local.A, local.B, local.C,  0, 14,  3, 14);
+    P2(local.C, local.D, local.E, local.A, local.B,  8, 15, 11, 14);
+    P2(local.B, local.C, local.D, local.E, local.A, 12,  9, 15,  6);
+    P2(local.A, local.B, local.C, local.D, local.E,  4,  8,  0, 14);
+    P2(local.E, local.A, local.B, local.C, local.D, 13,  9,  5,  6);
+    P2(local.D, local.E, local.A, local.B, local.C,  3, 14, 12,  9);
+    P2(local.C, local.D, local.E, local.A, local.B,  7,  5,  2, 12);
+    P2(local.B, local.C, local.D, local.E, local.A, 15,  6, 13,  9);
+    P2(local.A, local.B, local.C, local.D, local.E, 14,  8,  9, 12);
+    P2(local.E, local.A, local.B, local.C, local.D,  5,  6,  7,  5);
+    P2(local.D, local.E, local.A, local.B, local.C,  6,  5, 10, 15);
+    P2(local.C, local.D, local.E, local.A, local.B,  2, 12, 14,  8);
 #undef F
 #undef K
 #undef Fp
@@ -250,22 +236,22 @@
 #define K   0xA953FD4E
 #define Fp  F1
 #define Kp  0x00000000
-    P2( local.B, local.C, local.D, local.E, local.A,  4,  9, 12,  8 );
-    P2( local.A, local.B, local.C, local.D, local.E,  0, 15, 15,  5 );
-    P2( local.E, local.A, local.B, local.C, local.D,  5,  5, 10, 12 );
-    P2( local.D, local.E, local.A, local.B, local.C,  9, 11,  4,  9 );
-    P2( local.C, local.D, local.E, local.A, local.B,  7,  6,  1, 12 );
-    P2( local.B, local.C, local.D, local.E, local.A, 12,  8,  5,  5 );
-    P2( local.A, local.B, local.C, local.D, local.E,  2, 13,  8, 14 );
-    P2( local.E, local.A, local.B, local.C, local.D, 10, 12,  7,  6 );
-    P2( local.D, local.E, local.A, local.B, local.C, 14,  5,  6,  8 );
-    P2( local.C, local.D, local.E, local.A, local.B,  1, 12,  2, 13 );
-    P2( local.B, local.C, local.D, local.E, local.A,  3, 13, 13,  6 );
-    P2( local.A, local.B, local.C, local.D, local.E,  8, 14, 14,  5 );
-    P2( local.E, local.A, local.B, local.C, local.D, 11, 11,  0, 15 );
-    P2( local.D, local.E, local.A, local.B, local.C,  6,  8,  3, 13 );
-    P2( local.C, local.D, local.E, local.A, local.B, 15,  5,  9, 11 );
-    P2( local.B, local.C, local.D, local.E, local.A, 13,  6, 11, 11 );
+    P2(local.B, local.C, local.D, local.E, local.A,  4,  9, 12,  8);
+    P2(local.A, local.B, local.C, local.D, local.E,  0, 15, 15,  5);
+    P2(local.E, local.A, local.B, local.C, local.D,  5,  5, 10, 12);
+    P2(local.D, local.E, local.A, local.B, local.C,  9, 11,  4,  9);
+    P2(local.C, local.D, local.E, local.A, local.B,  7,  6,  1, 12);
+    P2(local.B, local.C, local.D, local.E, local.A, 12,  8,  5,  5);
+    P2(local.A, local.B, local.C, local.D, local.E,  2, 13,  8, 14);
+    P2(local.E, local.A, local.B, local.C, local.D, 10, 12,  7,  6);
+    P2(local.D, local.E, local.A, local.B, local.C, 14,  5,  6,  8);
+    P2(local.C, local.D, local.E, local.A, local.B,  1, 12,  2, 13);
+    P2(local.B, local.C, local.D, local.E, local.A,  3, 13, 13,  6);
+    P2(local.A, local.B, local.C, local.D, local.E,  8, 14, 14,  5);
+    P2(local.E, local.A, local.B, local.C, local.D, 11, 11,  0, 15);
+    P2(local.D, local.E, local.A, local.B, local.C,  6,  8,  3, 13);
+    P2(local.C, local.D, local.E, local.A, local.B, 15,  5,  9, 11);
+    P2(local.B, local.C, local.D, local.E, local.A, 13,  6, 11, 11);
 #undef F
 #undef K
 #undef Fp
@@ -279,33 +265,27 @@
     ctx->state[0] = local.C;
 
     /* Zeroise variables to clear sensitive data from memory. */
-    mbedtls_platform_zeroize( &local, sizeof( local ) );
+    mbedtls_platform_zeroize(&local, sizeof(local));
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx,
-                                const unsigned char data[64] )
-{
-    mbedtls_internal_ripemd160_process( ctx, data );
-}
-#endif
 #endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */
 
 /*
  * RIPEMD-160 process buffer
  */
-int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx,
-                                  const unsigned char *input,
-                                  size_t ilen )
+int mbedtls_ripemd160_update(mbedtls_ripemd160_context *ctx,
+                             const unsigned char *input,
+                             size_t ilen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t fill;
     uint32_t left;
 
-    if( ilen == 0 )
-        return( 0 );
+    if (ilen == 0) {
+        return 0;
+    }
 
     left = ctx->total[0] & 0x3F;
     fill = 64 - left;
@@ -313,50 +293,41 @@
     ctx->total[0] += (uint32_t) ilen;
     ctx->total[0] &= 0xFFFFFFFF;
 
-    if( ctx->total[0] < (uint32_t) ilen )
+    if (ctx->total[0] < (uint32_t) ilen) {
         ctx->total[1]++;
+    }
 
-    if( left && ilen >= fill )
-    {
-        memcpy( (void *) (ctx->buffer + left), input, fill );
+    if (left && ilen >= fill) {
+        memcpy((void *) (ctx->buffer + left), input, fill);
 
-        if( ( ret = mbedtls_internal_ripemd160_process( ctx, ctx->buffer ) ) != 0 )
-            return( ret );
+        if ((ret = mbedtls_internal_ripemd160_process(ctx, ctx->buffer)) != 0) {
+            return ret;
+        }
 
         input += fill;
         ilen  -= fill;
         left = 0;
     }
 
-    while( ilen >= 64 )
-    {
-        if( ( ret = mbedtls_internal_ripemd160_process( ctx, input ) ) != 0 )
-            return( ret );
+    while (ilen >= 64) {
+        if ((ret = mbedtls_internal_ripemd160_process(ctx, input)) != 0) {
+            return ret;
+        }
 
         input += 64;
         ilen  -= 64;
     }
 
-    if( ilen > 0 )
-    {
-        memcpy( (void *) (ctx->buffer + left), input, ilen );
+    if (ilen > 0) {
+        memcpy((void *) (ctx->buffer + left), input, ilen);
     }
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx,
-                               const unsigned char *input,
-                               size_t ilen )
-{
-    mbedtls_ripemd160_update_ret( ctx, input, ilen );
-}
-#endif
-
 static const unsigned char ripemd160_padding[64] =
 {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
@@ -365,87 +336,75 @@
 /*
  * RIPEMD-160 final digest
  */
-int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx,
-                                  unsigned char output[20] )
+int mbedtls_ripemd160_finish(mbedtls_ripemd160_context *ctx,
+                             unsigned char output[20])
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     uint32_t last, padn;
     uint32_t high, low;
     unsigned char msglen[8];
 
-    high = ( ctx->total[0] >> 29 )
-         | ( ctx->total[1] <<  3 );
-    low  = ( ctx->total[0] <<  3 );
+    high = (ctx->total[0] >> 29)
+           | (ctx->total[1] <<  3);
+    low  = (ctx->total[0] <<  3);
 
-    MBEDTLS_PUT_UINT32_LE( low,  msglen, 0 );
-    MBEDTLS_PUT_UINT32_LE( high, msglen, 4 );
+    MBEDTLS_PUT_UINT32_LE(low,  msglen, 0);
+    MBEDTLS_PUT_UINT32_LE(high, msglen, 4);
 
     last = ctx->total[0] & 0x3F;
-    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+    padn = (last < 56) ? (56 - last) : (120 - last);
 
-    ret = mbedtls_ripemd160_update_ret( ctx, ripemd160_padding, padn );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_ripemd160_update(ctx, ripemd160_padding, padn);
+    if (ret != 0) {
+        return ret;
+    }
 
-    ret = mbedtls_ripemd160_update_ret( ctx, msglen, 8 );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_ripemd160_update(ctx, msglen, 8);
+    if (ret != 0) {
+        return ret;
+    }
 
-    MBEDTLS_PUT_UINT32_LE( ctx->state[0], output,  0 );
-    MBEDTLS_PUT_UINT32_LE( ctx->state[1], output,  4 );
-    MBEDTLS_PUT_UINT32_LE( ctx->state[2], output,  8 );
-    MBEDTLS_PUT_UINT32_LE( ctx->state[3], output, 12 );
-    MBEDTLS_PUT_UINT32_LE( ctx->state[4], output, 16 );
+    MBEDTLS_PUT_UINT32_LE(ctx->state[0], output,  0);
+    MBEDTLS_PUT_UINT32_LE(ctx->state[1], output,  4);
+    MBEDTLS_PUT_UINT32_LE(ctx->state[2], output,  8);
+    MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12);
+    MBEDTLS_PUT_UINT32_LE(ctx->state[4], output, 16);
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx,
-                               unsigned char output[20] )
-{
-    mbedtls_ripemd160_finish_ret( ctx, output );
-}
-#endif
-
 #endif /* ! MBEDTLS_RIPEMD160_ALT */
 
 /*
  * output = RIPEMD-160( input buffer )
  */
-int mbedtls_ripemd160_ret( const unsigned char *input,
-                           size_t ilen,
-                           unsigned char output[20] )
+int mbedtls_ripemd160(const unsigned char *input,
+                      size_t ilen,
+                      unsigned char output[20])
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ripemd160_context ctx;
 
-    mbedtls_ripemd160_init( &ctx );
+    mbedtls_ripemd160_init(&ctx);
 
-    if( ( ret = mbedtls_ripemd160_starts_ret( &ctx ) ) != 0 )
+    if ((ret = mbedtls_ripemd160_starts(&ctx)) != 0) {
         goto exit;
+    }
 
-    if( ( ret = mbedtls_ripemd160_update_ret( &ctx, input, ilen ) ) != 0 )
+    if ((ret = mbedtls_ripemd160_update(&ctx, input, ilen)) != 0) {
         goto exit;
+    }
 
-    if( ( ret = mbedtls_ripemd160_finish_ret( &ctx, output ) ) != 0 )
+    if ((ret = mbedtls_ripemd160_finish(&ctx, output)) != 0) {
         goto exit;
+    }
 
 exit:
-    mbedtls_ripemd160_free( &ctx );
+    mbedtls_ripemd160_free(&ctx);
 
-    return( ret );
+    return ret;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_ripemd160( const unsigned char *input,
-                        size_t ilen,
-                        unsigned char output[20] )
-{
-    mbedtls_ripemd160_ret( input, ilen, output );
-}
-#endif
-
 #if defined(MBEDTLS_SELF_TEST)
 /*
  * Test vectors from the RIPEMD-160 paper and
@@ -492,43 +451,46 @@
 /*
  * Checkup routine
  */
-int mbedtls_ripemd160_self_test( int verbose )
+int mbedtls_ripemd160_self_test(int verbose)
 {
     int i, ret = 0;
     unsigned char output[20];
 
-    memset( output, 0, sizeof output );
+    memset(output, 0, sizeof(output));
 
-    for( i = 0; i < TESTS; i++ )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "  RIPEMD-160 test #%d: ", i + 1 );
+    for (i = 0; i < TESTS; i++) {
+        if (verbose != 0) {
+            mbedtls_printf("  RIPEMD-160 test #%d: ", i + 1);
+        }
 
-        ret = mbedtls_ripemd160_ret( ripemd160_test_str[i],
-                                     ripemd160_test_strlen[i], output );
-        if( ret != 0 )
+        ret = mbedtls_ripemd160(ripemd160_test_str[i],
+                                ripemd160_test_strlen[i], output);
+        if (ret != 0) {
             goto fail;
+        }
 
-        if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 )
-        {
+        if (memcmp(output, ripemd160_test_md[i], 20) != 0) {
             ret = 1;
             goto fail;
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
-    return( 0 );
+    return 0;
 
 fail:
-    if( verbose != 0 )
-        mbedtls_printf( "failed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("failed\n");
+    }
 
-    return( ret );
+    return ret;
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/lib/libmbedtls/mbedtls/library/rsa.c b/lib/libmbedtls/mbedtls/library/rsa.c
index 61d7f8e..40dbcab 100644
--- a/lib/libmbedtls/mbedtls/library/rsa.c
+++ b/lib/libmbedtls/mbedtls/library/rsa.c
@@ -40,99 +40,97 @@
 #if defined(MBEDTLS_RSA_C)
 
 #include "mbedtls/rsa.h"
-#include "mbedtls/rsa_internal.h"
+#include "rsa_alt_helpers.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 #include "constant_time_internal.h"
 #include "mbedtls/constant_time.h"
+#include "hash_info.h"
 
 #include <string.h>
 
-#if defined(MBEDTLS_PKCS1_V21)
-#include "mbedtls/md.h"
-#endif
-
 #if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) && !defined(__NetBSD__)
 #include <stdlib.h>
 #endif
 
-#if defined(MBEDTLS_PLATFORM_C)
+/* We use MD first if it's available (for compatibility reasons)
+ * and "fall back" to PSA otherwise (which needs psa_crypto_init()). */
+#if defined(MBEDTLS_PKCS1_V21)
+#if !defined(MBEDTLS_MD_C)
+#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_md_errors,              \
+                                                           psa_generic_status_to_mbedtls)
+#endif /* !MBEDTLS_MD_C */
+#endif /* MBEDTLS_PKCS1_V21 */
+
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#define mbedtls_calloc calloc
-#define mbedtls_free   free
-#endif
 
 #include <fault_mitigation.h>
 
 #if !defined(MBEDTLS_RSA_ALT)
 
-/* Parameter validation macros */
-#define RSA_VALIDATE_RET( cond )                                       \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_RSA_BAD_INPUT_DATA )
-#define RSA_VALIDATE( cond )                                           \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
-
-int mbedtls_rsa_import( mbedtls_rsa_context *ctx,
-                        const mbedtls_mpi *N,
-                        const mbedtls_mpi *P, const mbedtls_mpi *Q,
-                        const mbedtls_mpi *D, const mbedtls_mpi *E )
+int mbedtls_rsa_import(mbedtls_rsa_context *ctx,
+                       const mbedtls_mpi *N,
+                       const mbedtls_mpi *P, const mbedtls_mpi *Q,
+                       const mbedtls_mpi *D, const mbedtls_mpi *E)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    RSA_VALIDATE_RET( ctx != NULL );
 
-    if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) ||
-        ( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) ||
-        ( Q != NULL && ( ret = mbedtls_mpi_copy( &ctx->Q, Q ) ) != 0 ) ||
-        ( D != NULL && ( ret = mbedtls_mpi_copy( &ctx->D, D ) ) != 0 ) ||
-        ( E != NULL && ( ret = mbedtls_mpi_copy( &ctx->E, E ) ) != 0 ) )
-    {
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) );
+    if ((N != NULL && (ret = mbedtls_mpi_copy(&ctx->N, N)) != 0) ||
+        (P != NULL && (ret = mbedtls_mpi_copy(&ctx->P, P)) != 0) ||
+        (Q != NULL && (ret = mbedtls_mpi_copy(&ctx->Q, Q)) != 0) ||
+        (D != NULL && (ret = mbedtls_mpi_copy(&ctx->D, D)) != 0) ||
+        (E != NULL && (ret = mbedtls_mpi_copy(&ctx->E, E)) != 0)) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);
     }
 
-    if( N != NULL )
-        ctx->len = mbedtls_mpi_size( &ctx->N );
+    if (N != NULL) {
+        ctx->len = mbedtls_mpi_size(&ctx->N);
+    }
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx,
-                            unsigned char const *N, size_t N_len,
-                            unsigned char const *P, size_t P_len,
-                            unsigned char const *Q, size_t Q_len,
-                            unsigned char const *D, size_t D_len,
-                            unsigned char const *E, size_t E_len )
+int mbedtls_rsa_import_raw(mbedtls_rsa_context *ctx,
+                           unsigned char const *N, size_t N_len,
+                           unsigned char const *P, size_t P_len,
+                           unsigned char const *Q, size_t Q_len,
+                           unsigned char const *D, size_t D_len,
+                           unsigned char const *E, size_t E_len)
 {
     int ret = 0;
-    RSA_VALIDATE_RET( ctx != NULL );
 
-    if( N != NULL )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->N, N, N_len ) );
-        ctx->len = mbedtls_mpi_size( &ctx->N );
+    if (N != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->N, N, N_len));
+        ctx->len = mbedtls_mpi_size(&ctx->N);
     }
 
-    if( P != NULL )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->P, P, P_len ) );
+    if (P != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->P, P, P_len));
+    }
 
-    if( Q != NULL )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->Q, Q, Q_len ) );
+    if (Q != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->Q, Q, Q_len));
+    }
 
-    if( D != NULL )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->D, D, D_len ) );
+    if (D != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->D, D, D_len));
+    }
 
-    if( E != NULL )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->E, E, E_len ) );
+    if (E != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->E, E, E_len));
+    }
 
 cleanup:
 
-    if( ret != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) );
+    if (ret != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -140,8 +138,8 @@
  * that the RSA primitives will be able to execute without error.
  * It does *not* make guarantees for consistency of the parameters.
  */
-static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv,
-                              int blinding_needed )
+static int rsa_check_context(mbedtls_rsa_context const *ctx, int is_priv,
+                             int blinding_needed)
 {
 #if !defined(MBEDTLS_RSA_NO_CRT)
     /* blinding_needed is only used for NO_CRT to decide whether
@@ -149,10 +147,9 @@
     ((void) blinding_needed);
 #endif
 
-    if( ctx->len != mbedtls_mpi_size( &ctx->N ) ||
-        ctx->len > MBEDTLS_MPI_MAX_SIZE )
-    {
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (ctx->len != mbedtls_mpi_size(&ctx->N) ||
+        ctx->len > MBEDTLS_MPI_MAX_SIZE) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
 
     /*
@@ -161,23 +158,21 @@
 
     /* Modular exponentiation wrt. N is always used for
      * RSA public key operations. */
-    if( mbedtls_mpi_cmp_int( &ctx->N, 0 ) <= 0 ||
-        mbedtls_mpi_get_bit( &ctx->N, 0 ) == 0  )
-    {
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (mbedtls_mpi_cmp_int(&ctx->N, 0) <= 0 ||
+        mbedtls_mpi_get_bit(&ctx->N, 0) == 0) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
 
 #if !defined(MBEDTLS_RSA_NO_CRT)
     /* Modular exponentiation for P and Q is only
      * used for private key operations and if CRT
      * is used. */
-    if( is_priv &&
-        ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 ||
-          mbedtls_mpi_get_bit( &ctx->P, 0 ) == 0 ||
-          mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ||
-          mbedtls_mpi_get_bit( &ctx->Q, 0 ) == 0  ) )
-    {
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (is_priv &&
+        (mbedtls_mpi_cmp_int(&ctx->P, 0) <= 0 ||
+         mbedtls_mpi_get_bit(&ctx->P, 0) == 0 ||
+         mbedtls_mpi_cmp_int(&ctx->Q, 0) <= 0 ||
+         mbedtls_mpi_get_bit(&ctx->Q, 0) == 0)) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
 #endif /* !MBEDTLS_RSA_NO_CRT */
 
@@ -186,20 +181,21 @@
      */
 
     /* Always need E for public key operations */
-    if( mbedtls_mpi_cmp_int( &ctx->E, 0 ) <= 0 )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (mbedtls_mpi_cmp_int(&ctx->E, 0) <= 0) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
 #if defined(MBEDTLS_RSA_NO_CRT)
     /* For private key operations, use D or DP & DQ
      * as (unblinded) exponents. */
-    if( is_priv && mbedtls_mpi_cmp_int( &ctx->D, 0 ) <= 0 )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (is_priv && mbedtls_mpi_cmp_int(&ctx->D, 0) <= 0) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 #else
-    if( is_priv &&
-        ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) <= 0 ||
-          mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) <= 0  ) )
-    {
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (is_priv &&
+        (mbedtls_mpi_cmp_int(&ctx->DP, 0) <= 0 ||
+         mbedtls_mpi_cmp_int(&ctx->DQ, 0) <= 0)) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
 #endif /* MBEDTLS_RSA_NO_CRT */
 
@@ -207,28 +203,26 @@
      * so check that P, Q >= 1 if that hasn't yet been
      * done as part of 1. */
 #if defined(MBEDTLS_RSA_NO_CRT)
-    if( is_priv && blinding_needed &&
-        ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 ||
-          mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ) )
-    {
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (is_priv && blinding_needed &&
+        (mbedtls_mpi_cmp_int(&ctx->P, 0) <= 0 ||
+         mbedtls_mpi_cmp_int(&ctx->Q, 0) <= 0)) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
 #endif
 
     /* It wouldn't lead to an error if it wasn't satisfied,
      * but check for QP >= 1 nonetheless. */
 #if !defined(MBEDTLS_RSA_NO_CRT)
-    if( is_priv &&
-        mbedtls_mpi_cmp_int( &ctx->QP, 0 ) <= 0 )
-    {
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (is_priv &&
+        mbedtls_mpi_cmp_int(&ctx->QP, 0) <= 0) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
 #endif
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
+int mbedtls_rsa_complete(mbedtls_rsa_context *ctx)
 {
     int ret = 0;
     int have_N, have_P, have_Q, have_D, have_E;
@@ -237,18 +231,16 @@
 #endif
     int n_missing, pq_missing, d_missing, is_pub, is_priv;
 
-    RSA_VALIDATE_RET( ctx != NULL );
-
-    have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 );
-    have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 );
-    have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 );
-    have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 );
-    have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 );
+    have_N = (mbedtls_mpi_cmp_int(&ctx->N, 0) != 0);
+    have_P = (mbedtls_mpi_cmp_int(&ctx->P, 0) != 0);
+    have_Q = (mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0);
+    have_D = (mbedtls_mpi_cmp_int(&ctx->D, 0) != 0);
+    have_E = (mbedtls_mpi_cmp_int(&ctx->E, 0) != 0);
 
 #if !defined(MBEDTLS_RSA_NO_CRT)
-    have_DP = ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) != 0 );
-    have_DQ = ( mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) != 0 );
-    have_QP = ( mbedtls_mpi_cmp_int( &ctx->QP, 0 ) != 0 );
+    have_DP = (mbedtls_mpi_cmp_int(&ctx->DP, 0) != 0);
+    have_DQ = (mbedtls_mpi_cmp_int(&ctx->DQ, 0) != 0);
+    have_QP = (mbedtls_mpi_cmp_int(&ctx->QP, 0) != 0);
 #endif
 
     /*
@@ -269,44 +261,40 @@
     /* These three alternatives are mutually exclusive */
     is_priv = n_missing || pq_missing || d_missing;
 
-    if( !is_priv && !is_pub )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (!is_priv && !is_pub) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
     /*
      * Step 1: Deduce N if P, Q are provided.
      */
 
-    if( !have_N && have_P && have_Q )
-    {
-        if( ( ret = mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P,
-                                         &ctx->Q ) ) != 0 )
-        {
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) );
+    if (!have_N && have_P && have_Q) {
+        if ((ret = mbedtls_mpi_mul_mpi(&ctx->N, &ctx->P,
+                                       &ctx->Q)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);
         }
 
-        ctx->len = mbedtls_mpi_size( &ctx->N );
+        ctx->len = mbedtls_mpi_size(&ctx->N);
     }
 
     /*
      * Step 2: Deduce and verify all remaining core parameters.
      */
 
-    if( pq_missing )
-    {
-        ret = mbedtls_rsa_deduce_primes( &ctx->N, &ctx->E, &ctx->D,
-                                         &ctx->P, &ctx->Q );
-        if( ret != 0 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) );
+    if (pq_missing) {
+        ret = mbedtls_rsa_deduce_primes(&ctx->N, &ctx->E, &ctx->D,
+                                        &ctx->P, &ctx->Q);
+        if (ret != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);
+        }
 
-    }
-    else if( d_missing )
-    {
-        if( ( ret = mbedtls_rsa_deduce_private_exponent( &ctx->P,
-                                                         &ctx->Q,
-                                                         &ctx->E,
-                                                         &ctx->D ) ) != 0 )
-        {
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) );
+    } else if (d_missing) {
+        if ((ret = mbedtls_rsa_deduce_private_exponent(&ctx->P,
+                                                       &ctx->Q,
+                                                       &ctx->E,
+                                                       &ctx->D)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);
         }
     }
 
@@ -316,12 +304,12 @@
      */
 
 #if !defined(MBEDTLS_RSA_NO_CRT)
-    if( is_priv && ! ( have_DP && have_DQ && have_QP ) )
-    {
-        ret = mbedtls_rsa_deduce_crt( &ctx->P,  &ctx->Q,  &ctx->D,
-                                      &ctx->DP, &ctx->DQ, &ctx->QP );
-        if( ret != 0 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) );
+    if (is_priv && !(have_DP && have_DQ && have_QP)) {
+        ret = mbedtls_rsa_deduce_crt(&ctx->P,  &ctx->Q,  &ctx->D,
+                                     &ctx->DP, &ctx->DQ, &ctx->QP);
+        if (ret != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);
+        }
     }
 #endif /* MBEDTLS_RSA_NO_CRT */
 
@@ -329,94 +317,96 @@
      * Step 3: Basic sanity checks
      */
 
-    return( rsa_check_context( ctx, is_priv, 1 ) );
+    return rsa_check_context(ctx, is_priv, 1);
 }
 
-int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx,
-                            unsigned char *N, size_t N_len,
-                            unsigned char *P, size_t P_len,
-                            unsigned char *Q, size_t Q_len,
-                            unsigned char *D, size_t D_len,
-                            unsigned char *E, size_t E_len )
+int mbedtls_rsa_export_raw(const mbedtls_rsa_context *ctx,
+                           unsigned char *N, size_t N_len,
+                           unsigned char *P, size_t P_len,
+                           unsigned char *Q, size_t Q_len,
+                           unsigned char *D, size_t D_len,
+                           unsigned char *E, size_t E_len)
 {
     int ret = 0;
     int is_priv;
-    RSA_VALIDATE_RET( ctx != NULL );
 
     /* Check if key is private or public */
     is_priv =
-        mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
-        mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
-        mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
-        mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 &&
-        mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0;
+        mbedtls_mpi_cmp_int(&ctx->N, 0) != 0 &&
+        mbedtls_mpi_cmp_int(&ctx->P, 0) != 0 &&
+        mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0 &&
+        mbedtls_mpi_cmp_int(&ctx->D, 0) != 0 &&
+        mbedtls_mpi_cmp_int(&ctx->E, 0) != 0;
 
-    if( !is_priv )
-    {
+    if (!is_priv) {
         /* If we're trying to export private parameters for a public key,
          * something must be wrong. */
-        if( P != NULL || Q != NULL || D != NULL )
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+        if (P != NULL || Q != NULL || D != NULL) {
+            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+        }
 
     }
 
-    if( N != NULL )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->N, N, N_len ) );
+    if (N != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->N, N, N_len));
+    }
 
-    if( P != NULL )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->P, P, P_len ) );
+    if (P != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->P, P, P_len));
+    }
 
-    if( Q != NULL )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->Q, Q, Q_len ) );
+    if (Q != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->Q, Q, Q_len));
+    }
 
-    if( D != NULL )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->D, D, D_len ) );
+    if (D != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->D, D, D_len));
+    }
 
-    if( E != NULL )
-        MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->E, E, E_len ) );
+    if (E != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->E, E, E_len));
+    }
 
 cleanup:
 
-    return( ret );
+    return ret;
 }
 
-int mbedtls_rsa_export( const mbedtls_rsa_context *ctx,
-                        mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q,
-                        mbedtls_mpi *D, mbedtls_mpi *E )
+int mbedtls_rsa_export(const mbedtls_rsa_context *ctx,
+                       mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q,
+                       mbedtls_mpi *D, mbedtls_mpi *E)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     int is_priv;
-    RSA_VALIDATE_RET( ctx != NULL );
 
     /* Check if key is private or public */
     is_priv =
-        mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
-        mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
-        mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
-        mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 &&
-        mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0;
+        mbedtls_mpi_cmp_int(&ctx->N, 0) != 0 &&
+        mbedtls_mpi_cmp_int(&ctx->P, 0) != 0 &&
+        mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0 &&
+        mbedtls_mpi_cmp_int(&ctx->D, 0) != 0 &&
+        mbedtls_mpi_cmp_int(&ctx->E, 0) != 0;
 
-    if( !is_priv )
-    {
+    if (!is_priv) {
         /* If we're trying to export private parameters for a public key,
          * something must be wrong. */
-        if( P != NULL || Q != NULL || D != NULL )
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+        if (P != NULL || Q != NULL || D != NULL) {
+            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+        }
 
     }
 
     /* Export all requested core parameters. */
 
-    if( ( N != NULL && ( ret = mbedtls_mpi_copy( N, &ctx->N ) ) != 0 ) ||
-        ( P != NULL && ( ret = mbedtls_mpi_copy( P, &ctx->P ) ) != 0 ) ||
-        ( Q != NULL && ( ret = mbedtls_mpi_copy( Q, &ctx->Q ) ) != 0 ) ||
-        ( D != NULL && ( ret = mbedtls_mpi_copy( D, &ctx->D ) ) != 0 ) ||
-        ( E != NULL && ( ret = mbedtls_mpi_copy( E, &ctx->E ) ) != 0 ) )
-    {
-        return( ret );
+    if ((N != NULL && (ret = mbedtls_mpi_copy(N, &ctx->N)) != 0) ||
+        (P != NULL && (ret = mbedtls_mpi_copy(P, &ctx->P)) != 0) ||
+        (Q != NULL && (ret = mbedtls_mpi_copy(Q, &ctx->Q)) != 0) ||
+        (D != NULL && (ret = mbedtls_mpi_copy(D, &ctx->D)) != 0) ||
+        (E != NULL && (ret = mbedtls_mpi_copy(E, &ctx->E)) != 0)) {
+        return ret;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -425,87 +415,117 @@
  * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt
  * can be used in this case.
  */
-int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx,
-                            mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP )
+int mbedtls_rsa_export_crt(const mbedtls_rsa_context *ctx,
+                           mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     int is_priv;
-    RSA_VALIDATE_RET( ctx != NULL );
 
     /* Check if key is private or public */
     is_priv =
-        mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
-        mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
-        mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
-        mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 &&
-        mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0;
+        mbedtls_mpi_cmp_int(&ctx->N, 0) != 0 &&
+        mbedtls_mpi_cmp_int(&ctx->P, 0) != 0 &&
+        mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0 &&
+        mbedtls_mpi_cmp_int(&ctx->D, 0) != 0 &&
+        mbedtls_mpi_cmp_int(&ctx->E, 0) != 0;
 
-    if( !is_priv )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (!is_priv) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
 #if !defined(MBEDTLS_RSA_NO_CRT)
     /* Export all requested blinding parameters. */
-    if( ( DP != NULL && ( ret = mbedtls_mpi_copy( DP, &ctx->DP ) ) != 0 ) ||
-        ( DQ != NULL && ( ret = mbedtls_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) ||
-        ( QP != NULL && ( ret = mbedtls_mpi_copy( QP, &ctx->QP ) ) != 0 ) )
-    {
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) );
+    if ((DP != NULL && (ret = mbedtls_mpi_copy(DP, &ctx->DP)) != 0) ||
+        (DQ != NULL && (ret = mbedtls_mpi_copy(DQ, &ctx->DQ)) != 0) ||
+        (QP != NULL && (ret = mbedtls_mpi_copy(QP, &ctx->QP)) != 0)) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);
     }
 #else
-    if( ( ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
-                                        DP, DQ, QP ) ) != 0 )
-    {
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) );
+    if ((ret = mbedtls_rsa_deduce_crt(&ctx->P, &ctx->Q, &ctx->D,
+                                      DP, DQ, QP)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret);
     }
 #endif
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Initialize an RSA context
  */
-void mbedtls_rsa_init( mbedtls_rsa_context *ctx,
-               int padding,
-               int hash_id )
+void mbedtls_rsa_init(mbedtls_rsa_context *ctx)
 {
-    RSA_VALIDATE( ctx != NULL );
-    RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 ||
-                  padding == MBEDTLS_RSA_PKCS_V21 );
+    memset(ctx, 0, sizeof(mbedtls_rsa_context));
 
-    memset( ctx, 0, sizeof( mbedtls_rsa_context ) );
-
-    mbedtls_rsa_set_padding( ctx, padding, hash_id );
+    ctx->padding = MBEDTLS_RSA_PKCS_V15;
+    ctx->hash_id = MBEDTLS_MD_NONE;
 
 #if defined(MBEDTLS_THREADING_C)
     /* Set ctx->ver to nonzero to indicate that the mutex has been
      * initialized and will need to be freed. */
     ctx->ver = 1;
-    mbedtls_mutex_init( &ctx->mutex );
+    mbedtls_mutex_init(&ctx->mutex);
 #endif
 }
 
 /*
  * Set padding for an existing RSA context
  */
-void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding,
-                              int hash_id )
+int mbedtls_rsa_set_padding(mbedtls_rsa_context *ctx, int padding,
+                            mbedtls_md_type_t hash_id)
 {
-    RSA_VALIDATE( ctx != NULL );
-    RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 ||
-                  padding == MBEDTLS_RSA_PKCS_V21 );
+    switch (padding) {
+#if defined(MBEDTLS_PKCS1_V15)
+        case MBEDTLS_RSA_PKCS_V15:
+            break;
+#endif
+
+#if defined(MBEDTLS_PKCS1_V21)
+        case MBEDTLS_RSA_PKCS_V21:
+            break;
+#endif
+        default:
+            return MBEDTLS_ERR_RSA_INVALID_PADDING;
+    }
+
+#if defined(MBEDTLS_PKCS1_V21)
+    if ((padding == MBEDTLS_RSA_PKCS_V21) &&
+        (hash_id != MBEDTLS_MD_NONE)) {
+        /* Just make sure this hash is supported in this build. */
+        if (mbedtls_hash_info_psa_from_md(hash_id) == PSA_ALG_NONE) {
+            return MBEDTLS_ERR_RSA_INVALID_PADDING;
+        }
+    }
+#endif /* MBEDTLS_PKCS1_V21 */
 
     ctx->padding = padding;
     ctx->hash_id = hash_id;
+
+    return 0;
+}
+
+/*
+ * Get padding mode of initialized RSA context
+ */
+int mbedtls_rsa_get_padding_mode(const mbedtls_rsa_context *ctx)
+{
+    return ctx->padding;
+}
+
+/*
+ * Get hash identifier of mbedtls_md_type_t type
+ */
+int mbedtls_rsa_get_md_alg(const mbedtls_rsa_context *ctx)
+{
+    return ctx->hash_id;
 }
 
 /*
  * Get length in bytes of RSA modulus
  */
-
-size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx )
+size_t mbedtls_rsa_get_len(const mbedtls_rsa_context *ctx)
 {
-    return( ctx->len );
+    return ctx->len;
 }
 
 
@@ -517,31 +537,29 @@
  * This generation method follows the RSA key pair generation procedure of
  * FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072.
  */
-int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
-                 int (*f_rng)(void *, unsigned char *, size_t),
-                 void *p_rng,
-                 unsigned int nbits, int exponent )
+int mbedtls_rsa_gen_key(mbedtls_rsa_context *ctx,
+                        int (*f_rng)(void *, unsigned char *, size_t),
+                        void *p_rng,
+                        unsigned int nbits, int exponent)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_mpi H, G, L;
     int prime_quality = 0;
-    RSA_VALIDATE_RET( ctx != NULL );
-    RSA_VALIDATE_RET( f_rng != NULL );
 
     /*
      * If the modulus is 1024 bit long or shorter, then the security strength of
      * the RSA algorithm is less than or equal to 80 bits and therefore an error
      * rate of 2^-80 is sufficient.
      */
-    if( nbits > 1024 )
+    if (nbits > 1024) {
         prime_quality = MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR;
+    }
 
-    mbedtls_mpi_init( &H );
-    mbedtls_mpi_init( &G );
-    mbedtls_mpi_init( &L );
+    mbedtls_mpi_init(&H);
+    mbedtls_mpi_init(&G);
+    mbedtls_mpi_init(&L);
 
-    if( nbits < 128 || exponent < 3 || nbits % 2 != 0 )
-    {
+    if (nbits < 128 || exponent < 3 || nbits % 2 != 0) {
         ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
         goto cleanup;
     }
@@ -552,54 +570,56 @@
      * 2.  GCD( E, (P-1)*(Q-1) ) == 1
      * 3.  E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 )
      */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->E, exponent));
 
-    do
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1,
-                                                prime_quality, f_rng, p_rng ) );
+    do {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_gen_prime(&ctx->P, nbits >> 1,
+                                              prime_quality, f_rng, p_rng));
 
-        MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1,
-                                                prime_quality, f_rng, p_rng ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_gen_prime(&ctx->Q, nbits >> 1,
+                                              prime_quality, f_rng, p_rng));
 
         /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) );
-        if( mbedtls_mpi_bitlen( &H ) <= ( ( nbits >= 200 ) ? ( ( nbits >> 1 ) - 99 ) : 0 ) )
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&H, &ctx->P, &ctx->Q));
+        if (mbedtls_mpi_bitlen(&H) <= ((nbits >= 200) ? ((nbits >> 1) - 99) : 0)) {
             continue;
+        }
 
         /* not required by any standards, but some users rely on the fact that P > Q */
-        if( H.s < 0 )
-            mbedtls_mpi_swap( &ctx->P, &ctx->Q );
+        if (H.s < 0) {
+            mbedtls_mpi_swap(&ctx->P, &ctx->Q);
+        }
 
         /* Temporarily replace P,Q by P-1, Q-1 */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&ctx->P, &ctx->P, 1));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&ctx->Q, &ctx->Q, 1));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&H, &ctx->P, &ctx->Q));
 
         /* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H  ) );
-        if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
+        MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, &ctx->E, &H));
+        if (mbedtls_mpi_cmp_int(&G, 1) != 0) {
             continue;
+        }
 
         /* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->P, &ctx->Q ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L, NULL, &H, &G ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &L ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, &ctx->P, &ctx->Q));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&L, NULL, &H, &G));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&ctx->D, &ctx->E, &L));
 
-        if( mbedtls_mpi_bitlen( &ctx->D ) <= ( ( nbits + 1 ) / 2 ) ) // (FIPS 186-4 §B.3.1 criterion 3(a))
+        if (mbedtls_mpi_bitlen(&ctx->D) <= ((nbits + 1) / 2)) {      // (FIPS 186-4 §B.3.1 criterion 3(a))
             continue;
+        }
 
         break;
-    }
-    while( 1 );
+    } while (1);
 
     /* Restore P,Q */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P,  &ctx->P, 1 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q,  &ctx->Q, 1 ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&ctx->P,  &ctx->P, 1));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&ctx->Q,  &ctx->Q, 1));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->N, &ctx->P, &ctx->Q));
 
-    ctx->len = mbedtls_mpi_size( &ctx->N );
+    ctx->len = mbedtls_mpi_size(&ctx->N);
 
 #if !defined(MBEDTLS_RSA_NO_CRT)
     /*
@@ -607,29 +627,29 @@
      * DQ = D mod (Q - 1)
      * QP = Q^-1 mod P
      */
-    MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
-                                             &ctx->DP, &ctx->DQ, &ctx->QP ) );
+    MBEDTLS_MPI_CHK(mbedtls_rsa_deduce_crt(&ctx->P, &ctx->Q, &ctx->D,
+                                           &ctx->DP, &ctx->DQ, &ctx->QP));
 #endif /* MBEDTLS_RSA_NO_CRT */
 
     /* Double-check */
-    MBEDTLS_MPI_CHK( mbedtls_rsa_check_privkey( ctx ) );
+    MBEDTLS_MPI_CHK(mbedtls_rsa_check_privkey(ctx));
 
 cleanup:
 
-    mbedtls_mpi_free( &H );
-    mbedtls_mpi_free( &G );
-    mbedtls_mpi_free( &L );
+    mbedtls_mpi_free(&H);
+    mbedtls_mpi_free(&G);
+    mbedtls_mpi_free(&L);
 
-    if( ret != 0 )
-    {
-        mbedtls_rsa_free( ctx );
+    if (ret != 0) {
+        mbedtls_rsa_free(ctx);
 
-        if( ( -ret & ~0x7f ) == 0 )
-            ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_KEY_GEN_FAILED, ret );
-        return( ret );
+        if ((-ret & ~0x7f) == 0) {
+            ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_KEY_GEN_FAILED, ret);
+        }
+        return ret;
     }
 
-    return( 0 );
+    return 0;
 }
 
 #endif /* MBEDTLS_GENPRIME */
@@ -637,130 +657,117 @@
 /*
  * Check a public RSA key
  */
-int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx )
+int mbedtls_rsa_check_pubkey(const mbedtls_rsa_context *ctx)
 {
-    RSA_VALIDATE_RET( ctx != NULL );
-
-    if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 )
-        return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
-
-    if( mbedtls_mpi_bitlen( &ctx->N ) < 128 )
-    {
-        return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
+    if (rsa_check_context(ctx, 0 /* public */, 0 /* no blinding */) != 0) {
+        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     }
 
-    if( mbedtls_mpi_get_bit( &ctx->E, 0 ) == 0 ||
-        mbedtls_mpi_bitlen( &ctx->E )     < 2  ||
-        mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 )
-    {
-        return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
+    if (mbedtls_mpi_bitlen(&ctx->N) < 128) {
+        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     }
 
-    return( 0 );
+    if (mbedtls_mpi_get_bit(&ctx->E, 0) == 0 ||
+        mbedtls_mpi_bitlen(&ctx->E)     < 2  ||
+        mbedtls_mpi_cmp_mpi(&ctx->E, &ctx->N) >= 0) {
+        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
+    }
+
+    return 0;
 }
 
 /*
  * Check for the consistency of all fields in an RSA private key context
  */
-int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx )
+int mbedtls_rsa_check_privkey(const mbedtls_rsa_context *ctx)
 {
-    RSA_VALIDATE_RET( ctx != NULL );
-
-    if( mbedtls_rsa_check_pubkey( ctx ) != 0 ||
-        rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 )
-    {
-        return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
+    if (mbedtls_rsa_check_pubkey(ctx) != 0 ||
+        rsa_check_context(ctx, 1 /* private */, 1 /* blinding */) != 0) {
+        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     }
 
-    if( mbedtls_rsa_validate_params( &ctx->N, &ctx->P, &ctx->Q,
-                                     &ctx->D, &ctx->E, NULL, NULL ) != 0 )
-    {
-        return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
+    if (mbedtls_rsa_validate_params(&ctx->N, &ctx->P, &ctx->Q,
+                                    &ctx->D, &ctx->E, NULL, NULL) != 0) {
+        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     }
 
 #if !defined(MBEDTLS_RSA_NO_CRT)
-    else if( mbedtls_rsa_validate_crt( &ctx->P, &ctx->Q, &ctx->D,
-                                       &ctx->DP, &ctx->DQ, &ctx->QP ) != 0 )
-    {
-        return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
+    else if (mbedtls_rsa_validate_crt(&ctx->P, &ctx->Q, &ctx->D,
+                                      &ctx->DP, &ctx->DQ, &ctx->QP) != 0) {
+        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     }
 #endif
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Check if contexts holding a public and private key match
  */
-int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub,
-                                const mbedtls_rsa_context *prv )
+int mbedtls_rsa_check_pub_priv(const mbedtls_rsa_context *pub,
+                               const mbedtls_rsa_context *prv)
 {
-    RSA_VALIDATE_RET( pub != NULL );
-    RSA_VALIDATE_RET( prv != NULL );
-
-    if( mbedtls_rsa_check_pubkey( pub )  != 0 ||
-        mbedtls_rsa_check_privkey( prv ) != 0 )
-    {
-        return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
+    if (mbedtls_rsa_check_pubkey(pub)  != 0 ||
+        mbedtls_rsa_check_privkey(prv) != 0) {
+        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     }
 
-    if( mbedtls_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 ||
-        mbedtls_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 )
-    {
-        return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
+    if (mbedtls_mpi_cmp_mpi(&pub->N, &prv->N) != 0 ||
+        mbedtls_mpi_cmp_mpi(&pub->E, &prv->E) != 0) {
+        return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Do an RSA public key operation
  */
-int mbedtls_rsa_public( mbedtls_rsa_context *ctx,
-                const unsigned char *input,
-                unsigned char *output )
+int mbedtls_rsa_public(mbedtls_rsa_context *ctx,
+                       const unsigned char *input,
+                       unsigned char *output)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t olen;
     mbedtls_mpi T;
-    RSA_VALIDATE_RET( ctx != NULL );
-    RSA_VALIDATE_RET( input != NULL );
-    RSA_VALIDATE_RET( output != NULL );
 
-    if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (rsa_check_context(ctx, 0 /* public */, 0 /* no blinding */)) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
-    mbedtls_mpi_init( &T );
+    mbedtls_mpi_init(&T);
 
 #if defined(MBEDTLS_THREADING_C)
-    if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
+        return ret;
+    }
 #endif
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&T, input, ctx->len));
 
-    if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
-    {
+    if (mbedtls_mpi_cmp_mpi(&T, &ctx->N) >= 0) {
         ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
         goto cleanup;
     }
 
     olen = ctx->len;
-    MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, &ctx->E, &ctx->N, &ctx->RN));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&T, output, olen));
 
 cleanup:
 #if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
-        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
+        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
+    }
 #endif
 
-    mbedtls_mpi_free( &T );
+    mbedtls_mpi_free(&T);
 
-    if( ret != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_PUBLIC_FAILED, ret ) );
+    if (ret != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_PUBLIC_FAILED, ret);
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -769,63 +776,62 @@
  *  DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
  *  Berlin Heidelberg, 1996. p. 104-113.
  */
-static int rsa_prepare_blinding( mbedtls_rsa_context *ctx,
-                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+static int rsa_prepare_blinding(mbedtls_rsa_context *ctx,
+                                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
     int ret, count = 0;
     mbedtls_mpi R;
 
-    mbedtls_mpi_init( &R );
+    mbedtls_mpi_init(&R);
 
-    if( ctx->Vf.p != NULL )
-    {
+    if (ctx->Vf.p != NULL) {
         /* We already have blinding values, just update them by squaring */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &ctx->Vi));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->N));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &ctx->Vf));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->N));
 
         goto cleanup;
     }
 
     /* Unblinding value: Vf = random number, invertible mod N */
     do {
-        if( count++ > 10 )
-        {
+        if (count++ > 10) {
             ret = MBEDTLS_ERR_RSA_RNG_FAILED;
             goto cleanup;
         }
 
-        MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx->Vf, ctx->len - 1, f_rng, p_rng));
 
         /* Compute Vf^-1 as R * (R Vf)^-1 to avoid leaks from inv_mod. */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, ctx->len - 1, f_rng, p_rng ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vf, &R ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) );
+        MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, ctx->len - 1, f_rng, p_rng));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vf, &R));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->N));
 
         /* At this point, Vi is invertible mod N if and only if both Vf and R
          * are invertible mod N. If one of them isn't, we don't need to know
          * which one, we just loop and choose new values for both of them.
          * (Each iteration succeeds with overwhelming probability.) */
-        ret = mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vi, &ctx->N );
-        if( ret != 0 && ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
+        ret = mbedtls_mpi_inv_mod(&ctx->Vi, &ctx->Vi, &ctx->N);
+        if (ret != 0 && ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
             goto cleanup;
+        }
 
-    } while( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
+    } while (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE);
 
     /* Finish the computation of Vf^-1 = R * (R Vf)^-1 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &R ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &R));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->N));
 
     /* Blinding value: Vi = Vf^(-e) mod N
      * (Vi already contains Vf^-1 at this point) */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN));
 
 
 cleanup:
-    mbedtls_mpi_free( &R );
+    mbedtls_mpi_free(&R);
 
-    return( ret );
+    return ret;
 }
 
 /*
@@ -852,11 +858,11 @@
 /*
  * Do an RSA private key operation
  */
-int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
-                 int (*f_rng)(void *, unsigned char *, size_t),
-                 void *p_rng,
-                 const unsigned char *input,
-                 unsigned char *output )
+int mbedtls_rsa_private(mbedtls_rsa_context *ctx,
+                        int (*f_rng)(void *, unsigned char *, size_t),
+                        void *p_rng,
+                        const unsigned char *input,
+                        unsigned char *output)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t olen;
@@ -893,110 +899,103 @@
      * checked result; should be the same in the end. */
     mbedtls_mpi I, C;
 
-    RSA_VALIDATE_RET( ctx != NULL );
-    RSA_VALIDATE_RET( input  != NULL );
-    RSA_VALIDATE_RET( output != NULL );
+    if (f_rng == NULL) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
-    if( rsa_check_context( ctx, 1             /* private key checks */,
-                                f_rng != NULL /* blinding y/n       */ ) != 0 )
-    {
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (rsa_check_context(ctx, 1 /* private key checks */,
+                          1 /* blinding on        */) != 0) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
 
 #if defined(MBEDTLS_THREADING_C)
-    if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
+        return ret;
+    }
 #endif
 
     /* MPI Initialization */
-    mbedtls_mpi_init( &T );
+    mbedtls_mpi_init(&T);
 
-    mbedtls_mpi_init( &P1 );
-    mbedtls_mpi_init( &Q1 );
-    mbedtls_mpi_init( &R );
+    mbedtls_mpi_init(&P1);
+    mbedtls_mpi_init(&Q1);
+    mbedtls_mpi_init(&R);
 
-    if( f_rng != NULL )
-    {
 #if defined(MBEDTLS_RSA_NO_CRT)
-        mbedtls_mpi_init( &D_blind );
+    mbedtls_mpi_init(&D_blind);
 #else
-        mbedtls_mpi_init( &DP_blind );
-        mbedtls_mpi_init( &DQ_blind );
+    mbedtls_mpi_init(&DP_blind);
+    mbedtls_mpi_init(&DQ_blind);
 #endif
-    }
 
 #if !defined(MBEDTLS_RSA_NO_CRT)
-    mbedtls_mpi_init( &TP ); mbedtls_mpi_init( &TQ );
+    mbedtls_mpi_init(&TP); mbedtls_mpi_init(&TQ);
 #endif
 
-    mbedtls_mpi_init( &I );
-    mbedtls_mpi_init( &C );
+    mbedtls_mpi_init(&I);
+    mbedtls_mpi_init(&C);
 
     /* End of MPI initialization */
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) );
-    if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
-    {
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&T, input, ctx->len));
+    if (mbedtls_mpi_cmp_mpi(&T, &ctx->N) >= 0) {
         ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
         goto cleanup;
     }
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &I, &T ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&I, &T));
 
-    if( f_rng != NULL )
-    {
-        /*
-         * Blinding
-         * T = T * Vi mod N
-         */
-        MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) );
+    /*
+     * Blinding
+     * T = T * Vi mod N
+     */
+    MBEDTLS_MPI_CHK(rsa_prepare_blinding(ctx, f_rng, p_rng));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &T, &ctx->Vi));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &T, &ctx->N));
 
-        /*
-         * Exponent blinding
-         */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) );
+    /*
+     * Exponent blinding
+     */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&P1, &ctx->P, 1));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&Q1, &ctx->Q, 1));
 
 #if defined(MBEDTLS_RSA_NO_CRT)
-        /*
-         * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D
-         */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING,
-                         f_rng, p_rng ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) );
+    /*
+     * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D
+     */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING,
+                                            f_rng, p_rng));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &P1, &Q1));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &D_blind, &R));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&D_blind, &D_blind, &ctx->D));
 
-        D = &D_blind;
+    D = &D_blind;
 #else
-        /*
-         * DP_blind = ( P - 1 ) * R + DP
-         */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING,
-                         f_rng, p_rng ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind,
-                    &ctx->DP ) );
+    /*
+     * DP_blind = ( P - 1 ) * R + DP
+     */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING,
+                                            f_rng, p_rng));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&DP_blind, &P1, &R));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DP_blind, &DP_blind,
+                                        &ctx->DP));
 
-        DP = &DP_blind;
+    DP = &DP_blind;
 
-        /*
-         * DQ_blind = ( Q - 1 ) * R + DQ
-         */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING,
-                         f_rng, p_rng ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind,
-                    &ctx->DQ ) );
+    /*
+     * DQ_blind = ( Q - 1 ) * R + DQ
+     */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING,
+                                            f_rng, p_rng));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&DQ_blind, &Q1, &R));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DQ_blind, &DQ_blind,
+                                        &ctx->DQ));
 
-        DQ = &DQ_blind;
+    DQ = &DQ_blind;
 #endif /* MBEDTLS_RSA_NO_CRT */
-    }
 
 #if defined(MBEDTLS_RSA_NO_CRT)
-    MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, D, &ctx->N, &ctx->RN));
 #else
     /*
      * Faster decryption using the CRT
@@ -1005,78 +1004,73 @@
      * TQ = input ^ dQ mod Q
      */
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TP, &T, DP, &ctx->P, &ctx->RP ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TQ, &T, DQ, &ctx->Q, &ctx->RQ ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TP, &T, DP, &ctx->P, &ctx->RP));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TQ, &T, DQ, &ctx->Q, &ctx->RQ));
 
     /*
      * T = (TP - TQ) * (Q^-1 mod P) mod P
      */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &TP, &TQ ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->QP ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &TP, &ctx->P ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&T, &TP, &TQ));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&TP, &T, &ctx->QP));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &TP, &ctx->P));
 
     /*
      * T = TQ + T * Q
      */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->Q ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &TQ, &TP ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&TP, &T, &ctx->Q));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&T, &TQ, &TP));
 #endif /* MBEDTLS_RSA_NO_CRT */
 
-    if( f_rng != NULL )
-    {
-        /*
-         * Unblind
-         * T = T * Vf mod N
-         */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) );
-    }
+    /*
+     * Unblind
+     * T = T * Vf mod N
+     */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &T, &ctx->Vf));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &T, &ctx->N));
 
     /* Verify the result to prevent glitching attacks. */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &C, &T, &ctx->E,
-                                          &ctx->N, &ctx->RN ) );
-    if( mbedtls_mpi_cmp_mpi( &C, &I ) != 0 )
-    {
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&C, &T, &ctx->E,
+                                        &ctx->N, &ctx->RN));
+    if (mbedtls_mpi_cmp_mpi(&C, &I) != 0) {
         ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;
         goto cleanup;
     }
 
     olen = ctx->len;
-    MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&T, output, olen));
 
 cleanup:
 #if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
-        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
-#endif
-
-    mbedtls_mpi_free( &P1 );
-    mbedtls_mpi_free( &Q1 );
-    mbedtls_mpi_free( &R );
-
-    if( f_rng != NULL )
-    {
-#if defined(MBEDTLS_RSA_NO_CRT)
-        mbedtls_mpi_free( &D_blind );
-#else
-        mbedtls_mpi_free( &DP_blind );
-        mbedtls_mpi_free( &DQ_blind );
-#endif
+    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
+        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
     }
+#endif
 
-    mbedtls_mpi_free( &T );
+    mbedtls_mpi_free(&P1);
+    mbedtls_mpi_free(&Q1);
+    mbedtls_mpi_free(&R);
+
+#if defined(MBEDTLS_RSA_NO_CRT)
+    mbedtls_mpi_free(&D_blind);
+#else
+    mbedtls_mpi_free(&DP_blind);
+    mbedtls_mpi_free(&DQ_blind);
+#endif
+
+    mbedtls_mpi_free(&T);
 
 #if !defined(MBEDTLS_RSA_NO_CRT)
-    mbedtls_mpi_free( &TP ); mbedtls_mpi_free( &TQ );
+    mbedtls_mpi_free(&TP); mbedtls_mpi_free(&TQ);
 #endif
 
-    mbedtls_mpi_free( &C );
-    mbedtls_mpi_free( &I );
+    mbedtls_mpi_free(&C);
+    mbedtls_mpi_free(&I);
 
-    if( ret != 0 && ret >= -0x007f )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_PRIVATE_FAILED, ret ) );
+    if (ret != 0 && ret >= -0x007f) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_PRIVATE_FAILED, ret);
+    }
 
-    return( ret );
+    return ret;
 }
 
 #if defined(MBEDTLS_PKCS1_V21)
@@ -1087,43 +1081,86 @@
  * \param dlen      length of destination buffer
  * \param src       source of the mask generation
  * \param slen      length of the source buffer
- * \param md_ctx    message digest context to use
+ * \param md_alg    message digest to use
  */
-static int mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src,
-                      size_t slen, mbedtls_md_context_t *md_ctx )
+static int mgf_mask(unsigned char *dst, size_t dlen, unsigned char *src,
+                    size_t slen, mbedtls_md_type_t md_alg)
 {
-    unsigned char mask[MBEDTLS_MD_MAX_SIZE];
     unsigned char counter[4];
     unsigned char *p;
     unsigned int hlen;
     size_t i, use_len;
+    unsigned char mask[MBEDTLS_HASH_MAX_SIZE];
+#if defined(MBEDTLS_MD_C)
     int ret = 0;
+    const mbedtls_md_info_t *md_info;
+    mbedtls_md_context_t md_ctx;
 
-    memset( mask, 0, MBEDTLS_MD_MAX_SIZE );
-    memset( counter, 0, 4 );
+    mbedtls_md_init(&md_ctx);
+    md_info = mbedtls_md_info_from_type(md_alg);
+    if (md_info == NULL) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
-    hlen = mbedtls_md_get_size( md_ctx->md_info );
+    mbedtls_md_init(&md_ctx);
+    if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) {
+        goto exit;
+    }
+
+    hlen = mbedtls_md_get_size(md_info);
+#else
+    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
+    psa_algorithm_t alg = mbedtls_psa_translate_md(md_alg);
+    psa_status_t status = PSA_SUCCESS;
+    size_t out_len;
+
+    hlen = PSA_HASH_LENGTH(alg);
+#endif
+
+    memset(mask, 0, sizeof(mask));
+    memset(counter, 0, 4);
 
     /* Generate and apply dbMask */
     p = dst;
 
-    while( dlen > 0 )
-    {
+    while (dlen > 0) {
         use_len = hlen;
-        if( dlen < hlen )
+        if (dlen < hlen) {
             use_len = dlen;
+        }
 
-        if( ( ret = mbedtls_md_starts( md_ctx ) ) != 0 )
+#if defined(MBEDTLS_MD_C)
+        if ((ret = mbedtls_md_starts(&md_ctx)) != 0) {
             goto exit;
-        if( ( ret = mbedtls_md_update( md_ctx, src, slen ) ) != 0 )
+        }
+        if ((ret = mbedtls_md_update(&md_ctx, src, slen)) != 0) {
             goto exit;
-        if( ( ret = mbedtls_md_update( md_ctx, counter, 4 ) ) != 0 )
+        }
+        if ((ret = mbedtls_md_update(&md_ctx, counter, 4)) != 0) {
             goto exit;
-        if( ( ret = mbedtls_md_finish( md_ctx, mask ) ) != 0 )
+        }
+        if ((ret = mbedtls_md_finish(&md_ctx, mask)) != 0) {
             goto exit;
+        }
+#else
+        if ((status = psa_hash_setup(&op, alg)) != PSA_SUCCESS) {
+            goto exit;
+        }
+        if ((status = psa_hash_update(&op, src, slen)) != PSA_SUCCESS) {
+            goto exit;
+        }
+        if ((status = psa_hash_update(&op, counter, 4)) != PSA_SUCCESS) {
+            goto exit;
+        }
+        status = psa_hash_finish(&op, mask, sizeof(mask), &out_len);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+#endif
 
-        for( i = 0; i < use_len; ++i )
+        for (i = 0; i < use_len; ++i) {
             *p++ ^= mask[i];
+        }
 
         counter[3]++;
 
@@ -1131,9 +1168,129 @@
     }
 
 exit:
-    mbedtls_platform_zeroize( mask, sizeof( mask ) );
+    mbedtls_platform_zeroize(mask, sizeof(mask));
+#if defined(MBEDTLS_MD_C)
+    mbedtls_md_free(&md_ctx);
 
-    return( ret );
+    return ret;
+#else
+    psa_hash_abort(&op);
+
+    return PSA_TO_MBEDTLS_ERR(status);
+#endif
+}
+
+/**
+ * Generate Hash(M') as in RFC 8017 page 43 points 5 and 6.
+ *
+ * \param hash      the input hash
+ * \param hlen      length of the input hash
+ * \param salt      the input salt
+ * \param slen      length of the input salt
+ * \param out       the output buffer - must be large enough for \p md_alg
+ * \param md_alg    message digest to use
+ */
+static int hash_mprime(const unsigned char *hash, size_t hlen,
+                       const unsigned char *salt, size_t slen,
+                       unsigned char *out, mbedtls_md_type_t md_alg)
+{
+    const unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+#if defined(MBEDTLS_MD_C)
+    mbedtls_md_context_t md_ctx;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_alg);
+    if (md_info == NULL) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
+
+    mbedtls_md_init(&md_ctx);
+    if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) {
+        goto exit;
+    }
+    if ((ret = mbedtls_md_starts(&md_ctx)) != 0) {
+        goto exit;
+    }
+    if ((ret = mbedtls_md_update(&md_ctx, zeros, sizeof(zeros))) != 0) {
+        goto exit;
+    }
+    if ((ret = mbedtls_md_update(&md_ctx, hash, hlen)) != 0) {
+        goto exit;
+    }
+    if ((ret = mbedtls_md_update(&md_ctx, salt, slen)) != 0) {
+        goto exit;
+    }
+    if ((ret = mbedtls_md_finish(&md_ctx, out)) != 0) {
+        goto exit;
+    }
+
+exit:
+    mbedtls_md_free(&md_ctx);
+
+    return ret;
+#else
+    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
+    psa_algorithm_t alg = mbedtls_psa_translate_md(md_alg);
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t out_size = PSA_HASH_LENGTH(alg);
+    size_t out_len;
+
+    if ((status = psa_hash_setup(&op, alg)) != PSA_SUCCESS) {
+        goto exit;
+    }
+    if ((status = psa_hash_update(&op, zeros, sizeof(zeros))) != PSA_SUCCESS) {
+        goto exit;
+    }
+    if ((status = psa_hash_update(&op, hash, hlen)) != PSA_SUCCESS) {
+        goto exit;
+    }
+    if ((status = psa_hash_update(&op, salt, slen)) != PSA_SUCCESS) {
+        goto exit;
+    }
+    status = psa_hash_finish(&op, out, out_size, &out_len);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+exit:
+    psa_hash_abort(&op);
+
+    return PSA_TO_MBEDTLS_ERR(status);
+#endif /* !MBEDTLS_MD_C */
+}
+
+/**
+ * Compute a hash.
+ *
+ * \param md_alg    algorithm to use
+ * \param input     input message to hash
+ * \param ilen      input length
+ * \param output    the output buffer - must be large enough for \p md_alg
+ */
+static int compute_hash(mbedtls_md_type_t md_alg,
+                        const unsigned char *input, size_t ilen,
+                        unsigned char *output)
+{
+#if defined(MBEDTLS_MD_C)
+    const mbedtls_md_info_t *md_info;
+
+    md_info = mbedtls_md_info_from_type(md_alg);
+    if (md_info == NULL) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
+
+    return mbedtls_md(md_info, input, ilen, output);
+#else
+    psa_algorithm_t alg = mbedtls_psa_translate_md(md_alg);
+    psa_status_t status;
+    size_t out_size = PSA_HASH_LENGTH(alg);
+    size_t out_len;
+
+    status = psa_hash_compute(alg, input, ilen, output, out_size, &out_len);
+
+    return PSA_TO_MBEDTLS_ERR(status);
+#endif /* !MBEDTLS_MD_C */
 }
 #endif /* MBEDTLS_PKCS1_V21 */
 
@@ -1141,88 +1298,71 @@
 /*
  * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function
  */
-int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx,
-                            int (*f_rng)(void *, unsigned char *, size_t),
-                            void *p_rng,
-                            int mode,
-                            const unsigned char *label, size_t label_len,
-                            size_t ilen,
-                            const unsigned char *input,
-                            unsigned char *output )
+int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx,
+                                   int (*f_rng)(void *, unsigned char *, size_t),
+                                   void *p_rng,
+                                   const unsigned char *label, size_t label_len,
+                                   size_t ilen,
+                                   const unsigned char *input,
+                                   unsigned char *output)
 {
     size_t olen;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *p = output;
     unsigned int hlen;
-    const mbedtls_md_info_t *md_info;
-    mbedtls_md_context_t md_ctx;
 
-    RSA_VALIDATE_RET( ctx != NULL );
-    RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
-                      mode == MBEDTLS_RSA_PUBLIC );
-    RSA_VALIDATE_RET( output != NULL );
-    RSA_VALIDATE_RET( ilen == 0 || input != NULL );
-    RSA_VALIDATE_RET( label_len == 0 || label != NULL );
+    if (f_rng == NULL) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
-    if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
-    if( f_rng == NULL )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
-    md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id );
-    if( md_info == NULL )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    hlen = mbedtls_hash_info_get_size((mbedtls_md_type_t) ctx->hash_id);
+    if (hlen == 0) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
     olen = ctx->len;
-    hlen = mbedtls_md_get_size( md_info );
 
     /* first comparison checks for overflow */
-    if( ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2 )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
-    memset( output, 0, olen );
+    memset(output, 0, olen);
 
     *p++ = 0;
 
     /* Generate a random octet string seed */
-    if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_RNG_FAILED, ret ) );
+    if ((ret = f_rng(p_rng, p, hlen)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_RNG_FAILED, ret);
+    }
 
     p += hlen;
 
     /* Construct DB */
-    if( ( ret = mbedtls_md( md_info, label, label_len, p ) ) != 0 )
-        return( ret );
+    ret = compute_hash((mbedtls_md_type_t) ctx->hash_id, label, label_len, p);
+    if (ret != 0) {
+        return ret;
+    }
     p += hlen;
     p += olen - 2 * hlen - 2 - ilen;
     *p++ = 1;
-    if( ilen != 0 )
-        memcpy( p, input, ilen );
-
-    mbedtls_md_init( &md_ctx );
-    if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
-        goto exit;
+    if (ilen != 0) {
+        memcpy(p, input, ilen);
+    }
 
     /* maskedDB: Apply dbMask to DB */
-    if( ( ret = mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen,
-                          &md_ctx ) ) != 0 )
-        goto exit;
+    if ((ret = mgf_mask(output + hlen + 1, olen - hlen - 1, output + 1, hlen,
+                        ctx->hash_id)) != 0) {
+        return ret;
+    }
 
     /* maskedSeed: Apply seedMask to seed */
-    if( ( ret = mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1,
-                          &md_ctx ) ) != 0 )
-        goto exit;
+    if ((ret = mgf_mask(output + 1, hlen, output + hlen + 1, olen - hlen - 1,
+                        ctx->hash_id)) != 0) {
+        return ret;
+    }
 
-exit:
-    mbedtls_md_free( &md_ctx );
-
-    if( ret != 0 )
-        return( ret );
-
-    return( ( mode == MBEDTLS_RSA_PUBLIC )
-            ? mbedtls_rsa_public(  ctx, output, output )
-            : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) );
+    return mbedtls_rsa_public(ctx, output, output);
 }
 #endif /* MBEDTLS_PKCS1_V21 */
 
@@ -1230,107 +1370,82 @@
 /*
  * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function
  */
-int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx,
-                                 int (*f_rng)(void *, unsigned char *, size_t),
-                                 void *p_rng,
-                                 int mode, size_t ilen,
-                                 const unsigned char *input,
-                                 unsigned char *output )
+int mbedtls_rsa_rsaes_pkcs1_v15_encrypt(mbedtls_rsa_context *ctx,
+                                        int (*f_rng)(void *, unsigned char *, size_t),
+                                        void *p_rng, size_t ilen,
+                                        const unsigned char *input,
+                                        unsigned char *output)
 {
     size_t nb_pad, olen;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *p = output;
 
-    RSA_VALIDATE_RET( ctx != NULL );
-    RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
-                      mode == MBEDTLS_RSA_PUBLIC );
-    RSA_VALIDATE_RET( output != NULL );
-    RSA_VALIDATE_RET( ilen == 0 || input != NULL );
-
-    if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
     olen = ctx->len;
 
     /* first comparison checks for overflow */
-    if( ilen + 11 < ilen || olen < ilen + 11 )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (ilen + 11 < ilen || olen < ilen + 11) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
     nb_pad = olen - 3 - ilen;
 
     *p++ = 0;
-    if( mode == MBEDTLS_RSA_PUBLIC )
-    {
-        if( f_rng == NULL )
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
 
-        *p++ = MBEDTLS_RSA_CRYPT;
-
-        while( nb_pad-- > 0 )
-        {
-            int rng_dl = 100;
-
-            do {
-                ret = f_rng( p_rng, p, 1 );
-            } while( *p == 0 && --rng_dl && ret == 0 );
-
-            /* Check if RNG failed to generate data */
-            if( rng_dl == 0 || ret != 0 )
-                return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_RNG_FAILED, ret ) );
-
-            p++;
-        }
+    if (f_rng == NULL) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
-    else
-    {
-        *p++ = MBEDTLS_RSA_SIGN;
 
-        while( nb_pad-- > 0 )
-            *p++ = 0xFF;
+    *p++ = MBEDTLS_RSA_CRYPT;
+
+    while (nb_pad-- > 0) {
+        int rng_dl = 100;
+
+        do {
+            ret = f_rng(p_rng, p, 1);
+        } while (*p == 0 && --rng_dl && ret == 0);
+
+        /* Check if RNG failed to generate data */
+        if (rng_dl == 0 || ret != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_RNG_FAILED, ret);
+        }
+
+        p++;
     }
 
     *p++ = 0;
-    if( ilen != 0 )
-        memcpy( p, input, ilen );
+    if (ilen != 0) {
+        memcpy(p, input, ilen);
+    }
 
-    return( ( mode == MBEDTLS_RSA_PUBLIC )
-            ? mbedtls_rsa_public(  ctx, output, output )
-            : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) );
+    return mbedtls_rsa_public(ctx, output, output);
 }
 #endif /* MBEDTLS_PKCS1_V15 */
 
 /*
  * Add the message padding, then do an RSA operation
  */
-int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx,
-                       int (*f_rng)(void *, unsigned char *, size_t),
-                       void *p_rng,
-                       int mode, size_t ilen,
-                       const unsigned char *input,
-                       unsigned char *output )
+int mbedtls_rsa_pkcs1_encrypt(mbedtls_rsa_context *ctx,
+                              int (*f_rng)(void *, unsigned char *, size_t),
+                              void *p_rng,
+                              size_t ilen,
+                              const unsigned char *input,
+                              unsigned char *output)
 {
-    RSA_VALIDATE_RET( ctx != NULL );
-    RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
-                      mode == MBEDTLS_RSA_PUBLIC );
-    RSA_VALIDATE_RET( output != NULL );
-    RSA_VALIDATE_RET( ilen == 0 || input != NULL );
-
-    switch( ctx->padding )
-    {
+    switch (ctx->padding) {
 #if defined(MBEDTLS_PKCS1_V15)
         case MBEDTLS_RSA_PKCS_V15:
-            return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen,
-                                                input, output );
+            return mbedtls_rsa_rsaes_pkcs1_v15_encrypt(ctx, f_rng, p_rng,
+                                                       ilen, input, output);
 #endif
 
 #if defined(MBEDTLS_PKCS1_V21)
         case MBEDTLS_RSA_PKCS_V21:
-            return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0,
-                                           ilen, input, output );
+            return mbedtls_rsa_rsaes_oaep_encrypt(ctx, f_rng, p_rng, NULL, 0,
+                                                  ilen, input, output);
 #endif
 
         default:
-            return( MBEDTLS_ERR_RSA_INVALID_PADDING );
+            return MBEDTLS_ERR_RSA_INVALID_PADDING;
     }
 }
 
@@ -1338,95 +1453,75 @@
 /*
  * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function
  */
-int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx,
-                            int (*f_rng)(void *, unsigned char *, size_t),
-                            void *p_rng,
-                            int mode,
-                            const unsigned char *label, size_t label_len,
-                            size_t *olen,
-                            const unsigned char *input,
-                            unsigned char *output,
-                            size_t output_max_len )
+int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx,
+                                   int (*f_rng)(void *, unsigned char *, size_t),
+                                   void *p_rng,
+                                   const unsigned char *label, size_t label_len,
+                                   size_t *olen,
+                                   const unsigned char *input,
+                                   unsigned char *output,
+                                   size_t output_max_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t ilen, i, pad_len;
     unsigned char *p, bad, pad_done;
     unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
-    unsigned char lhash[MBEDTLS_MD_MAX_SIZE];
+    unsigned char lhash[MBEDTLS_HASH_MAX_SIZE];
     unsigned int hlen;
-    const mbedtls_md_info_t *md_info;
-    mbedtls_md_context_t md_ctx;
-
-    RSA_VALIDATE_RET( ctx != NULL );
-    RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
-                      mode == MBEDTLS_RSA_PUBLIC );
-    RSA_VALIDATE_RET( output_max_len == 0 || output != NULL );
-    RSA_VALIDATE_RET( label_len == 0 || label != NULL );
-    RSA_VALIDATE_RET( input != NULL );
-    RSA_VALIDATE_RET( olen != NULL );
 
     /*
      * Parameters sanity checks
      */
-    if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (ctx->padding != MBEDTLS_RSA_PKCS_V21) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
     ilen = ctx->len;
 
-    if( ilen < 16 || ilen > sizeof( buf ) )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (ilen < 16 || ilen > sizeof(buf)) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
-    md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id );
-    if( md_info == NULL )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
-    hlen = mbedtls_md_get_size( md_info );
+    hlen = mbedtls_hash_info_get_size((mbedtls_md_type_t) ctx->hash_id);
+    if (hlen == 0) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
     // checking for integer underflow
-    if( 2 * hlen + 2 > ilen )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (2 * hlen + 2 > ilen) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
     /*
      * RSA operation
      */
     if( ctx->P.n == 0 )
-        ret = ( mode == MBEDTLS_RSA_PUBLIC )
-              ? mbedtls_rsa_public(  ctx, input, buf )
-              : mbedtls_rsa_private( ctx, NULL, NULL, input, buf );
+        ret = mbedtls_rsa_private( ctx, NULL, NULL, input, buf );
     else
-        ret = ( mode == MBEDTLS_RSA_PUBLIC )
-              ? mbedtls_rsa_public(  ctx, input, buf )
-              : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf );
+        ret = mbedtls_rsa_private(ctx, f_rng, p_rng, input, buf);
 
-    if( ret != 0 )
+    if (ret != 0) {
         goto cleanup;
+    }
 
     /*
      * Unmask data and generate lHash
      */
-    mbedtls_md_init( &md_ctx );
-    if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
-    {
-        mbedtls_md_free( &md_ctx );
-        goto cleanup;
-    }
-
     /* seed: Apply seedMask to maskedSeed */
-    if( ( ret = mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1,
-                          &md_ctx ) ) != 0 ||
-    /* DB: Apply dbMask to maskedDB */
-        ( ret = mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen,
-                          &md_ctx ) ) != 0 )
-    {
-        mbedtls_md_free( &md_ctx );
+    if ((ret = mgf_mask(buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1,
+                        ctx->hash_id)) != 0 ||
+        /* DB: Apply dbMask to maskedDB */
+        (ret = mgf_mask(buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen,
+                        ctx->hash_id)) != 0) {
         goto cleanup;
     }
 
-    mbedtls_md_free( &md_ctx );
-
     /* Generate lHash */
-    if( ( ret = mbedtls_md( md_info, label, label_len, lhash ) ) != 0 )
+    ret = compute_hash((mbedtls_md_type_t) ctx->hash_id,
+                       label, label_len, lhash);
+    if (ret != 0) {
         goto cleanup;
+    }
 
     /*
      * Check contents, in "constant-time"
@@ -1439,17 +1534,17 @@
     p += hlen; /* Skip seed */
 
     /* Check lHash */
-    for( i = 0; i < hlen; i++ )
+    for (i = 0; i < hlen; i++) {
         bad |= lhash[i] ^ *p++;
+    }
 
     /* Get zero-padding len, but always read till end of buffer
      * (minus one, for the 01 byte) */
     pad_len = 0;
     pad_done = 0;
-    for( i = 0; i < ilen - 2 * hlen - 2; i++ )
-    {
+    for (i = 0; i < ilen - 2 * hlen - 2; i++) {
         pad_done |= p[i];
-        pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1;
+        pad_len += ((pad_done | (unsigned char) -pad_done) >> 7) ^ 1;
     }
 
     p += pad_len;
@@ -1461,28 +1556,27 @@
      * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between
      * the different error conditions.
      */
-    if( bad != 0 )
-    {
+    if (bad != 0) {
         ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
         goto cleanup;
     }
 
-    if( ilen - ( p - buf ) > output_max_len )
-    {
+    if (ilen - (p - buf) > output_max_len) {
         ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
         goto cleanup;
     }
 
     *olen = ilen - (p - buf);
-    if( *olen != 0 )
-        memcpy( output, p, *olen );
+    if (*olen != 0) {
+        memcpy(output, p, *olen);
+    }
     ret = 0;
 
 cleanup:
-    mbedtls_platform_zeroize( buf, sizeof( buf ) );
-    mbedtls_platform_zeroize( lhash, sizeof( lhash ) );
+    mbedtls_platform_zeroize(buf, sizeof(buf));
+    mbedtls_platform_zeroize(lhash, sizeof(lhash));
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_PKCS1_V21 */
 
@@ -1490,99 +1584,83 @@
 /*
  * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function
  */
-int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
-                                 int (*f_rng)(void *, unsigned char *, size_t),
-                                 void *p_rng,
-                                 int mode,
-                                 size_t *olen,
-                                 const unsigned char *input,
-                                 unsigned char *output,
-                                 size_t output_max_len )
+int mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_rsa_context *ctx,
+                                        int (*f_rng)(void *, unsigned char *, size_t),
+                                        void *p_rng,
+                                        size_t *olen,
+                                        const unsigned char *input,
+                                        unsigned char *output,
+                                        size_t output_max_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t ilen;
     unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
 
-    RSA_VALIDATE_RET( ctx != NULL );
-    RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
-                      mode == MBEDTLS_RSA_PUBLIC );
-    RSA_VALIDATE_RET( output_max_len == 0 || output != NULL );
-    RSA_VALIDATE_RET( input != NULL );
-    RSA_VALIDATE_RET( olen != NULL );
-
     ilen = ctx->len;
 
-    if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (ctx->padding != MBEDTLS_RSA_PKCS_V15) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
-    if( ilen < 16 || ilen > sizeof( buf ) )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (ilen < 16 || ilen > sizeof(buf)) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
-    ret = ( mode == MBEDTLS_RSA_PUBLIC )
-          ? mbedtls_rsa_public(  ctx, input, buf )
-          : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf );
+    ret = mbedtls_rsa_private(ctx, f_rng, p_rng, input, buf);
 
-    if( ret != 0 )
+    if (ret != 0) {
         goto cleanup;
+    }
 
-    ret = mbedtls_ct_rsaes_pkcs1_v15_unpadding( mode, buf, ilen,
-                                                output, output_max_len, olen );
+    ret = mbedtls_ct_rsaes_pkcs1_v15_unpadding(buf, ilen,
+                                               output, output_max_len, olen);
 
 cleanup:
-    mbedtls_platform_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize(buf, sizeof(buf));
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_PKCS1_V15 */
 
 /*
  * Do an RSA operation, then remove the message padding
  */
-int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx,
-                       int (*f_rng)(void *, unsigned char *, size_t),
-                       void *p_rng,
-                       int mode, size_t *olen,
-                       const unsigned char *input,
-                       unsigned char *output,
-                       size_t output_max_len)
+int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx,
+                              int (*f_rng)(void *, unsigned char *, size_t),
+                              void *p_rng,
+                              size_t *olen,
+                              const unsigned char *input,
+                              unsigned char *output,
+                              size_t output_max_len)
 {
-    RSA_VALIDATE_RET( ctx != NULL );
-    RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
-                      mode == MBEDTLS_RSA_PUBLIC );
-    RSA_VALIDATE_RET( output_max_len == 0 || output != NULL );
-    RSA_VALIDATE_RET( input != NULL );
-    RSA_VALIDATE_RET( olen != NULL );
-
-    switch( ctx->padding )
-    {
+    switch (ctx->padding) {
 #if defined(MBEDTLS_PKCS1_V15)
         case MBEDTLS_RSA_PKCS_V15:
-            return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen,
-                                                input, output, output_max_len );
+            return mbedtls_rsa_rsaes_pkcs1_v15_decrypt(ctx, f_rng, p_rng, olen,
+                                                       input, output, output_max_len);
 #endif
 
 #if defined(MBEDTLS_PKCS1_V21)
         case MBEDTLS_RSA_PKCS_V21:
-            return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0,
-                                           olen, input, output,
-                                           output_max_len );
+            return mbedtls_rsa_rsaes_oaep_decrypt(ctx, f_rng, p_rng, NULL, 0,
+                                                  olen, input, output,
+                                                  output_max_len);
 #endif
 
         default:
-            return( MBEDTLS_ERR_RSA_INVALID_PADDING );
+            return MBEDTLS_ERR_RSA_INVALID_PADDING;
     }
 }
 
 #if defined(MBEDTLS_PKCS1_V21)
-static int rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
-                         int (*f_rng)(void *, unsigned char *, size_t),
-                         void *p_rng,
-                         int mode,
-                         mbedtls_md_type_t md_alg,
-                         unsigned int hashlen,
-                         const unsigned char *hash,
-                         int saltlen,
-                         unsigned char *sig )
+static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,
+                               int (*f_rng)(void *, unsigned char *, size_t),
+                               void *p_rng,
+                               mbedtls_md_type_t md_alg,
+                               unsigned int hashlen,
+                               const unsigned char *hash,
+                               int saltlen,
+                               unsigned char *sig)
 {
     size_t olen;
     unsigned char *p = sig;
@@ -1590,159 +1668,136 @@
     size_t slen, min_slen, hlen, offset = 0;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t msb;
-    const mbedtls_md_info_t *md_info;
-    mbedtls_md_context_t md_ctx;
-    RSA_VALIDATE_RET( ctx != NULL );
-    RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
-                      mode == MBEDTLS_RSA_PUBLIC );
-    RSA_VALIDATE_RET( ( md_alg  == MBEDTLS_MD_NONE &&
-                        hashlen == 0 ) ||
-                      hash != NULL );
-    RSA_VALIDATE_RET( sig != NULL );
 
-    if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
-    if( f_rng == NULL )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (ctx->padding != MBEDTLS_RSA_PKCS_V21) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
+
+    if (f_rng == NULL) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
     olen = ctx->len;
 
-    if( md_alg != MBEDTLS_MD_NONE )
-    {
+    if (md_alg != MBEDTLS_MD_NONE) {
         /* Gather length of hash to sign */
-        md_info = mbedtls_md_info_from_type( md_alg );
-        if( md_info == NULL )
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+        size_t exp_hashlen = mbedtls_hash_info_get_size(md_alg);
+        if (exp_hashlen == 0) {
+            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+        }
 
-        hashlen = mbedtls_md_get_size( md_info );
+        if (hashlen != exp_hashlen) {
+            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+        }
     }
 
-    md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id );
-    if( md_info == NULL )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    hlen = mbedtls_hash_info_get_size((mbedtls_md_type_t) ctx->hash_id);
+    if (hlen == 0) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
-    hlen = mbedtls_md_get_size( md_info );
-
-    if (saltlen == MBEDTLS_RSA_SALT_LEN_ANY)
-    {
-       /* Calculate the largest possible salt length, up to the hash size.
-        * Normally this is the hash length, which is the maximum salt length
-        * according to FIPS 185-4 §5.5 (e) and common practice. If there is not
-        * enough room, use the maximum salt length that fits. The constraint is
-        * that the hash length plus the salt length plus 2 bytes must be at most
-        * the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017
-        * (PKCS#1 v2.2) §9.1.1 step 3. */
+    if (saltlen == MBEDTLS_RSA_SALT_LEN_ANY) {
+        /* Calculate the largest possible salt length, up to the hash size.
+         * Normally this is the hash length, which is the maximum salt length
+         * according to FIPS 185-4 §5.5 (e) and common practice. If there is not
+         * enough room, use the maximum salt length that fits. The constraint is
+         * that the hash length plus the salt length plus 2 bytes must be at most
+         * the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017
+         * (PKCS#1 v2.2) §9.1.1 step 3. */
         min_slen = hlen - 2;
-        if( olen < hlen + min_slen + 2 )
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-        else if( olen >= hlen + hlen + 2 )
+        if (olen < hlen + min_slen + 2) {
+            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+        } else if (olen >= hlen + hlen + 2) {
             slen = hlen;
-        else
+        } else {
             slen = olen - hlen - 2;
-    }
-    else if ( (saltlen < 0) || (saltlen + hlen + 2 > olen) )
-    {
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-    }
-    else
-    {
+        }
+    } else if ((saltlen < 0) || (saltlen + hlen + 2 > olen)) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    } else {
         slen = (size_t) saltlen;
     }
 
-    memset( sig, 0, olen );
+    memset(sig, 0, olen);
 
     /* Note: EMSA-PSS encoding is over the length of N - 1 bits */
-    msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
+    msb = mbedtls_mpi_bitlen(&ctx->N) - 1;
     p += olen - hlen - slen - 2;
     *p++ = 0x01;
 
     /* Generate salt of length slen in place in the encoded message */
     salt = p;
-    if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_RNG_FAILED, ret ) );
+    if ((ret = f_rng(p_rng, salt, slen)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_RNG_FAILED, ret);
+    }
 
     p += slen;
 
-    mbedtls_md_init( &md_ctx );
-    if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
-        goto exit;
-
     /* Generate H = Hash( M' ) */
-    if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 )
-        goto exit;
-    if( ( ret = mbedtls_md_update( &md_ctx, p, 8 ) ) != 0 )
-        goto exit;
-    if( ( ret = mbedtls_md_update( &md_ctx, hash, hashlen ) ) != 0 )
-        goto exit;
-    if( ( ret = mbedtls_md_update( &md_ctx, salt, slen ) ) != 0 )
-        goto exit;
-    if( ( ret = mbedtls_md_finish( &md_ctx, p ) ) != 0 )
-        goto exit;
+    ret = hash_mprime(hash, hashlen, salt, slen, p, ctx->hash_id);
+    if (ret != 0) {
+        return ret;
+    }
 
     /* Compensate for boundary condition when applying mask */
-    if( msb % 8 == 0 )
+    if (msb % 8 == 0) {
         offset = 1;
+    }
 
     /* maskedDB: Apply dbMask to DB */
-    if( ( ret = mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen,
-                          &md_ctx ) ) != 0 )
-        goto exit;
+    ret = mgf_mask(sig + offset, olen - hlen - 1 - offset, p, hlen,
+                   ctx->hash_id);
+    if (ret != 0) {
+        return ret;
+    }
 
-    msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
-    sig[0] &= 0xFF >> ( olen * 8 - msb );
+    msb = mbedtls_mpi_bitlen(&ctx->N) - 1;
+    sig[0] &= 0xFF >> (olen * 8 - msb);
 
     p += hlen;
     *p++ = 0xBC;
 
-exit:
-    mbedtls_md_free( &md_ctx );
+    if (ctx->P.n == 0)
+        return mbedtls_rsa_private(ctx, NULL, NULL, sig, sig);
 
-    if( ret != 0 )
-        return( ret );
-
-    if( ctx->P.n == 0)
-        return( ( mode == MBEDTLS_RSA_PUBLIC )
-                ? mbedtls_rsa_public(  ctx, sig, sig )
-                : mbedtls_rsa_private( ctx, NULL, NULL, sig, sig ) );
-    else
-        return( ( mode == MBEDTLS_RSA_PUBLIC )
-                ? mbedtls_rsa_public(  ctx, sig, sig )
-                : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) );
+    return mbedtls_rsa_private(ctx, f_rng, p_rng, sig, sig);
 }
 
 /*
  * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function with
  * the option to pass in the salt length.
  */
-int mbedtls_rsa_rsassa_pss_sign_ext( mbedtls_rsa_context *ctx,
-                         int (*f_rng)(void *, unsigned char *, size_t),
-                         void *p_rng,
-                         mbedtls_md_type_t md_alg,
-                         unsigned int hashlen,
-                         const unsigned char *hash,
-                         int saltlen,
-                         unsigned char *sig )
+int mbedtls_rsa_rsassa_pss_sign_ext(mbedtls_rsa_context *ctx,
+                                    int (*f_rng)(void *, unsigned char *, size_t),
+                                    void *p_rng,
+                                    mbedtls_md_type_t md_alg,
+                                    unsigned int hashlen,
+                                    const unsigned char *hash,
+                                    int saltlen,
+                                    unsigned char *sig)
 {
-    return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, md_alg,
-                                hashlen, hash, saltlen, sig );
+    return rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg,
+                               hashlen, hash, saltlen, sig);
 }
 
 
 /*
  * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function
  */
-int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
-                         int (*f_rng)(void *, unsigned char *, size_t),
-                         void *p_rng,
-                         int mode,
-                         mbedtls_md_type_t md_alg,
-                         unsigned int hashlen,
-                         const unsigned char *hash,
-                         unsigned char *sig )
+int mbedtls_rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,
+                                int (*f_rng)(void *, unsigned char *, size_t),
+                                void *p_rng,
+                                mbedtls_md_type_t md_alg,
+                                unsigned int hashlen,
+                                const unsigned char *hash,
+                                unsigned char *sig)
 {
-    return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg,
-                                hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig );
+    return rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg,
+                               hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig);
 }
 #endif /* MBEDTLS_PKCS1_V21 */
 
@@ -1758,22 +1813,21 @@
  * Parameters:
  * - md_alg:  Identifies the hash algorithm used to generate the given hash;
  *            MBEDTLS_MD_NONE if raw data is signed.
- * - hashlen: Length of hash in case hashlen is MBEDTLS_MD_NONE.
+ * - hashlen: Length of hash. Must match md_alg if that's not NONE.
  * - hash:    Buffer containing the hashed message or the raw data.
  * - dst_len: Length of the encoded message.
  * - dst:     Buffer to hold the encoded message.
  *
  * Assumptions:
- * - hash has size hashlen if md_alg == MBEDTLS_MD_NONE.
- * - hash has size corresponding to md_alg if md_alg != MBEDTLS_MD_NONE.
+ * - hash has size hashlen.
  * - dst points to a buffer of size at least dst_len.
  *
  */
-static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg,
-                                        unsigned int hashlen,
-                                        const unsigned char *hash,
-                                        size_t dst_len,
-                                        unsigned char *dst )
+static int rsa_rsassa_pkcs1_v15_encode(mbedtls_md_type_t md_alg,
+                                       unsigned int hashlen,
+                                       const unsigned char *hash,
+                                       size_t dst_len,
+                                       unsigned char *dst)
 {
     size_t oid_size  = 0;
     size_t nb_pad    = dst_len;
@@ -1781,23 +1835,27 @@
     const char *oid  = NULL;
 
     /* Are we signing hashed or raw data? */
-    if( md_alg != MBEDTLS_MD_NONE )
-    {
-        const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
-        if( md_info == NULL )
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (md_alg != MBEDTLS_MD_NONE) {
+        unsigned char md_size = mbedtls_hash_info_get_size(md_alg);
+        if (md_size == 0) {
+            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+        }
 
-        if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 )
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+        if (mbedtls_oid_get_oid_by_md(md_alg, &oid, &oid_size) != 0) {
+            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+        }
 
-        hashlen = mbedtls_md_get_size( md_info );
+        if (hashlen != md_size) {
+            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+        }
 
         /* Double-check that 8 + hashlen + oid_size can be used as a
          * 1-byte ASN.1 length encoding and that there's no overflow. */
-        if( 8 + hashlen + oid_size  >= 0x80         ||
+        if (8 + hashlen + oid_size  >= 0x80         ||
             10 + hashlen            <  hashlen      ||
-            10 + hashlen + oid_size <  10 + hashlen )
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+            10 + hashlen + oid_size <  10 + hashlen) {
+            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+        }
 
         /*
          * Static bounds check:
@@ -1807,22 +1865,23 @@
          * - Need hashlen bytes for hash
          * - Need oid_size bytes for hash alg OID.
          */
-        if( nb_pad < 10 + hashlen + oid_size )
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+        if (nb_pad < 10 + hashlen + oid_size) {
+            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+        }
         nb_pad -= 10 + hashlen + oid_size;
-    }
-    else
-    {
-        if( nb_pad < hashlen )
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    } else {
+        if (nb_pad < hashlen) {
+            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+        }
 
         nb_pad -= hashlen;
     }
 
     /* Need space for signature header and padding delimiter (3 bytes),
      * and 8 bytes for the minimal padding */
-    if( nb_pad < 3 + 8 )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (nb_pad < 3 + 8) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
     nb_pad -= 3;
 
     /* Now nb_pad is the amount of memory to be filled
@@ -1831,15 +1890,14 @@
     /* Write signature header and padding */
     *p++ = 0;
     *p++ = MBEDTLS_RSA_SIGN;
-    memset( p, 0xFF, nb_pad );
+    memset(p, 0xFF, nb_pad);
     p += nb_pad;
     *p++ = 0;
 
     /* Are we signing raw data? */
-    if( md_alg == MBEDTLS_MD_NONE )
-    {
-        memcpy( p, hash, hashlen );
-        return( 0 );
+    if (md_alg == MBEDTLS_MD_NONE) {
+        memcpy(p, hash, hashlen);
+        return 0;
     }
 
     /* Signing hashed data, add corresponding ASN.1 structure
@@ -1856,73 +1914,59 @@
      *                 TAG-OCTET + LEN [ HASH ] ]
      */
     *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
-    *p++ = (unsigned char)( 0x08 + oid_size + hashlen );
+    *p++ = (unsigned char) (0x08 + oid_size + hashlen);
     *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
-    *p++ = (unsigned char)( 0x04 + oid_size );
+    *p++ = (unsigned char) (0x04 + oid_size);
     *p++ = MBEDTLS_ASN1_OID;
     *p++ = (unsigned char) oid_size;
-    memcpy( p, oid, oid_size );
+    memcpy(p, oid, oid_size);
     p += oid_size;
     *p++ = MBEDTLS_ASN1_NULL;
     *p++ = 0x00;
     *p++ = MBEDTLS_ASN1_OCTET_STRING;
     *p++ = (unsigned char) hashlen;
-    memcpy( p, hash, hashlen );
+    memcpy(p, hash, hashlen);
     p += hashlen;
 
     /* Just a sanity-check, should be automatic
      * after the initial bounds check. */
-    if( p != dst + dst_len )
-    {
-        mbedtls_platform_zeroize( dst, dst_len );
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (p != dst + dst_len) {
+        mbedtls_platform_zeroize(dst, dst_len);
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Do an RSA operation to sign the message digest
  */
-int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx,
-                               int (*f_rng)(void *, unsigned char *, size_t),
-                               void *p_rng,
-                               int mode,
-                               mbedtls_md_type_t md_alg,
-                               unsigned int hashlen,
-                               const unsigned char *hash,
-                               unsigned char *sig )
+int mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx,
+                                      int (*f_rng)(void *, unsigned char *, size_t),
+                                      void *p_rng,
+                                      mbedtls_md_type_t md_alg,
+                                      unsigned int hashlen,
+                                      const unsigned char *hash,
+                                      unsigned char *sig)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *sig_try = NULL, *verif = NULL;
 
-    RSA_VALIDATE_RET( ctx != NULL );
-    RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
-                      mode == MBEDTLS_RSA_PUBLIC );
-    RSA_VALIDATE_RET( ( md_alg  == MBEDTLS_MD_NONE &&
-                        hashlen == 0 ) ||
-                      hash != NULL );
-    RSA_VALIDATE_RET( sig != NULL );
+    if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
-    if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (ctx->padding != MBEDTLS_RSA_PKCS_V15) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
     /*
      * Prepare PKCS1-v1.5 encoding (padding and hash identifier)
      */
 
-    if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash,
-                                             ctx->len, sig ) ) != 0 )
-        return( ret );
-
-    /*
-     * Call respective RSA primitive
-     */
-
-    if( mode == MBEDTLS_RSA_PUBLIC )
-    {
-        /* Skip verification on a public key operation */
-        return( mbedtls_rsa_public( ctx, sig, sig ) );
+    if ((ret = rsa_rsassa_pkcs1_v15_encode(md_alg, hashlen, hash,
+                                           ctx->len, sig)) != 0) {
+        return ret;
     }
 
     /* Private key operation
@@ -1931,76 +1975,70 @@
      * temporary buffer and check it before returning it.
      */
 
-    sig_try = mbedtls_calloc( 1, ctx->len );
-    if( sig_try == NULL )
-        return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
-
-    verif = mbedtls_calloc( 1, ctx->len );
-    if( verif == NULL )
-    {
-        mbedtls_free( sig_try );
-        return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
+    sig_try = mbedtls_calloc(1, ctx->len);
+    if (sig_try == NULL) {
+        return MBEDTLS_ERR_MPI_ALLOC_FAILED;
     }
 
-    MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) );
-    MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) );
+    verif = mbedtls_calloc(1, ctx->len);
+    if (verif == NULL) {
+        mbedtls_free(sig_try);
+        return MBEDTLS_ERR_MPI_ALLOC_FAILED;
+    }
 
-    if( mbedtls_ct_memcmp( verif, sig, ctx->len ) != 0 )
-    {
+    MBEDTLS_MPI_CHK(mbedtls_rsa_private(ctx, f_rng, p_rng, sig, sig_try));
+    MBEDTLS_MPI_CHK(mbedtls_rsa_public(ctx, sig_try, verif));
+
+    if (mbedtls_ct_memcmp(verif, sig, ctx->len) != 0) {
         ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED;
         goto cleanup;
     }
 
-    memcpy( sig, sig_try, ctx->len );
+    memcpy(sig, sig_try, ctx->len);
 
 cleanup:
-    mbedtls_platform_zeroize( sig_try, ctx->len );
-    mbedtls_platform_zeroize( verif, ctx->len );
-    mbedtls_free( sig_try );
-    mbedtls_free( verif );
+    mbedtls_platform_zeroize(sig_try, ctx->len);
+    mbedtls_platform_zeroize(verif, ctx->len);
+    mbedtls_free(sig_try);
+    mbedtls_free(verif);
 
-    if( ret != 0 )
-        memset( sig, '!', ctx->len );
-    return( ret );
+    if (ret != 0) {
+        memset(sig, '!', ctx->len);
+    }
+    return ret;
 }
 #endif /* MBEDTLS_PKCS1_V15 */
 
 /*
  * Do an RSA operation to sign the message digest
  */
-int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx,
-                    int (*f_rng)(void *, unsigned char *, size_t),
-                    void *p_rng,
-                    int mode,
-                    mbedtls_md_type_t md_alg,
-                    unsigned int hashlen,
-                    const unsigned char *hash,
-                    unsigned char *sig )
+int mbedtls_rsa_pkcs1_sign(mbedtls_rsa_context *ctx,
+                           int (*f_rng)(void *, unsigned char *, size_t),
+                           void *p_rng,
+                           mbedtls_md_type_t md_alg,
+                           unsigned int hashlen,
+                           const unsigned char *hash,
+                           unsigned char *sig)
 {
-    RSA_VALIDATE_RET( ctx != NULL );
-    RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
-                      mode == MBEDTLS_RSA_PUBLIC );
-    RSA_VALIDATE_RET( ( md_alg  == MBEDTLS_MD_NONE &&
-                        hashlen == 0 ) ||
-                      hash != NULL );
-    RSA_VALIDATE_RET( sig != NULL );
+    if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
-    switch( ctx->padding )
-    {
+    switch (ctx->padding) {
 #if defined(MBEDTLS_PKCS1_V15)
         case MBEDTLS_RSA_PKCS_V15:
-            return mbedtls_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg,
-                                              hashlen, hash, sig );
+            return mbedtls_rsa_rsassa_pkcs1_v15_sign(ctx, f_rng, p_rng,
+                                                     md_alg, hashlen, hash, sig);
 #endif
 
 #if defined(MBEDTLS_PKCS1_V21)
         case MBEDTLS_RSA_PKCS_V21:
-            return mbedtls_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg,
-                                        hashlen, hash, sig );
+            return mbedtls_rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg,
+                                               hashlen, hash, sig);
 #endif
 
         default:
-            return( MBEDTLS_ERR_RSA_INVALID_PADDING );
+            return MBEDTLS_ERR_RSA_INVALID_PADDING;
     }
 }
 
@@ -2008,182 +2046,143 @@
 /*
  * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function
  */
-int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx,
-                               int (*f_rng)(void *, unsigned char *, size_t),
-                               void *p_rng,
-                               int mode,
-                               mbedtls_md_type_t md_alg,
-                               unsigned int hashlen,
-                               const unsigned char *hash,
-                               mbedtls_md_type_t mgf1_hash_id,
-                               int expected_salt_len,
-                               const unsigned char *sig )
+int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx,
+                                      mbedtls_md_type_t md_alg,
+                                      unsigned int hashlen,
+                                      const unsigned char *hash,
+                                      mbedtls_md_type_t mgf1_hash_id,
+                                      int expected_salt_len,
+                                      const unsigned char *sig)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t siglen;
     unsigned char *p;
     unsigned char *hash_start;
-    unsigned char result[MBEDTLS_MD_MAX_SIZE];
-    unsigned char zeros[8];
+    unsigned char result[MBEDTLS_HASH_MAX_SIZE];
     unsigned int hlen;
     size_t observed_salt_len, msb;
-    const mbedtls_md_info_t *md_info;
-    mbedtls_md_context_t md_ctx;
-    unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
+    unsigned char buf[MBEDTLS_MPI_MAX_SIZE] = { 0 };
 
-    RSA_VALIDATE_RET( ctx != NULL );
-    RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
-                      mode == MBEDTLS_RSA_PUBLIC );
-    RSA_VALIDATE_RET( sig != NULL );
-    RSA_VALIDATE_RET( ( md_alg  == MBEDTLS_MD_NONE &&
-                        hashlen == 0 ) ||
-                      hash != NULL );
-
-    if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
     siglen = ctx->len;
 
-    if( siglen < 16 || siglen > sizeof( buf ) )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (siglen < 16 || siglen > sizeof(buf)) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
-    ret = ( mode == MBEDTLS_RSA_PUBLIC )
-          ? mbedtls_rsa_public(  ctx, sig, buf )
-          : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf );
+    ret = mbedtls_rsa_public(ctx, sig, buf);
 
-    if( ret != 0 )
-        return( ret );
+    if (ret != 0) {
+        return ret;
+    }
 
     p = buf;
 
-    if( buf[siglen - 1] != 0xBC )
-        return( MBEDTLS_ERR_RSA_INVALID_PADDING );
-
-    if( md_alg != MBEDTLS_MD_NONE )
-    {
-        /* Gather length of hash to sign */
-        md_info = mbedtls_md_info_from_type( md_alg );
-        if( md_info == NULL )
-            return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
-        hashlen = mbedtls_md_get_size( md_info );
+    if (buf[siglen - 1] != 0xBC) {
+        return MBEDTLS_ERR_RSA_INVALID_PADDING;
     }
 
-    md_info = mbedtls_md_info_from_type( mgf1_hash_id );
-    if( md_info == NULL )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (md_alg != MBEDTLS_MD_NONE) {
+        /* Gather length of hash to sign */
+        size_t exp_hashlen = mbedtls_hash_info_get_size(md_alg);
+        if (exp_hashlen == 0) {
+            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+        }
 
-    hlen = mbedtls_md_get_size( md_info );
+        if (hashlen != exp_hashlen) {
+            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+        }
+    }
 
-    memset( zeros, 0, 8 );
+    hlen = mbedtls_hash_info_get_size(mgf1_hash_id);
+    if (hlen == 0) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
     /*
      * Note: EMSA-PSS verification is over the length of N - 1 bits
      */
-    msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
+    msb = mbedtls_mpi_bitlen(&ctx->N) - 1;
 
-    if( buf[0] >> ( 8 - siglen * 8 + msb ) )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (buf[0] >> (8 - siglen * 8 + msb)) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
     /* Compensate for boundary condition when applying mask */
-    if( msb % 8 == 0 )
-    {
+    if (msb % 8 == 0) {
         p++;
         siglen -= 1;
     }
 
-    if( siglen < hlen + 2 )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
+    if (siglen < hlen + 2) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
     hash_start = p + siglen - hlen - 1;
 
-    mbedtls_md_init( &md_ctx );
-    if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
-        goto exit;
+    ret = mgf_mask(p, siglen - hlen - 1, hash_start, hlen, mgf1_hash_id);
+    if (ret != 0) {
+        return ret;
+    }
 
-    ret = mgf_mask( p, siglen - hlen - 1, hash_start, hlen, &md_ctx );
-    if( ret != 0 )
-        goto exit;
+    buf[0] &= 0xFF >> (siglen * 8 - msb);
 
-    buf[0] &= 0xFF >> ( siglen * 8 - msb );
-
-    while( p < hash_start - 1 && *p == 0 )
+    while (p < hash_start - 1 && *p == 0) {
         p++;
+    }
 
-    if( *p++ != 0x01 )
-    {
-        ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
-        goto exit;
+    if (*p++ != 0x01) {
+        return MBEDTLS_ERR_RSA_INVALID_PADDING;
     }
 
     observed_salt_len = hash_start - p;
 
-    if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY &&
-        observed_salt_len != (size_t) expected_salt_len )
-    {
-        ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
-        goto exit;
+    if (expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY &&
+        observed_salt_len != (size_t) expected_salt_len) {
+        return MBEDTLS_ERR_RSA_INVALID_PADDING;
     }
 
     /*
      * Generate H = Hash( M' )
      */
-    ret = mbedtls_md_starts( &md_ctx );
-    if ( ret != 0 )
-        goto exit;
-    ret = mbedtls_md_update( &md_ctx, zeros, 8 );
-    if ( ret != 0 )
-        goto exit;
-    ret = mbedtls_md_update( &md_ctx, hash, hashlen );
-    if ( ret != 0 )
-        goto exit;
-    ret = mbedtls_md_update( &md_ctx, p, observed_salt_len );
-    if ( ret != 0 )
-        goto exit;
-    ret = mbedtls_md_finish( &md_ctx, result );
-    if ( ret != 0 )
-        goto exit;
-
-    if( FTMN_CALLEE_DONE_MEMCMP( memcmp, hash_start, result, hlen ) != 0 )
-    {
-        ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;
-        goto exit;
+    ret = hash_mprime(hash, hashlen, p, observed_salt_len,
+                      result, mgf1_hash_id);
+    if (ret != 0) {
+        return ret;
     }
 
-exit:
-    mbedtls_md_free( &md_ctx );
+    if (FTMN_CALLEE_DONE_MEMCMP(memcmp, hash_start, result, hlen) != 0) {
+        return MBEDTLS_ERR_RSA_VERIFY_FAILED;
+    }
 
-    return( ret );
+    return 0;
 }
 
 /*
  * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function
  */
-int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx,
-                           int (*f_rng)(void *, unsigned char *, size_t),
-                           void *p_rng,
-                           int mode,
-                           mbedtls_md_type_t md_alg,
-                           unsigned int hashlen,
-                           const unsigned char *hash,
-                           const unsigned char *sig )
+int mbedtls_rsa_rsassa_pss_verify(mbedtls_rsa_context *ctx,
+                                  mbedtls_md_type_t md_alg,
+                                  unsigned int hashlen,
+                                  const unsigned char *hash,
+                                  const unsigned char *sig)
 {
     mbedtls_md_type_t mgf1_hash_id;
-    RSA_VALIDATE_RET( ctx != NULL );
-    RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
-                      mode == MBEDTLS_RSA_PUBLIC );
-    RSA_VALIDATE_RET( sig != NULL );
-    RSA_VALIDATE_RET( ( md_alg  == MBEDTLS_MD_NONE &&
-                        hashlen == 0 ) ||
-                      hash != NULL );
+    if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
-    mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE )
+    mgf1_hash_id = (ctx->hash_id != MBEDTLS_MD_NONE)
                              ? (mbedtls_md_type_t) ctx->hash_id
                              : md_alg;
 
-    return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode,
-                                       md_alg, hashlen, hash,
-                                       mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY,
-                                       sig ) );
+    return mbedtls_rsa_rsassa_pss_verify_ext(ctx,
+                                             md_alg, hashlen, hash,
+                                             mgf1_hash_id,
+                                             MBEDTLS_RSA_SALT_LEN_ANY,
+                                             sig);
 
 }
 #endif /* MBEDTLS_PKCS1_V21 */
@@ -2192,196 +2191,173 @@
 /*
  * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function
  */
-int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx,
-                                 int (*f_rng)(void *, unsigned char *, size_t),
-                                 void *p_rng,
-                                 int mode,
-                                 mbedtls_md_type_t md_alg,
-                                 unsigned int hashlen,
-                                 const unsigned char *hash,
-                                 const unsigned char *sig )
+int mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx,
+                                        mbedtls_md_type_t md_alg,
+                                        unsigned int hashlen,
+                                        const unsigned char *hash,
+                                        const unsigned char *sig)
 {
     int ret = 0;
     size_t sig_len;
     unsigned char *encoded = NULL, *encoded_expected = NULL;
 
-    RSA_VALIDATE_RET( ctx != NULL );
-    RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
-                      mode == MBEDTLS_RSA_PUBLIC );
-    RSA_VALIDATE_RET( sig != NULL );
-    RSA_VALIDATE_RET( ( md_alg  == MBEDTLS_MD_NONE &&
-                        hashlen == 0 ) ||
-                      hash != NULL );
+    if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
     sig_len = ctx->len;
 
-    if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
-        return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
-
     /*
      * Prepare expected PKCS1 v1.5 encoding of hash.
      */
 
-    if( ( encoded          = mbedtls_calloc( 1, sig_len ) ) == NULL ||
-        ( encoded_expected = mbedtls_calloc( 1, sig_len ) ) == NULL )
-    {
+    if ((encoded          = mbedtls_calloc(1, sig_len)) == NULL ||
+        (encoded_expected = mbedtls_calloc(1, sig_len)) == NULL) {
         ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
         goto cleanup;
     }
 
-    if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, sig_len,
-                                             encoded_expected ) ) != 0 )
+    if ((ret = rsa_rsassa_pkcs1_v15_encode(md_alg, hashlen, hash, sig_len,
+                                           encoded_expected)) != 0) {
         goto cleanup;
+    }
 
     /*
      * Apply RSA primitive to get what should be PKCS1 encoded hash.
      */
 
-    ret = ( mode == MBEDTLS_RSA_PUBLIC )
-          ? mbedtls_rsa_public(  ctx, sig, encoded )
-          : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, encoded );
-    if( ret != 0 )
+    ret = mbedtls_rsa_public(ctx, sig, encoded);
+    if (ret != 0) {
         goto cleanup;
+    }
 
     /*
      * Compare
      */
 
-    if( ( ret = FTMN_CALLEE_DONE_MEMCMP(mbedtls_ct_memcmp, encoded,
-                                        encoded_expected, sig_len ) ) != 0 )
-    {
+    if ((ret = FTMN_CALLEE_DONE_MEMCMP(mbedtls_ct_memcmp, encoded,
+                                       encoded_expected, sig_len )) != 0) {
         ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;
         goto cleanup;
     }
 
 cleanup:
 
-    if( encoded != NULL )
-    {
-        mbedtls_platform_zeroize( encoded, sig_len );
-        mbedtls_free( encoded );
+    if (encoded != NULL) {
+        mbedtls_platform_zeroize(encoded, sig_len);
+        mbedtls_free(encoded);
     }
 
-    if( encoded_expected != NULL )
-    {
-        mbedtls_platform_zeroize( encoded_expected, sig_len );
-        mbedtls_free( encoded_expected );
+    if (encoded_expected != NULL) {
+        mbedtls_platform_zeroize(encoded_expected, sig_len);
+        mbedtls_free(encoded_expected);
     }
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_PKCS1_V15 */
 
 /*
  * Do an RSA operation and check the message digest
  */
-int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx,
-                      int (*f_rng)(void *, unsigned char *, size_t),
-                      void *p_rng,
-                      int mode,
-                      mbedtls_md_type_t md_alg,
-                      unsigned int hashlen,
-                      const unsigned char *hash,
-                      const unsigned char *sig )
+int mbedtls_rsa_pkcs1_verify(mbedtls_rsa_context *ctx,
+                             mbedtls_md_type_t md_alg,
+                             unsigned int hashlen,
+                             const unsigned char *hash,
+                             const unsigned char *sig)
 {
-    RSA_VALIDATE_RET( ctx != NULL );
-    RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
-                      mode == MBEDTLS_RSA_PUBLIC );
-    RSA_VALIDATE_RET( sig != NULL );
-    RSA_VALIDATE_RET( ( md_alg  == MBEDTLS_MD_NONE &&
-                        hashlen == 0 ) ||
-                      hash != NULL );
+    if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
-    switch( ctx->padding )
-    {
+    switch (ctx->padding) {
 #if defined(MBEDTLS_PKCS1_V15)
         case MBEDTLS_RSA_PKCS_V15:
-            return mbedtls_rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg,
-                                                hashlen, hash, sig );
+            return mbedtls_rsa_rsassa_pkcs1_v15_verify(ctx, md_alg,
+                                                       hashlen, hash, sig);
 #endif
 
 #if defined(MBEDTLS_PKCS1_V21)
         case MBEDTLS_RSA_PKCS_V21:
-            return mbedtls_rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg,
-                                          hashlen, hash, sig );
+            return mbedtls_rsa_rsassa_pss_verify(ctx, md_alg,
+                                                 hashlen, hash, sig);
 #endif
 
         default:
-            return( MBEDTLS_ERR_RSA_INVALID_PADDING );
+            return MBEDTLS_ERR_RSA_INVALID_PADDING;
     }
 }
 
 /*
  * Copy the components of an RSA key
  */
-int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src )
+int mbedtls_rsa_copy(mbedtls_rsa_context *dst, const mbedtls_rsa_context *src)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    RSA_VALIDATE_RET( dst != NULL );
-    RSA_VALIDATE_RET( src != NULL );
 
     dst->len = src->len;
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->E, &src->E ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->N, &src->N));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->E, &src->E));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->D, &src->D));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->P, &src->P));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->Q, &src->Q));
 
 #if !defined(MBEDTLS_RSA_NO_CRT)
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->DP, &src->DP));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->DQ, &src->DQ));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->QP, &src->QP));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->RP, &src->RP));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->RQ, &src->RQ));
 #endif
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->RN, &src->RN));
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->Vi, &src->Vi));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->Vf, &src->Vf));
 
     dst->padding = src->padding;
     dst->hash_id = src->hash_id;
 
 cleanup:
-    if( ret != 0 )
-        mbedtls_rsa_free( dst );
+    if (ret != 0) {
+        mbedtls_rsa_free(dst);
+    }
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Free the components of an RSA key
  */
-void mbedtls_rsa_free( mbedtls_rsa_context *ctx )
+void mbedtls_rsa_free(mbedtls_rsa_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_mpi_free( &ctx->Vi );
-    mbedtls_mpi_free( &ctx->Vf );
-    mbedtls_mpi_free( &ctx->RN );
-    mbedtls_mpi_free( &ctx->D  );
-    mbedtls_mpi_free( &ctx->Q  );
-    mbedtls_mpi_free( &ctx->P  );
-    mbedtls_mpi_free( &ctx->E  );
-    mbedtls_mpi_free( &ctx->N  );
+    mbedtls_mpi_free(&ctx->Vi);
+    mbedtls_mpi_free(&ctx->Vf);
+    mbedtls_mpi_free(&ctx->RN);
+    mbedtls_mpi_free(&ctx->D);
+    mbedtls_mpi_free(&ctx->Q);
+    mbedtls_mpi_free(&ctx->P);
+    mbedtls_mpi_free(&ctx->E);
+    mbedtls_mpi_free(&ctx->N);
 
 #if !defined(MBEDTLS_RSA_NO_CRT)
-    mbedtls_mpi_free( &ctx->RQ );
-    mbedtls_mpi_free( &ctx->RP );
-    mbedtls_mpi_free( &ctx->QP );
-    mbedtls_mpi_free( &ctx->DQ );
-    mbedtls_mpi_free( &ctx->DP );
+    mbedtls_mpi_free(&ctx->RQ);
+    mbedtls_mpi_free(&ctx->RP);
+    mbedtls_mpi_free(&ctx->QP);
+    mbedtls_mpi_free(&ctx->DQ);
+    mbedtls_mpi_free(&ctx->DP);
 #endif /* MBEDTLS_RSA_NO_CRT */
 
 #if defined(MBEDTLS_THREADING_C)
     /* Free the mutex, but only if it hasn't been freed already. */
-    if( ctx->ver != 0 )
-    {
-        mbedtls_mutex_free( &ctx->mutex );
+    if (ctx->ver != 0) {
+        mbedtls_mutex_free(&ctx->mutex);
         ctx->ver = 0;
     }
 #endif
@@ -2391,7 +2367,7 @@
 
 #if defined(MBEDTLS_SELF_TEST)
 
-#include "mbedtls/sha1.h"
+#include "mbedtls/md.h"
 
 /*
  * Example RSA-1024 keypair, for test purposes
@@ -2433,31 +2409,34 @@
                 "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
 
 #if defined(MBEDTLS_PKCS1_V15)
-static int myrand( void *rng_state, unsigned char *output, size_t len )
+static int myrand(void *rng_state, unsigned char *output, size_t len)
 {
 #if !defined(__OpenBSD__) && !defined(__NetBSD__)
     size_t i;
 
-    if( rng_state != NULL )
+    if (rng_state != NULL) {
         rng_state  = NULL;
+    }
 
-    for( i = 0; i < len; ++i )
+    for (i = 0; i < len; ++i) {
         output[i] = rand();
+    }
 #else
-    if( rng_state != NULL )
+    if (rng_state != NULL) {
         rng_state = NULL;
+    }
 
-    arc4random_buf( output, len );
+    arc4random_buf(output, len);
 #endif /* !OpenBSD && !NetBSD */
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_PKCS1_V15 */
 
 /*
  * Checkup routine
  */
-int mbedtls_rsa_self_test( int verbose )
+int mbedtls_rsa_self_test(int verbose)
 {
     int ret = 0;
 #if defined(MBEDTLS_PKCS1_V15)
@@ -2472,128 +2451,136 @@
 
     mbedtls_mpi K;
 
-    mbedtls_mpi_init( &K );
-    mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 );
+    mbedtls_mpi_init(&K);
+    mbedtls_rsa_init(&rsa);
 
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_N  ) );
-    MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, &K, NULL, NULL, NULL, NULL ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_P  ) );
-    MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, &K, NULL, NULL, NULL ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_Q  ) );
-    MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, &K, NULL, NULL ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_D  ) );
-    MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, &K, NULL ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_E  ) );
-    MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, NULL, &K ) );
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_N));
+    MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, &K, NULL, NULL, NULL, NULL));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_P));
+    MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, &K, NULL, NULL, NULL));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_Q));
+    MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, NULL, &K, NULL, NULL));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_D));
+    MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, NULL, NULL, &K, NULL));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_E));
+    MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, NULL, NULL, NULL, &K));
 
-    MBEDTLS_MPI_CHK( mbedtls_rsa_complete( &rsa ) );
+    MBEDTLS_MPI_CHK(mbedtls_rsa_complete(&rsa));
 
-    if( verbose != 0 )
-        mbedtls_printf( "  RSA key validation: " );
+    if (verbose != 0) {
+        mbedtls_printf("  RSA key validation: ");
+    }
 
-    if( mbedtls_rsa_check_pubkey(  &rsa ) != 0 ||
-        mbedtls_rsa_check_privkey( &rsa ) != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
+    if (mbedtls_rsa_check_pubkey(&rsa) != 0 ||
+        mbedtls_rsa_check_privkey(&rsa) != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("failed\n");
+        }
 
         ret = 1;
         goto cleanup;
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n  PKCS#1 encryption : " );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n  PKCS#1 encryption : ");
+    }
 
-    memcpy( rsa_plaintext, RSA_PT, PT_LEN );
+    memcpy(rsa_plaintext, RSA_PT, PT_LEN);
 
-    if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC,
-                                   PT_LEN, rsa_plaintext,
-                                   rsa_ciphertext ) != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
+    if (mbedtls_rsa_pkcs1_encrypt(&rsa, myrand, NULL,
+                                  PT_LEN, rsa_plaintext,
+                                  rsa_ciphertext) != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("failed\n");
+        }
 
         ret = 1;
         goto cleanup;
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n  PKCS#1 decryption : " );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n  PKCS#1 decryption : ");
+    }
 
-    if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE,
-                                   &len, rsa_ciphertext, rsa_decrypted,
-                                   sizeof(rsa_decrypted) ) != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
+    if (mbedtls_rsa_pkcs1_decrypt(&rsa, myrand, NULL,
+                                  &len, rsa_ciphertext, rsa_decrypted,
+                                  sizeof(rsa_decrypted)) != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("failed\n");
+        }
 
         ret = 1;
         goto cleanup;
     }
 
-    if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
+    if (memcmp(rsa_decrypted, rsa_plaintext, len) != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("failed\n");
+        }
 
         ret = 1;
         goto cleanup;
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
 
 #if defined(MBEDTLS_SHA1_C)
-    if( verbose != 0 )
-        mbedtls_printf( "  PKCS#1 data sign  : " );
-
-    if( mbedtls_sha1_ret( rsa_plaintext, PT_LEN, sha1sum ) != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
-
-        return( 1 );
+    if (verbose != 0) {
+        mbedtls_printf("  PKCS#1 data sign  : ");
     }
 
-    if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL,
-                                MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0,
-                                sha1sum, rsa_ciphertext ) != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
+    if (mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1),
+                   rsa_plaintext, PT_LEN, sha1sum) != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("failed\n");
+        }
+
+        return 1;
+    }
+
+    if (mbedtls_rsa_pkcs1_sign(&rsa, myrand, NULL,
+                               MBEDTLS_MD_SHA1, 20,
+                               sha1sum, rsa_ciphertext) != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("failed\n");
+        }
 
         ret = 1;
         goto cleanup;
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n  PKCS#1 sig. verify: " );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n  PKCS#1 sig. verify: ");
+    }
 
-    if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL,
-                                  MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0,
-                                  sha1sum, rsa_ciphertext ) != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
+    if (mbedtls_rsa_pkcs1_verify(&rsa, MBEDTLS_MD_SHA1, 20,
+                                 sha1sum, rsa_ciphertext) != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("failed\n");
+        }
 
         ret = 1;
         goto cleanup;
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
 #endif /* MBEDTLS_SHA1_C */
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
 cleanup:
-    mbedtls_mpi_free( &K );
-    mbedtls_rsa_free( &rsa );
+    mbedtls_mpi_free(&K);
+    mbedtls_rsa_free(&rsa);
 #else /* MBEDTLS_PKCS1_V15 */
     ((void) verbose);
 #endif /* MBEDTLS_PKCS1_V15 */
-    return( ret );
+    return ret;
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.c b/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.c
new file mode 100644
index 0000000..3451469
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.c
@@ -0,0 +1,459 @@
+/*
+ *  Helper functions for the RSA module
+ *
+ *  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.
+ *
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_RSA_C)
+
+#include "mbedtls/rsa.h"
+#include "mbedtls/bignum.h"
+#include "rsa_alt_helpers.h"
+
+/*
+ * Compute RSA prime factors from public and private exponents
+ *
+ * Summary of algorithm:
+ * Setting F := lcm(P-1,Q-1), the idea is as follows:
+ *
+ * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2)
+ *     is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the
+ *     square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four
+ *     possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1)
+ *     or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime
+ *     factors of N.
+ *
+ * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same
+ *     construction still applies since (-)^K is the identity on the set of
+ *     roots of 1 in Z/NZ.
+ *
+ * The public and private key primitives (-)^E and (-)^D are mutually inverse
+ * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e.
+ * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L.
+ * Splitting L = 2^t * K with K odd, we have
+ *
+ *   DE - 1 = FL = (F/2) * (2^(t+1)) * K,
+ *
+ * so (F / 2) * K is among the numbers
+ *
+ *   (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord
+ *
+ * where ord is the order of 2 in (DE - 1).
+ * We can therefore iterate through these numbers apply the construction
+ * of (a) and (b) above to attempt to factor N.
+ *
+ */
+int mbedtls_rsa_deduce_primes(mbedtls_mpi const *N,
+                              mbedtls_mpi const *E, mbedtls_mpi const *D,
+                              mbedtls_mpi *P, mbedtls_mpi *Q)
+{
+    int ret = 0;
+
+    uint16_t attempt;  /* Number of current attempt  */
+    uint16_t iter;     /* Number of squares computed in the current attempt */
+
+    uint16_t order;    /* Order of 2 in DE - 1 */
+
+    mbedtls_mpi T;  /* Holds largest odd divisor of DE - 1     */
+    mbedtls_mpi K;  /* Temporary holding the current candidate */
+
+    const unsigned char primes[] = { 2,
+                                     3,    5,    7,   11,   13,   17,   19,   23,
+                                     29,   31,   37,   41,   43,   47,   53,   59,
+                                     61,   67,   71,   73,   79,   83,   89,   97,
+                                     101,  103,  107,  109,  113,  127,  131,  137,
+                                     139,  149,  151,  157,  163,  167,  173,  179,
+                                     181,  191,  193,  197,  199,  211,  223,  227,
+                                     229,  233,  239,  241,  251 };
+
+    const size_t num_primes = sizeof(primes) / sizeof(*primes);
+
+    if (P == NULL || Q == NULL || P->p != NULL || Q->p != NULL) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+
+    if (mbedtls_mpi_cmp_int(N, 0) <= 0 ||
+        mbedtls_mpi_cmp_int(D, 1) <= 0 ||
+        mbedtls_mpi_cmp_mpi(D, N) >= 0 ||
+        mbedtls_mpi_cmp_int(E, 1) <= 0 ||
+        mbedtls_mpi_cmp_mpi(E, N) >= 0) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+
+    /*
+     * Initializations and temporary changes
+     */
+
+    mbedtls_mpi_init(&K);
+    mbedtls_mpi_init(&T);
+
+    /* T := DE - 1 */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, D,  E));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&T, &T, 1));
+
+    if ((order = (uint16_t) mbedtls_mpi_lsb(&T)) == 0) {
+        ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+        goto cleanup;
+    }
+
+    /* After this operation, T holds the largest odd divisor of DE - 1. */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&T, order));
+
+    /*
+     * Actual work
+     */
+
+    /* Skip trying 2 if N == 1 mod 8 */
+    attempt = 0;
+    if (N->p[0] % 8 == 1) {
+        attempt = 1;
+    }
+
+    for (; attempt < num_primes; ++attempt) {
+        mbedtls_mpi_lset(&K, primes[attempt]);
+
+        /* Check if gcd(K,N) = 1 */
+        MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N));
+        if (mbedtls_mpi_cmp_int(P, 1) != 0) {
+            continue;
+        }
+
+        /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ...
+         * and check whether they have nontrivial GCD with N. */
+        MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &K, &T, N,
+                                            Q /* temporarily use Q for storing Montgomery
+                                               * multiplication helper values */));
+
+        for (iter = 1; iter <= order; ++iter) {
+            /* If we reach 1 prematurely, there's no point
+             * in continuing to square K */
+            if (mbedtls_mpi_cmp_int(&K, 1) == 0) {
+                break;
+            }
+
+            MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&K, &K, 1));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N));
+
+            if (mbedtls_mpi_cmp_int(P, 1) ==  1 &&
+                mbedtls_mpi_cmp_mpi(P, N) == -1) {
+                /*
+                 * Have found a nontrivial divisor P of N.
+                 * Set Q := N / P.
+                 */
+
+                MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(Q, NULL, N, P));
+                goto cleanup;
+            }
+
+            MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &K));
+            MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, N));
+        }
+
+        /*
+         * If we get here, then either we prematurely aborted the loop because
+         * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must
+         * be 1 if D,E,N were consistent.
+         * Check if that's the case and abort if not, to avoid very long,
+         * yet eventually failing, computations if N,D,E were not sane.
+         */
+        if (mbedtls_mpi_cmp_int(&K, 1) != 0) {
+            break;
+        }
+    }
+
+    ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+
+cleanup:
+
+    mbedtls_mpi_free(&K);
+    mbedtls_mpi_free(&T);
+    return ret;
+}
+
+/*
+ * Given P, Q and the public exponent E, deduce D.
+ * This is essentially a modular inversion.
+ */
+int mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const *P,
+                                        mbedtls_mpi const *Q,
+                                        mbedtls_mpi const *E,
+                                        mbedtls_mpi *D)
+{
+    int ret = 0;
+    mbedtls_mpi K, L;
+
+    if (D == NULL || mbedtls_mpi_cmp_int(D, 0) != 0) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+
+    if (mbedtls_mpi_cmp_int(P, 1) <= 0 ||
+        mbedtls_mpi_cmp_int(Q, 1) <= 0 ||
+        mbedtls_mpi_cmp_int(E, 0) == 0) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+
+    mbedtls_mpi_init(&K);
+    mbedtls_mpi_init(&L);
+
+    /* Temporarily put K := P-1 and L := Q-1 */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));
+
+    /* Temporarily put D := gcd(P-1, Q-1) */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(D, &K, &L));
+
+    /* K := LCM(P-1, Q-1) */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &L));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&K, NULL, &K, D));
+
+    /* Compute modular inverse of E in LCM(P-1, Q-1) */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(D, E, &K));
+
+cleanup:
+
+    mbedtls_mpi_free(&K);
+    mbedtls_mpi_free(&L);
+
+    return ret;
+}
+
+int mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,
+                           const mbedtls_mpi *D, mbedtls_mpi *DP,
+                           mbedtls_mpi *DQ, mbedtls_mpi *QP)
+{
+    int ret = 0;
+    mbedtls_mpi K;
+    mbedtls_mpi_init(&K);
+
+    /* DP = D mod P-1 */
+    if (DP != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DP, D, &K));
+    }
+
+    /* DQ = D mod Q-1 */
+    if (DQ != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DQ, D, &K));
+    }
+
+    /* QP = Q^{-1} mod P */
+    if (QP != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(QP, Q, P));
+    }
+
+cleanup:
+    mbedtls_mpi_free(&K);
+
+    return ret;
+}
+
+/*
+ * Check that core RSA parameters are sane.
+ */
+int mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P,
+                                const mbedtls_mpi *Q, const mbedtls_mpi *D,
+                                const mbedtls_mpi *E,
+                                int (*f_rng)(void *, unsigned char *, size_t),
+                                void *p_rng)
+{
+    int ret = 0;
+    mbedtls_mpi K, L;
+
+    mbedtls_mpi_init(&K);
+    mbedtls_mpi_init(&L);
+
+    /*
+     * Step 1: If PRNG provided, check that P and Q are prime
+     */
+
+#if defined(MBEDTLS_GENPRIME)
+    /*
+     * When generating keys, the strongest security we support aims for an error
+     * rate of at most 2^-100 and we are aiming for the same certainty here as
+     * well.
+     */
+    if (f_rng != NULL && P != NULL &&
+        (ret = mbedtls_mpi_is_prime_ext(P, 50, f_rng, p_rng)) != 0) {
+        ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
+        goto cleanup;
+    }
+
+    if (f_rng != NULL && Q != NULL &&
+        (ret = mbedtls_mpi_is_prime_ext(Q, 50, f_rng, p_rng)) != 0) {
+        ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
+        goto cleanup;
+    }
+#else
+    ((void) f_rng);
+    ((void) p_rng);
+#endif /* MBEDTLS_GENPRIME */
+
+    /*
+     * Step 2: Check that 1 < N = P * Q
+     */
+
+    if (P != NULL && Q != NULL && N != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, P, Q));
+        if (mbedtls_mpi_cmp_int(N, 1)  <= 0 ||
+            mbedtls_mpi_cmp_mpi(&K, N) != 0) {
+            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
+            goto cleanup;
+        }
+    }
+
+    /*
+     * Step 3: Check and 1 < D, E < N if present.
+     */
+
+    if (N != NULL && D != NULL && E != NULL) {
+        if (mbedtls_mpi_cmp_int(D, 1) <= 0 ||
+            mbedtls_mpi_cmp_int(E, 1) <= 0 ||
+            mbedtls_mpi_cmp_mpi(D, N) >= 0 ||
+            mbedtls_mpi_cmp_mpi(E, N) >= 0) {
+            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
+            goto cleanup;
+        }
+    }
+
+    /*
+     * Step 4: Check that D, E are inverse modulo P-1 and Q-1
+     */
+
+    if (P != NULL && Q != NULL && D != NULL && E != NULL) {
+        if (mbedtls_mpi_cmp_int(P, 1) <= 0 ||
+            mbedtls_mpi_cmp_int(Q, 1) <= 0) {
+            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
+            goto cleanup;
+        }
+
+        /* Compute DE-1 mod P-1 */
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, P, 1));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
+        if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
+            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
+            goto cleanup;
+        }
+
+        /* Compute DE-1 mod Q-1 */
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
+        if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
+            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
+            goto cleanup;
+        }
+    }
+
+cleanup:
+
+    mbedtls_mpi_free(&K);
+    mbedtls_mpi_free(&L);
+
+    /* Wrap MPI error codes by RSA check failure error code */
+    if (ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) {
+        ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
+    }
+
+    return ret;
+}
+
+/*
+ * Check that RSA CRT parameters are in accordance with core parameters.
+ */
+int mbedtls_rsa_validate_crt(const mbedtls_mpi *P,  const mbedtls_mpi *Q,
+                             const mbedtls_mpi *D,  const mbedtls_mpi *DP,
+                             const mbedtls_mpi *DQ, const mbedtls_mpi *QP)
+{
+    int ret = 0;
+
+    mbedtls_mpi K, L;
+    mbedtls_mpi_init(&K);
+    mbedtls_mpi_init(&L);
+
+    /* Check that DP - D == 0 mod P - 1 */
+    if (DP != NULL) {
+        if (P == NULL) {
+            ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+            goto cleanup;
+        }
+
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DP, D));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
+
+        if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
+            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
+            goto cleanup;
+        }
+    }
+
+    /* Check that DQ - D == 0 mod Q - 1 */
+    if (DQ != NULL) {
+        if (Q == NULL) {
+            ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+            goto cleanup;
+        }
+
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DQ, D));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
+
+        if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
+            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
+            goto cleanup;
+        }
+    }
+
+    /* Check that QP * Q - 1 == 0 mod P */
+    if (QP != NULL) {
+        if (P == NULL || Q == NULL) {
+            ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+            goto cleanup;
+        }
+
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, QP, Q));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, P));
+        if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
+            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
+            goto cleanup;
+        }
+    }
+
+cleanup:
+
+    /* Wrap MPI error codes by RSA check failure error code */
+    if (ret != 0 &&
+        ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED &&
+        ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) {
+        ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
+    }
+
+    mbedtls_mpi_free(&K);
+    mbedtls_mpi_free(&L);
+
+    return ret;
+}
+
+#endif /* MBEDTLS_RSA_C */
diff --git a/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.h b/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.h
new file mode 100644
index 0000000..3b22ba8
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.h
@@ -0,0 +1,220 @@
+/**
+ * \file rsa_alt_helpers.h
+ *
+ * \brief Context-independent RSA helper functions
+ *
+ *  This module declares some RSA-related helper functions useful when
+ *  implementing the RSA interface. These functions are provided in a separate
+ *  compilation unit in order to make it easy for designers of alternative RSA
+ *  implementations to use them in their own code, as it is conceived that the
+ *  functionality they provide will be necessary for most complete
+ *  implementations.
+ *
+ *  End-users of Mbed TLS who are not providing their own alternative RSA
+ *  implementations should not use these functions directly, and should instead
+ *  use only the functions declared in rsa.h.
+ *
+ *  The interface provided by this module will be maintained through LTS (Long
+ *  Term Support) branches of Mbed TLS, but may otherwise be subject to change,
+ *  and must be considered an internal interface of the library.
+ *
+ *  There are two classes of helper functions:
+ *
+ *  (1) Parameter-generating helpers. These are:
+ *      - mbedtls_rsa_deduce_primes
+ *      - mbedtls_rsa_deduce_private_exponent
+ *      - mbedtls_rsa_deduce_crt
+ *       Each of these functions takes a set of core RSA parameters and
+ *       generates some other, or CRT related parameters.
+ *
+ *  (2) Parameter-checking helpers. These are:
+ *      - mbedtls_rsa_validate_params
+ *      - mbedtls_rsa_validate_crt
+ *      They take a set of core or CRT related RSA parameters and check their
+ *      validity.
+ *
+ */
+/*
+ *  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_RSA_INTERNAL_H
+#define MBEDTLS_RSA_INTERNAL_H
+
+#include "mbedtls/build_info.h"
+
+#include "mbedtls/bignum.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * \brief          Compute RSA prime moduli P, Q from public modulus N=PQ
+ *                 and a pair of private and public key.
+ *
+ * \note           This is a 'static' helper function not operating on
+ *                 an RSA context. Alternative implementations need not
+ *                 overwrite it.
+ *
+ * \param N        RSA modulus N = PQ, with P, Q to be found
+ * \param E        RSA public exponent
+ * \param D        RSA private exponent
+ * \param P        Pointer to MPI holding first prime factor of N on success
+ * \param Q        Pointer to MPI holding second prime factor of N on success
+ *
+ * \return
+ *                 - 0 if successful. In this case, P and Q constitute a
+ *                   factorization of N.
+ *                 - A non-zero error code otherwise.
+ *
+ * \note           It is neither checked that P, Q are prime nor that
+ *                 D, E are modular inverses wrt. P-1 and Q-1. For that,
+ *                 use the helper function \c mbedtls_rsa_validate_params.
+ *
+ */
+int mbedtls_rsa_deduce_primes(mbedtls_mpi const *N, mbedtls_mpi const *E,
+                              mbedtls_mpi const *D,
+                              mbedtls_mpi *P, mbedtls_mpi *Q);
+
+/**
+ * \brief          Compute RSA private exponent from
+ *                 prime moduli and public key.
+ *
+ * \note           This is a 'static' helper function not operating on
+ *                 an RSA context. Alternative implementations need not
+ *                 overwrite it.
+ *
+ * \param P        First prime factor of RSA modulus
+ * \param Q        Second prime factor of RSA modulus
+ * \param E        RSA public exponent
+ * \param D        Pointer to MPI holding the private exponent on success.
+ *
+ * \return
+ *                 - 0 if successful. In this case, D is set to a simultaneous
+ *                   modular inverse of E modulo both P-1 and Q-1.
+ *                 - A non-zero error code otherwise.
+ *
+ * \note           This function does not check whether P and Q are primes.
+ *
+ */
+int mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const *P,
+                                        mbedtls_mpi const *Q,
+                                        mbedtls_mpi const *E,
+                                        mbedtls_mpi *D);
+
+
+/**
+ * \brief          Generate RSA-CRT parameters
+ *
+ * \note           This is a 'static' helper function not operating on
+ *                 an RSA context. Alternative implementations need not
+ *                 overwrite it.
+ *
+ * \param P        First prime factor of N
+ * \param Q        Second prime factor of N
+ * \param D        RSA private exponent
+ * \param DP       Output variable for D modulo P-1
+ * \param DQ       Output variable for D modulo Q-1
+ * \param QP       Output variable for the modular inverse of Q modulo P.
+ *
+ * \return         0 on success, non-zero error code otherwise.
+ *
+ * \note           This function does not check whether P, Q are
+ *                 prime and whether D is a valid private exponent.
+ *
+ */
+int mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,
+                           const mbedtls_mpi *D, mbedtls_mpi *DP,
+                           mbedtls_mpi *DQ, mbedtls_mpi *QP);
+
+
+/**
+ * \brief          Check validity of core RSA parameters
+ *
+ * \note           This is a 'static' helper function not operating on
+ *                 an RSA context. Alternative implementations need not
+ *                 overwrite it.
+ *
+ * \param N        RSA modulus N = PQ
+ * \param P        First prime factor of N
+ * \param Q        Second prime factor of N
+ * \param D        RSA private exponent
+ * \param E        RSA public exponent
+ * \param f_rng    PRNG to be used for primality check, or NULL
+ * \param p_rng    PRNG context for f_rng, or NULL
+ *
+ * \return
+ *                 - 0 if the following conditions are satisfied
+ *                   if all relevant parameters are provided:
+ *                    - P prime if f_rng != NULL (%)
+ *                    - Q prime if f_rng != NULL (%)
+ *                    - 1 < N = P * Q
+ *                    - 1 < D, E < N
+ *                    - D and E are modular inverses modulo P-1 and Q-1
+ *                   (%) This is only done if MBEDTLS_GENPRIME is defined.
+ *                 - A non-zero error code otherwise.
+ *
+ * \note           The function can be used with a restricted set of arguments
+ *                 to perform specific checks only. E.g., calling it with
+ *                 (-,P,-,-,-) and a PRNG amounts to a primality check for P.
+ */
+int mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P,
+                                const mbedtls_mpi *Q, const mbedtls_mpi *D,
+                                const mbedtls_mpi *E,
+                                int (*f_rng)(void *, unsigned char *, size_t),
+                                void *p_rng);
+
+/**
+ * \brief          Check validity of RSA CRT parameters
+ *
+ * \note           This is a 'static' helper function not operating on
+ *                 an RSA context. Alternative implementations need not
+ *                 overwrite it.
+ *
+ * \param P        First prime factor of RSA modulus
+ * \param Q        Second prime factor of RSA modulus
+ * \param D        RSA private exponent
+ * \param DP       MPI to check for D modulo P-1
+ * \param DQ       MPI to check for D modulo P-1
+ * \param QP       MPI to check for the modular inverse of Q modulo P.
+ *
+ * \return
+ *                 - 0 if the following conditions are satisfied:
+ *                    - D = DP mod P-1 if P, D, DP != NULL
+ *                    - Q = DQ mod P-1 if P, D, DQ != NULL
+ *                    - QP = Q^-1 mod P if P, Q, QP != NULL
+ *                 - \c MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if check failed,
+ *                   potentially including \c MBEDTLS_ERR_MPI_XXX if some
+ *                   MPI calculations failed.
+ *                 - \c MBEDTLS_ERR_RSA_BAD_INPUT_DATA if insufficient
+ *                   data was provided to check DP, DQ or QP.
+ *
+ * \note           The function can be used with a restricted set of arguments
+ *                 to perform specific checks only. E.g., calling it with the
+ *                 parameters (P, -, D, DP, -, -) will check DP = D mod P-1.
+ */
+int mbedtls_rsa_validate_crt(const mbedtls_mpi *P,  const mbedtls_mpi *Q,
+                             const mbedtls_mpi *D,  const mbedtls_mpi *DP,
+                             const mbedtls_mpi *DQ, const mbedtls_mpi *QP);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* rsa_alt_helpers.h */
diff --git a/lib/libmbedtls/mbedtls/library/rsa_internal.c b/lib/libmbedtls/mbedtls/library/rsa_internal.c
deleted file mode 100644
index d6ba97a..0000000
--- a/lib/libmbedtls/mbedtls/library/rsa_internal.c
+++ /dev/null
@@ -1,486 +0,0 @@
-/*
- *  Helper functions for the RSA module
- *
- *  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.
- *
- */
-
-#include "common.h"
-
-#if defined(MBEDTLS_RSA_C)
-
-#include "mbedtls/rsa.h"
-#include "mbedtls/bignum.h"
-#include "mbedtls/rsa_internal.h"
-
-/*
- * Compute RSA prime factors from public and private exponents
- *
- * Summary of algorithm:
- * Setting F := lcm(P-1,Q-1), the idea is as follows:
- *
- * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2)
- *     is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the
- *     square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four
- *     possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1)
- *     or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime
- *     factors of N.
- *
- * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same
- *     construction still applies since (-)^K is the identity on the set of
- *     roots of 1 in Z/NZ.
- *
- * The public and private key primitives (-)^E and (-)^D are mutually inverse
- * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e.
- * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L.
- * Splitting L = 2^t * K with K odd, we have
- *
- *   DE - 1 = FL = (F/2) * (2^(t+1)) * K,
- *
- * so (F / 2) * K is among the numbers
- *
- *   (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord
- *
- * where ord is the order of 2 in (DE - 1).
- * We can therefore iterate through these numbers apply the construction
- * of (a) and (b) above to attempt to factor N.
- *
- */
-int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N,
-                     mbedtls_mpi const *E, mbedtls_mpi const *D,
-                     mbedtls_mpi *P, mbedtls_mpi *Q )
-{
-    int ret = 0;
-
-    uint16_t attempt;  /* Number of current attempt  */
-    uint16_t iter;     /* Number of squares computed in the current attempt */
-
-    uint16_t order;    /* Order of 2 in DE - 1 */
-
-    mbedtls_mpi T;  /* Holds largest odd divisor of DE - 1     */
-    mbedtls_mpi K;  /* Temporary holding the current candidate */
-
-    const unsigned char primes[] = { 2,
-           3,    5,    7,   11,   13,   17,   19,   23,
-          29,   31,   37,   41,   43,   47,   53,   59,
-          61,   67,   71,   73,   79,   83,   89,   97,
-         101,  103,  107,  109,  113,  127,  131,  137,
-         139,  149,  151,  157,  163,  167,  173,  179,
-         181,  191,  193,  197,  199,  211,  223,  227,
-         229,  233,  239,  241,  251
-    };
-
-    const size_t num_primes = sizeof( primes ) / sizeof( *primes );
-
-    if( P == NULL || Q == NULL || P->p != NULL || Q->p != NULL )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-
-    if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 ||
-        mbedtls_mpi_cmp_int( D, 1 ) <= 0 ||
-        mbedtls_mpi_cmp_mpi( D, N ) >= 0 ||
-        mbedtls_mpi_cmp_int( E, 1 ) <= 0 ||
-        mbedtls_mpi_cmp_mpi( E, N ) >= 0 )
-    {
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-    }
-
-    /*
-     * Initializations and temporary changes
-     */
-
-    mbedtls_mpi_init( &K );
-    mbedtls_mpi_init( &T );
-
-    /* T := DE - 1 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, D,  E ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &T, &T, 1 ) );
-
-    if( ( order = (uint16_t) mbedtls_mpi_lsb( &T ) ) == 0 )
-    {
-        ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
-        goto cleanup;
-    }
-
-    /* After this operation, T holds the largest odd divisor of DE - 1. */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &T, order ) );
-
-    /*
-     * Actual work
-     */
-
-    /* Skip trying 2 if N == 1 mod 8 */
-    attempt = 0;
-    if( N->p[0] % 8 == 1 )
-        attempt = 1;
-
-    for( ; attempt < num_primes; ++attempt )
-    {
-        mbedtls_mpi_lset( &K, primes[attempt] );
-
-        /* Check if gcd(K,N) = 1 */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) );
-        if( mbedtls_mpi_cmp_int( P, 1 ) != 0 )
-            continue;
-
-        /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ...
-         * and check whether they have nontrivial GCD with N. */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &K, &K, &T, N,
-                             Q /* temporarily use Q for storing Montgomery
-                                * multiplication helper values */ ) );
-
-        for( iter = 1; iter <= order; ++iter )
-        {
-            /* If we reach 1 prematurely, there's no point
-             * in continuing to square K */
-            if( mbedtls_mpi_cmp_int( &K, 1 ) == 0 )
-                break;
-
-            MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &K, &K, 1 ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) );
-
-            if( mbedtls_mpi_cmp_int( P, 1 ) ==  1 &&
-                mbedtls_mpi_cmp_mpi( P, N ) == -1 )
-            {
-                /*
-                 * Have found a nontrivial divisor P of N.
-                 * Set Q := N / P.
-                 */
-
-                MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( Q, NULL, N, P ) );
-                goto cleanup;
-            }
-
-            MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &K ) );
-            MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, N ) );
-        }
-
-        /*
-         * If we get here, then either we prematurely aborted the loop because
-         * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must
-         * be 1 if D,E,N were consistent.
-         * Check if that's the case and abort if not, to avoid very long,
-         * yet eventually failing, computations if N,D,E were not sane.
-         */
-        if( mbedtls_mpi_cmp_int( &K, 1 ) != 0 )
-        {
-            break;
-        }
-    }
-
-    ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
-
-cleanup:
-
-    mbedtls_mpi_free( &K );
-    mbedtls_mpi_free( &T );
-    return( ret );
-}
-
-/*
- * Given P, Q and the public exponent E, deduce D.
- * This is essentially a modular inversion.
- */
-int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P,
-                                         mbedtls_mpi const *Q,
-                                         mbedtls_mpi const *E,
-                                         mbedtls_mpi *D )
-{
-    int ret = 0;
-    mbedtls_mpi K, L;
-
-    if( D == NULL || mbedtls_mpi_cmp_int( D, 0 ) != 0 )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-
-    if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 ||
-        mbedtls_mpi_cmp_int( Q, 1 ) <= 0 ||
-        mbedtls_mpi_cmp_int( E, 0 ) == 0 )
-    {
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-    }
-
-    mbedtls_mpi_init( &K );
-    mbedtls_mpi_init( &L );
-
-    /* Temporarily put K := P-1 and L := Q-1 */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) );
-
-    /* Temporarily put D := gcd(P-1, Q-1) */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( D, &K, &L ) );
-
-    /* K := LCM(P-1, Q-1) */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &L ) );
-    MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &K, NULL, &K, D ) );
-
-    /* Compute modular inverse of E in LCM(P-1, Q-1) */
-    MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( D, E, &K ) );
-
-cleanup:
-
-    mbedtls_mpi_free( &K );
-    mbedtls_mpi_free( &L );
-
-    return( ret );
-}
-
-/*
- * Check that RSA CRT parameters are in accordance with core parameters.
- */
-int mbedtls_rsa_validate_crt( const mbedtls_mpi *P,  const mbedtls_mpi *Q,
-                              const mbedtls_mpi *D,  const mbedtls_mpi *DP,
-                              const mbedtls_mpi *DQ, const mbedtls_mpi *QP )
-{
-    int ret = 0;
-
-    mbedtls_mpi K, L;
-    mbedtls_mpi_init( &K );
-    mbedtls_mpi_init( &L );
-
-    /* Check that DP - D == 0 mod P - 1 */
-    if( DP != NULL )
-    {
-        if( P == NULL )
-        {
-            ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
-            goto cleanup;
-        }
-
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DP, D ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) );
-
-        if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 )
-        {
-            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
-            goto cleanup;
-        }
-    }
-
-    /* Check that DQ - D == 0 mod Q - 1 */
-    if( DQ != NULL )
-    {
-        if( Q == NULL )
-        {
-            ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
-            goto cleanup;
-        }
-
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DQ, D ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) );
-
-        if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 )
-        {
-            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
-            goto cleanup;
-        }
-    }
-
-    /* Check that QP * Q - 1 == 0 mod P */
-    if( QP != NULL )
-    {
-        if( P == NULL || Q == NULL )
-        {
-            ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
-            goto cleanup;
-        }
-
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, QP, Q ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, P ) );
-        if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 )
-        {
-            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
-            goto cleanup;
-        }
-    }
-
-cleanup:
-
-    /* Wrap MPI error codes by RSA check failure error code */
-    if( ret != 0 &&
-        ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED &&
-        ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA )
-    {
-        ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
-    }
-
-    mbedtls_mpi_free( &K );
-    mbedtls_mpi_free( &L );
-
-    return( ret );
-}
-
-/*
- * Check that core RSA parameters are sane.
- */
-int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P,
-                                 const mbedtls_mpi *Q, const mbedtls_mpi *D,
-                                 const mbedtls_mpi *E,
-                                 int (*f_rng)(void *, unsigned char *, size_t),
-                                 void *p_rng )
-{
-    int ret = 0;
-    mbedtls_mpi K, L;
-
-    mbedtls_mpi_init( &K );
-    mbedtls_mpi_init( &L );
-
-    /*
-     * Step 1: If PRNG provided, check that P and Q are prime
-     */
-
-#if defined(MBEDTLS_GENPRIME)
-    /*
-     * When generating keys, the strongest security we support aims for an error
-     * rate of at most 2^-100 and we are aiming for the same certainty here as
-     * well.
-     */
-    if( f_rng != NULL && P != NULL &&
-        ( ret = mbedtls_mpi_is_prime_ext( P, 50, f_rng, p_rng ) ) != 0 )
-    {
-        ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
-        goto cleanup;
-    }
-
-    if( f_rng != NULL && Q != NULL &&
-        ( ret = mbedtls_mpi_is_prime_ext( Q, 50, f_rng, p_rng ) ) != 0 )
-    {
-        ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
-        goto cleanup;
-    }
-#else
-    ((void) f_rng);
-    ((void) p_rng);
-#endif /* MBEDTLS_GENPRIME */
-
-    /*
-     * Step 2: Check that 1 < N = P * Q
-     */
-
-    if( P != NULL && Q != NULL && N != NULL )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, P, Q ) );
-        if( mbedtls_mpi_cmp_int( N, 1 )  <= 0 ||
-            mbedtls_mpi_cmp_mpi( &K, N ) != 0 )
-        {
-            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
-            goto cleanup;
-        }
-    }
-
-    /*
-     * Step 3: Check and 1 < D, E < N if present.
-     */
-
-    if( N != NULL && D != NULL && E != NULL )
-    {
-        if ( mbedtls_mpi_cmp_int( D, 1 ) <= 0 ||
-             mbedtls_mpi_cmp_int( E, 1 ) <= 0 ||
-             mbedtls_mpi_cmp_mpi( D, N ) >= 0 ||
-             mbedtls_mpi_cmp_mpi( E, N ) >= 0 )
-        {
-            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
-            goto cleanup;
-        }
-    }
-
-    /*
-     * Step 4: Check that D, E are inverse modulo P-1 and Q-1
-     */
-
-    if( P != NULL && Q != NULL && D != NULL && E != NULL )
-    {
-        if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 ||
-            mbedtls_mpi_cmp_int( Q, 1 ) <= 0 )
-        {
-            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
-            goto cleanup;
-        }
-
-        /* Compute DE-1 mod P-1 */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, P, 1 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) );
-        if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 )
-        {
-            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
-            goto cleanup;
-        }
-
-        /* Compute DE-1 mod Q-1 */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) );
-        if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 )
-        {
-            ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
-            goto cleanup;
-        }
-    }
-
-cleanup:
-
-    mbedtls_mpi_free( &K );
-    mbedtls_mpi_free( &L );
-
-    /* Wrap MPI error codes by RSA check failure error code */
-    if( ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED )
-    {
-        ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
-    }
-
-    return( ret );
-}
-
-int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q,
-                            const mbedtls_mpi *D, mbedtls_mpi *DP,
-                            mbedtls_mpi *DQ, mbedtls_mpi *QP )
-{
-    int ret = 0;
-    mbedtls_mpi K;
-    mbedtls_mpi_init( &K );
-
-    /* DP = D mod P-1 */
-    if( DP != NULL )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1  ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DP, D, &K ) );
-    }
-
-    /* DQ = D mod Q-1 */
-    if( DQ != NULL )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1  ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DQ, D, &K ) );
-    }
-
-    /* QP = Q^{-1} mod P */
-    if( QP != NULL )
-    {
-        MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( QP, Q, P ) );
-    }
-
-cleanup:
-    mbedtls_mpi_free( &K );
-
-    return( ret );
-}
-
-#endif /* MBEDTLS_RSA_C */
diff --git a/lib/libmbedtls/mbedtls/library/sha1.c b/lib/libmbedtls/mbedtls/library/sha1.c
index 0a5edaf..4c9cbf5 100644
--- a/lib/libmbedtls/mbedtls/library/sha1.c
+++ b/lib/libmbedtls/mbedtls/library/sha1.c
@@ -32,53 +32,35 @@
 
 #include <string.h>
 
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
-
-#define SHA1_VALIDATE_RET(cond)                             \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA )
-
-#define SHA1_VALIDATE(cond)  MBEDTLS_INTERNAL_VALIDATE( cond )
 
 #if !defined(MBEDTLS_SHA1_ALT)
 
-void mbedtls_sha1_init( mbedtls_sha1_context *ctx )
+void mbedtls_sha1_init(mbedtls_sha1_context *ctx)
 {
-    SHA1_VALIDATE( ctx != NULL );
-
-    memset( ctx, 0, sizeof( mbedtls_sha1_context ) );
+    memset(ctx, 0, sizeof(mbedtls_sha1_context));
 }
 
-void mbedtls_sha1_free( mbedtls_sha1_context *ctx )
+void mbedtls_sha1_free(mbedtls_sha1_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha1_context ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha1_context));
 }
 
-void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
-                         const mbedtls_sha1_context *src )
+void mbedtls_sha1_clone(mbedtls_sha1_context *dst,
+                        const mbedtls_sha1_context *src)
 {
-    SHA1_VALIDATE( dst != NULL );
-    SHA1_VALIDATE( src != NULL );
-
     *dst = *src;
 }
 
 /*
  * SHA-1 context setup
  */
-int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx )
+int mbedtls_sha1_starts(mbedtls_sha1_context *ctx)
 {
-    SHA1_VALIDATE_RET( ctx != NULL );
-
     ctx->total[0] = 0;
     ctx->total[1] = 0;
 
@@ -88,62 +70,51 @@
     ctx->state[3] = 0x10325476;
     ctx->state[4] = 0xC3D2E1F0;
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_sha1_starts( mbedtls_sha1_context *ctx )
-{
-    mbedtls_sha1_starts_ret( ctx );
-}
-#endif
-
 #if !defined(MBEDTLS_SHA1_PROCESS_ALT)
-int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx,
-                                   const unsigned char data[64] )
+int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx,
+                                  const unsigned char data[64])
 {
-    struct
-    {
+    struct {
         uint32_t temp, W[16], A, B, C, D, E;
     } local;
 
-    SHA1_VALIDATE_RET( ctx != NULL );
-    SHA1_VALIDATE_RET( (const unsigned char *)data != NULL );
+    local.W[0] = MBEDTLS_GET_UINT32_BE(data,  0);
+    local.W[1] = MBEDTLS_GET_UINT32_BE(data,  4);
+    local.W[2] = MBEDTLS_GET_UINT32_BE(data,  8);
+    local.W[3] = MBEDTLS_GET_UINT32_BE(data, 12);
+    local.W[4] = MBEDTLS_GET_UINT32_BE(data, 16);
+    local.W[5] = MBEDTLS_GET_UINT32_BE(data, 20);
+    local.W[6] = MBEDTLS_GET_UINT32_BE(data, 24);
+    local.W[7] = MBEDTLS_GET_UINT32_BE(data, 28);
+    local.W[8] = MBEDTLS_GET_UINT32_BE(data, 32);
+    local.W[9] = MBEDTLS_GET_UINT32_BE(data, 36);
+    local.W[10] = MBEDTLS_GET_UINT32_BE(data, 40);
+    local.W[11] = MBEDTLS_GET_UINT32_BE(data, 44);
+    local.W[12] = MBEDTLS_GET_UINT32_BE(data, 48);
+    local.W[13] = MBEDTLS_GET_UINT32_BE(data, 52);
+    local.W[14] = MBEDTLS_GET_UINT32_BE(data, 56);
+    local.W[15] = MBEDTLS_GET_UINT32_BE(data, 60);
 
-    local.W[ 0] = MBEDTLS_GET_UINT32_BE( data,  0 );
-    local.W[ 1] = MBEDTLS_GET_UINT32_BE( data,  4 );
-    local.W[ 2] = MBEDTLS_GET_UINT32_BE( data,  8 );
-    local.W[ 3] = MBEDTLS_GET_UINT32_BE( data, 12 );
-    local.W[ 4] = MBEDTLS_GET_UINT32_BE( data, 16 );
-    local.W[ 5] = MBEDTLS_GET_UINT32_BE( data, 20 );
-    local.W[ 6] = MBEDTLS_GET_UINT32_BE( data, 24 );
-    local.W[ 7] = MBEDTLS_GET_UINT32_BE( data, 28 );
-    local.W[ 8] = MBEDTLS_GET_UINT32_BE( data, 32 );
-    local.W[ 9] = MBEDTLS_GET_UINT32_BE( data, 36 );
-    local.W[10] = MBEDTLS_GET_UINT32_BE( data, 40 );
-    local.W[11] = MBEDTLS_GET_UINT32_BE( data, 44 );
-    local.W[12] = MBEDTLS_GET_UINT32_BE( data, 48 );
-    local.W[13] = MBEDTLS_GET_UINT32_BE( data, 52 );
-    local.W[14] = MBEDTLS_GET_UINT32_BE( data, 56 );
-    local.W[15] = MBEDTLS_GET_UINT32_BE( data, 60 );
-
-#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
+#define S(x, n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
 
 #define R(t)                                                    \
     (                                                           \
-        local.temp = local.W[( (t) -  3 ) & 0x0F] ^             \
-                     local.W[( (t) -  8 ) & 0x0F] ^             \
-                     local.W[( (t) - 14 ) & 0x0F] ^             \
-                     local.W[  (t)        & 0x0F],              \
-        ( local.W[(t) & 0x0F] = S(local.temp,1) )               \
+        local.temp = local.W[((t) -  3) & 0x0F] ^             \
+                     local.W[((t) -  8) & 0x0F] ^             \
+                     local.W[((t) - 14) & 0x0F] ^             \
+                     local.W[(t)        & 0x0F],              \
+        (local.W[(t) & 0x0F] = S(local.temp, 1))               \
     )
 
-#define P(a,b,c,d,e,x)                                          \
+#define P(a, b, c, d, e, x)                                          \
     do                                                          \
     {                                                           \
-        (e) += S((a),5) + F((b),(c),(d)) + K + (x);             \
-        (b) = S((b),30);                                        \
-    } while( 0 )
+        (e) += S((a), 5) + F((b), (c), (d)) + K + (x);             \
+        (b) = S((b), 30);                                        \
+    } while (0)
 
     local.A = ctx->state[0];
     local.B = ctx->state[1];
@@ -151,110 +122,110 @@
     local.D = ctx->state[3];
     local.E = ctx->state[4];
 
-#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
 #define K 0x5A827999
 
-    P( local.A, local.B, local.C, local.D, local.E, local.W[0]  );
-    P( local.E, local.A, local.B, local.C, local.D, local.W[1]  );
-    P( local.D, local.E, local.A, local.B, local.C, local.W[2]  );
-    P( local.C, local.D, local.E, local.A, local.B, local.W[3]  );
-    P( local.B, local.C, local.D, local.E, local.A, local.W[4]  );
-    P( local.A, local.B, local.C, local.D, local.E, local.W[5]  );
-    P( local.E, local.A, local.B, local.C, local.D, local.W[6]  );
-    P( local.D, local.E, local.A, local.B, local.C, local.W[7]  );
-    P( local.C, local.D, local.E, local.A, local.B, local.W[8]  );
-    P( local.B, local.C, local.D, local.E, local.A, local.W[9]  );
-    P( local.A, local.B, local.C, local.D, local.E, local.W[10] );
-    P( local.E, local.A, local.B, local.C, local.D, local.W[11] );
-    P( local.D, local.E, local.A, local.B, local.C, local.W[12] );
-    P( local.C, local.D, local.E, local.A, local.B, local.W[13] );
-    P( local.B, local.C, local.D, local.E, local.A, local.W[14] );
-    P( local.A, local.B, local.C, local.D, local.E, local.W[15] );
-    P( local.E, local.A, local.B, local.C, local.D, R(16) );
-    P( local.D, local.E, local.A, local.B, local.C, R(17) );
-    P( local.C, local.D, local.E, local.A, local.B, R(18) );
-    P( local.B, local.C, local.D, local.E, local.A, R(19) );
+    P(local.A, local.B, local.C, local.D, local.E, local.W[0]);
+    P(local.E, local.A, local.B, local.C, local.D, local.W[1]);
+    P(local.D, local.E, local.A, local.B, local.C, local.W[2]);
+    P(local.C, local.D, local.E, local.A, local.B, local.W[3]);
+    P(local.B, local.C, local.D, local.E, local.A, local.W[4]);
+    P(local.A, local.B, local.C, local.D, local.E, local.W[5]);
+    P(local.E, local.A, local.B, local.C, local.D, local.W[6]);
+    P(local.D, local.E, local.A, local.B, local.C, local.W[7]);
+    P(local.C, local.D, local.E, local.A, local.B, local.W[8]);
+    P(local.B, local.C, local.D, local.E, local.A, local.W[9]);
+    P(local.A, local.B, local.C, local.D, local.E, local.W[10]);
+    P(local.E, local.A, local.B, local.C, local.D, local.W[11]);
+    P(local.D, local.E, local.A, local.B, local.C, local.W[12]);
+    P(local.C, local.D, local.E, local.A, local.B, local.W[13]);
+    P(local.B, local.C, local.D, local.E, local.A, local.W[14]);
+    P(local.A, local.B, local.C, local.D, local.E, local.W[15]);
+    P(local.E, local.A, local.B, local.C, local.D, R(16));
+    P(local.D, local.E, local.A, local.B, local.C, R(17));
+    P(local.C, local.D, local.E, local.A, local.B, R(18));
+    P(local.B, local.C, local.D, local.E, local.A, R(19));
 
 #undef K
 #undef F
 
-#define F(x,y,z) ((x) ^ (y) ^ (z))
+#define F(x, y, z) ((x) ^ (y) ^ (z))
 #define K 0x6ED9EBA1
 
-    P( local.A, local.B, local.C, local.D, local.E, R(20) );
-    P( local.E, local.A, local.B, local.C, local.D, R(21) );
-    P( local.D, local.E, local.A, local.B, local.C, R(22) );
-    P( local.C, local.D, local.E, local.A, local.B, R(23) );
-    P( local.B, local.C, local.D, local.E, local.A, R(24) );
-    P( local.A, local.B, local.C, local.D, local.E, R(25) );
-    P( local.E, local.A, local.B, local.C, local.D, R(26) );
-    P( local.D, local.E, local.A, local.B, local.C, R(27) );
-    P( local.C, local.D, local.E, local.A, local.B, R(28) );
-    P( local.B, local.C, local.D, local.E, local.A, R(29) );
-    P( local.A, local.B, local.C, local.D, local.E, R(30) );
-    P( local.E, local.A, local.B, local.C, local.D, R(31) );
-    P( local.D, local.E, local.A, local.B, local.C, R(32) );
-    P( local.C, local.D, local.E, local.A, local.B, R(33) );
-    P( local.B, local.C, local.D, local.E, local.A, R(34) );
-    P( local.A, local.B, local.C, local.D, local.E, R(35) );
-    P( local.E, local.A, local.B, local.C, local.D, R(36) );
-    P( local.D, local.E, local.A, local.B, local.C, R(37) );
-    P( local.C, local.D, local.E, local.A, local.B, R(38) );
-    P( local.B, local.C, local.D, local.E, local.A, R(39) );
+    P(local.A, local.B, local.C, local.D, local.E, R(20));
+    P(local.E, local.A, local.B, local.C, local.D, R(21));
+    P(local.D, local.E, local.A, local.B, local.C, R(22));
+    P(local.C, local.D, local.E, local.A, local.B, R(23));
+    P(local.B, local.C, local.D, local.E, local.A, R(24));
+    P(local.A, local.B, local.C, local.D, local.E, R(25));
+    P(local.E, local.A, local.B, local.C, local.D, R(26));
+    P(local.D, local.E, local.A, local.B, local.C, R(27));
+    P(local.C, local.D, local.E, local.A, local.B, R(28));
+    P(local.B, local.C, local.D, local.E, local.A, R(29));
+    P(local.A, local.B, local.C, local.D, local.E, R(30));
+    P(local.E, local.A, local.B, local.C, local.D, R(31));
+    P(local.D, local.E, local.A, local.B, local.C, R(32));
+    P(local.C, local.D, local.E, local.A, local.B, R(33));
+    P(local.B, local.C, local.D, local.E, local.A, R(34));
+    P(local.A, local.B, local.C, local.D, local.E, R(35));
+    P(local.E, local.A, local.B, local.C, local.D, R(36));
+    P(local.D, local.E, local.A, local.B, local.C, R(37));
+    P(local.C, local.D, local.E, local.A, local.B, R(38));
+    P(local.B, local.C, local.D, local.E, local.A, R(39));
 
 #undef K
 #undef F
 
-#define F(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
+#define F(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))
 #define K 0x8F1BBCDC
 
-    P( local.A, local.B, local.C, local.D, local.E, R(40) );
-    P( local.E, local.A, local.B, local.C, local.D, R(41) );
-    P( local.D, local.E, local.A, local.B, local.C, R(42) );
-    P( local.C, local.D, local.E, local.A, local.B, R(43) );
-    P( local.B, local.C, local.D, local.E, local.A, R(44) );
-    P( local.A, local.B, local.C, local.D, local.E, R(45) );
-    P( local.E, local.A, local.B, local.C, local.D, R(46) );
-    P( local.D, local.E, local.A, local.B, local.C, R(47) );
-    P( local.C, local.D, local.E, local.A, local.B, R(48) );
-    P( local.B, local.C, local.D, local.E, local.A, R(49) );
-    P( local.A, local.B, local.C, local.D, local.E, R(50) );
-    P( local.E, local.A, local.B, local.C, local.D, R(51) );
-    P( local.D, local.E, local.A, local.B, local.C, R(52) );
-    P( local.C, local.D, local.E, local.A, local.B, R(53) );
-    P( local.B, local.C, local.D, local.E, local.A, R(54) );
-    P( local.A, local.B, local.C, local.D, local.E, R(55) );
-    P( local.E, local.A, local.B, local.C, local.D, R(56) );
-    P( local.D, local.E, local.A, local.B, local.C, R(57) );
-    P( local.C, local.D, local.E, local.A, local.B, R(58) );
-    P( local.B, local.C, local.D, local.E, local.A, R(59) );
+    P(local.A, local.B, local.C, local.D, local.E, R(40));
+    P(local.E, local.A, local.B, local.C, local.D, R(41));
+    P(local.D, local.E, local.A, local.B, local.C, R(42));
+    P(local.C, local.D, local.E, local.A, local.B, R(43));
+    P(local.B, local.C, local.D, local.E, local.A, R(44));
+    P(local.A, local.B, local.C, local.D, local.E, R(45));
+    P(local.E, local.A, local.B, local.C, local.D, R(46));
+    P(local.D, local.E, local.A, local.B, local.C, R(47));
+    P(local.C, local.D, local.E, local.A, local.B, R(48));
+    P(local.B, local.C, local.D, local.E, local.A, R(49));
+    P(local.A, local.B, local.C, local.D, local.E, R(50));
+    P(local.E, local.A, local.B, local.C, local.D, R(51));
+    P(local.D, local.E, local.A, local.B, local.C, R(52));
+    P(local.C, local.D, local.E, local.A, local.B, R(53));
+    P(local.B, local.C, local.D, local.E, local.A, R(54));
+    P(local.A, local.B, local.C, local.D, local.E, R(55));
+    P(local.E, local.A, local.B, local.C, local.D, R(56));
+    P(local.D, local.E, local.A, local.B, local.C, R(57));
+    P(local.C, local.D, local.E, local.A, local.B, R(58));
+    P(local.B, local.C, local.D, local.E, local.A, R(59));
 
 #undef K
 #undef F
 
-#define F(x,y,z) ((x) ^ (y) ^ (z))
+#define F(x, y, z) ((x) ^ (y) ^ (z))
 #define K 0xCA62C1D6
 
-    P( local.A, local.B, local.C, local.D, local.E, R(60) );
-    P( local.E, local.A, local.B, local.C, local.D, R(61) );
-    P( local.D, local.E, local.A, local.B, local.C, R(62) );
-    P( local.C, local.D, local.E, local.A, local.B, R(63) );
-    P( local.B, local.C, local.D, local.E, local.A, R(64) );
-    P( local.A, local.B, local.C, local.D, local.E, R(65) );
-    P( local.E, local.A, local.B, local.C, local.D, R(66) );
-    P( local.D, local.E, local.A, local.B, local.C, R(67) );
-    P( local.C, local.D, local.E, local.A, local.B, R(68) );
-    P( local.B, local.C, local.D, local.E, local.A, R(69) );
-    P( local.A, local.B, local.C, local.D, local.E, R(70) );
-    P( local.E, local.A, local.B, local.C, local.D, R(71) );
-    P( local.D, local.E, local.A, local.B, local.C, R(72) );
-    P( local.C, local.D, local.E, local.A, local.B, R(73) );
-    P( local.B, local.C, local.D, local.E, local.A, R(74) );
-    P( local.A, local.B, local.C, local.D, local.E, R(75) );
-    P( local.E, local.A, local.B, local.C, local.D, R(76) );
-    P( local.D, local.E, local.A, local.B, local.C, R(77) );
-    P( local.C, local.D, local.E, local.A, local.B, R(78) );
-    P( local.B, local.C, local.D, local.E, local.A, R(79) );
+    P(local.A, local.B, local.C, local.D, local.E, R(60));
+    P(local.E, local.A, local.B, local.C, local.D, R(61));
+    P(local.D, local.E, local.A, local.B, local.C, R(62));
+    P(local.C, local.D, local.E, local.A, local.B, R(63));
+    P(local.B, local.C, local.D, local.E, local.A, R(64));
+    P(local.A, local.B, local.C, local.D, local.E, R(65));
+    P(local.E, local.A, local.B, local.C, local.D, R(66));
+    P(local.D, local.E, local.A, local.B, local.C, R(67));
+    P(local.C, local.D, local.E, local.A, local.B, R(68));
+    P(local.B, local.C, local.D, local.E, local.A, R(69));
+    P(local.A, local.B, local.C, local.D, local.E, R(70));
+    P(local.E, local.A, local.B, local.C, local.D, R(71));
+    P(local.D, local.E, local.A, local.B, local.C, R(72));
+    P(local.C, local.D, local.E, local.A, local.B, R(73));
+    P(local.B, local.C, local.D, local.E, local.A, R(74));
+    P(local.A, local.B, local.C, local.D, local.E, R(75));
+    P(local.E, local.A, local.B, local.C, local.D, R(76));
+    P(local.D, local.E, local.A, local.B, local.C, R(77));
+    P(local.C, local.D, local.E, local.A, local.B, R(78));
+    P(local.B, local.C, local.D, local.E, local.A, R(79));
 
 #undef K
 #undef F
@@ -266,36 +237,27 @@
     ctx->state[4] += local.E;
 
     /* Zeroise buffers and variables to clear sensitive data from memory. */
-    mbedtls_platform_zeroize( &local, sizeof( local ) );
+    mbedtls_platform_zeroize(&local, sizeof(local));
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_sha1_process( mbedtls_sha1_context *ctx,
-                           const unsigned char data[64] )
-{
-    mbedtls_internal_sha1_process( ctx, data );
-}
-#endif
 #endif /* !MBEDTLS_SHA1_PROCESS_ALT */
 
 /*
  * SHA-1 process buffer
  */
-int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx,
-                             const unsigned char *input,
-                             size_t ilen )
+int mbedtls_sha1_update(mbedtls_sha1_context *ctx,
+                        const unsigned char *input,
+                        size_t ilen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t fill;
     uint32_t left;
 
-    SHA1_VALIDATE_RET( ctx != NULL );
-    SHA1_VALIDATE_RET( ilen == 0 || input != NULL );
-
-    if( ilen == 0 )
-        return( 0 );
+    if (ilen == 0) {
+        return 0;
+    }
 
     left = ctx->total[0] & 0x3F;
     fill = 64 - left;
@@ -303,58 +265,48 @@
     ctx->total[0] += (uint32_t) ilen;
     ctx->total[0] &= 0xFFFFFFFF;
 
-    if( ctx->total[0] < (uint32_t) ilen )
+    if (ctx->total[0] < (uint32_t) ilen) {
         ctx->total[1]++;
+    }
 
-    if( left && ilen >= fill )
-    {
-        memcpy( (void *) (ctx->buffer + left), input, fill );
+    if (left && ilen >= fill) {
+        memcpy((void *) (ctx->buffer + left), input, fill);
 
-        if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 )
-            return( ret );
+        if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) {
+            return ret;
+        }
 
         input += fill;
         ilen  -= fill;
         left = 0;
     }
 
-    while( ilen >= 64 )
-    {
-        if( ( ret = mbedtls_internal_sha1_process( ctx, input ) ) != 0 )
-            return( ret );
+    while (ilen >= 64) {
+        if ((ret = mbedtls_internal_sha1_process(ctx, input)) != 0) {
+            return ret;
+        }
 
         input += 64;
         ilen  -= 64;
     }
 
-    if( ilen > 0 )
-        memcpy( (void *) (ctx->buffer + left), input, ilen );
+    if (ilen > 0) {
+        memcpy((void *) (ctx->buffer + left), input, ilen);
+    }
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_sha1_update( mbedtls_sha1_context *ctx,
-                          const unsigned char *input,
-                          size_t ilen )
-{
-    mbedtls_sha1_update_ret( ctx, input, ilen );
-}
-#endif
-
 /*
  * SHA-1 final digest
  */
-int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx,
-                             unsigned char output[20] )
+int mbedtls_sha1_finish(mbedtls_sha1_context *ctx,
+                        unsigned char output[20])
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     uint32_t used;
     uint32_t high, low;
 
-    SHA1_VALIDATE_RET( ctx != NULL );
-    SHA1_VALIDATE_RET( (unsigned char *)output != NULL );
-
     /*
      * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
      */
@@ -362,96 +314,78 @@
 
     ctx->buffer[used++] = 0x80;
 
-    if( used <= 56 )
-    {
+    if (used <= 56) {
         /* Enough room for padding + length in current block */
-        memset( ctx->buffer + used, 0, 56 - used );
-    }
-    else
-    {
+        memset(ctx->buffer + used, 0, 56 - used);
+    } else {
         /* We'll need an extra block */
-        memset( ctx->buffer + used, 0, 64 - used );
+        memset(ctx->buffer + used, 0, 64 - used);
 
-        if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 )
-            return( ret );
+        if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) {
+            return ret;
+        }
 
-        memset( ctx->buffer, 0, 56 );
+        memset(ctx->buffer, 0, 56);
     }
 
     /*
      * Add message length
      */
-    high = ( ctx->total[0] >> 29 )
-         | ( ctx->total[1] <<  3 );
-    low  = ( ctx->total[0] <<  3 );
+    high = (ctx->total[0] >> 29)
+           | (ctx->total[1] <<  3);
+    low  = (ctx->total[0] <<  3);
 
-    MBEDTLS_PUT_UINT32_BE( high, ctx->buffer, 56 );
-    MBEDTLS_PUT_UINT32_BE( low,  ctx->buffer, 60 );
+    MBEDTLS_PUT_UINT32_BE(high, ctx->buffer, 56);
+    MBEDTLS_PUT_UINT32_BE(low,  ctx->buffer, 60);
 
-    if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) {
+        return ret;
+    }
 
     /*
      * Output final state
      */
-    MBEDTLS_PUT_UINT32_BE( ctx->state[0], output,  0 );
-    MBEDTLS_PUT_UINT32_BE( ctx->state[1], output,  4 );
-    MBEDTLS_PUT_UINT32_BE( ctx->state[2], output,  8 );
-    MBEDTLS_PUT_UINT32_BE( ctx->state[3], output, 12 );
-    MBEDTLS_PUT_UINT32_BE( ctx->state[4], output, 16 );
+    MBEDTLS_PUT_UINT32_BE(ctx->state[0], output,  0);
+    MBEDTLS_PUT_UINT32_BE(ctx->state[1], output,  4);
+    MBEDTLS_PUT_UINT32_BE(ctx->state[2], output,  8);
+    MBEDTLS_PUT_UINT32_BE(ctx->state[3], output, 12);
+    MBEDTLS_PUT_UINT32_BE(ctx->state[4], output, 16);
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_sha1_finish( mbedtls_sha1_context *ctx,
-                          unsigned char output[20] )
-{
-    mbedtls_sha1_finish_ret( ctx, output );
-}
-#endif
-
 #endif /* !MBEDTLS_SHA1_ALT */
 
 /*
  * output = SHA-1( input buffer )
  */
-int mbedtls_sha1_ret( const unsigned char *input,
-                      size_t ilen,
-                      unsigned char output[20] )
+int mbedtls_sha1(const unsigned char *input,
+                 size_t ilen,
+                 unsigned char output[20])
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_sha1_context ctx;
 
-    SHA1_VALIDATE_RET( ilen == 0 || input != NULL );
-    SHA1_VALIDATE_RET( (unsigned char *)output != NULL );
+    mbedtls_sha1_init(&ctx);
 
-    mbedtls_sha1_init( &ctx );
-
-    if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 )
+    if ((ret = mbedtls_sha1_starts(&ctx)) != 0) {
         goto exit;
+    }
 
-    if( ( ret = mbedtls_sha1_update_ret( &ctx, input, ilen ) ) != 0 )
+    if ((ret = mbedtls_sha1_update(&ctx, input, ilen)) != 0) {
         goto exit;
+    }
 
-    if( ( ret = mbedtls_sha1_finish_ret( &ctx, output ) ) != 0 )
+    if ((ret = mbedtls_sha1_finish(&ctx, output)) != 0) {
         goto exit;
+    }
 
 exit:
-    mbedtls_sha1_free( &ctx );
+    mbedtls_sha1_free(&ctx);
 
-    return( ret );
+    return ret;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_sha1( const unsigned char *input,
-                   size_t ilen,
-                   unsigned char output[20] )
-{
-    mbedtls_sha1_ret( input, ilen, output );
-}
-#endif
-
 #if defined(MBEDTLS_SELF_TEST)
 /*
  * FIPS-180-1 test vectors
@@ -481,71 +415,73 @@
 /*
  * Checkup routine
  */
-int mbedtls_sha1_self_test( int verbose )
+int mbedtls_sha1_self_test(int verbose)
 {
     int i, j, buflen, ret = 0;
     unsigned char buf[1024];
     unsigned char sha1sum[20];
     mbedtls_sha1_context ctx;
 
-    mbedtls_sha1_init( &ctx );
+    mbedtls_sha1_init(&ctx);
 
     /*
      * SHA-1
      */
-    for( i = 0; i < 3; i++ )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "  SHA-1 test #%d: ", i + 1 );
+    for (i = 0; i < 3; i++) {
+        if (verbose != 0) {
+            mbedtls_printf("  SHA-1 test #%d: ", i + 1);
+        }
 
-        if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 )
+        if ((ret = mbedtls_sha1_starts(&ctx)) != 0) {
             goto fail;
+        }
 
-        if( i == 2 )
-        {
-            memset( buf, 'a', buflen = 1000 );
+        if (i == 2) {
+            memset(buf, 'a', buflen = 1000);
 
-            for( j = 0; j < 1000; j++ )
-            {
-                ret = mbedtls_sha1_update_ret( &ctx, buf, buflen );
-                if( ret != 0 )
+            for (j = 0; j < 1000; j++) {
+                ret = mbedtls_sha1_update(&ctx, buf, buflen);
+                if (ret != 0) {
                     goto fail;
+                }
+            }
+        } else {
+            ret = mbedtls_sha1_update(&ctx, sha1_test_buf[i],
+                                      sha1_test_buflen[i]);
+            if (ret != 0) {
+                goto fail;
             }
         }
-        else
-        {
-            ret = mbedtls_sha1_update_ret( &ctx, sha1_test_buf[i],
-                                           sha1_test_buflen[i] );
-            if( ret != 0 )
-                goto fail;
+
+        if ((ret = mbedtls_sha1_finish(&ctx, sha1sum)) != 0) {
+            goto fail;
         }
 
-        if( ( ret = mbedtls_sha1_finish_ret( &ctx, sha1sum ) ) != 0 )
-            goto fail;
-
-        if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 )
-        {
+        if (memcmp(sha1sum, sha1_test_sum[i], 20) != 0) {
             ret = 1;
             goto fail;
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
     goto exit;
 
 fail:
-    if( verbose != 0 )
-        mbedtls_printf( "failed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("failed\n");
+    }
 
 exit:
-    mbedtls_sha1_free( &ctx );
+    mbedtls_sha1_free(&ctx);
 
-    return( ret );
+    return ret;
 }
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/lib/libmbedtls/mbedtls/library/sha256.c b/lib/libmbedtls/mbedtls/library/sha256.c
index db675ef..08822f4 100644
--- a/lib/libmbedtls/mbedtls/library/sha256.c
+++ b/lib/libmbedtls/mbedtls/library/sha256.c
@@ -22,9 +22,31 @@
  *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
  */
 
+#if defined(__aarch64__) && !defined(__ARM_FEATURE_CRYPTO) && \
+    defined(__clang__) && __clang_major__ >= 4
+/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged.
+ *
+ * The intrinsic declaration are guarded by predefined ACLE macros in clang:
+ * these are normally only enabled by the -march option on the command line.
+ * By defining the macros ourselves we gain access to those declarations without
+ * requiring -march on the command line.
+ *
+ * `arm_neon.h` could be included by any header file, so we put these defines
+ * at the top of this file, before any includes.
+ */
+#define __ARM_FEATURE_CRYPTO 1
+/* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions
+ *
+ * `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it
+ * for older compilers.
+ */
+#define __ARM_FEATURE_SHA2   1
+#define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG
+#endif
+
 #include "common.h"
 
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA224_C)
 
 #include "mbedtls/sha256.h"
 #include "mbedtls/platform_util.h"
@@ -32,62 +54,181 @@
 
 #include <string.h>
 
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#define mbedtls_printf printf
-#define mbedtls_calloc    calloc
-#define mbedtls_free       free
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
 
-#define SHA256_VALIDATE_RET(cond)                           \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA )
-#define SHA256_VALIDATE(cond)  MBEDTLS_INTERNAL_VALIDATE( cond )
+#if defined(__aarch64__)
+#  if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \
+    defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
+/* *INDENT-OFF* */
+#    if !defined(__ARM_FEATURE_CRYPTO) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG)
+#      if defined(__clang__)
+#        if __clang_major__ < 4
+#          error "A more recent Clang is required for MBEDTLS_SHA256_USE_A64_CRYPTO_*"
+#        endif
+#        pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function)
+#        define MBEDTLS_POP_TARGET_PRAGMA
+#      elif defined(__GNUC__)
+         /* FIXME: GCC 5 claims to support Armv8 Crypto Extensions, but some
+          *        intrinsics are missing. Missing intrinsics could be worked around.
+          */
+#        if __GNUC__ < 6
+#          error "A more recent GCC is required for MBEDTLS_SHA256_USE_A64_CRYPTO_*"
+#        else
+#          pragma GCC push_options
+#          pragma GCC target ("arch=armv8-a+crypto")
+#          define MBEDTLS_POP_TARGET_PRAGMA
+#        endif
+#      else
+#        error "Only GCC and Clang supported for MBEDTLS_SHA256_USE_A64_CRYPTO_*"
+#      endif
+#    endif
+/* *INDENT-ON* */
+#    include <arm_neon.h>
+#  endif
+#  if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
+#    if defined(__unix__)
+#      if defined(__linux__)
+/* Our preferred method of detection is getauxval() */
+#        include <sys/auxv.h>
+#      endif
+/* Use SIGILL on Unix, and fall back to it on Linux */
+#      include <signal.h>
+#    endif
+#  endif
+#elif defined(_M_ARM64)
+#  if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \
+    defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
+#    include <arm64_neon.h>
+#  endif
+#else
+#  undef MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY
+#  undef MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
+#endif
+
+#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
+/*
+ * Capability detection code comes early, so we can disable
+ * MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT if no detection mechanism found
+ */
+#if defined(HWCAP_SHA2)
+static int mbedtls_a64_crypto_sha256_determine_support(void)
+{
+    return (getauxval(AT_HWCAP) & HWCAP_SHA2) ? 1 : 0;
+}
+#elif defined(__APPLE__)
+static int mbedtls_a64_crypto_sha256_determine_support(void)
+{
+    return 1;
+}
+#elif defined(_M_ARM64)
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+#include <processthreadsapi.h>
+
+static int mbedtls_a64_crypto_sha256_determine_support(void)
+{
+    return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ?
+           1 : 0;
+}
+#elif defined(__unix__) && defined(SIG_SETMASK)
+/* Detection with SIGILL, setjmp() and longjmp() */
+#include <signal.h>
+#include <setjmp.h>
+
+static jmp_buf return_from_sigill;
+
+/*
+ * A64 SHA256 support detection via SIGILL
+ */
+static void sigill_handler(int signal)
+{
+    (void) signal;
+    longjmp(return_from_sigill, 1);
+}
+
+static int mbedtls_a64_crypto_sha256_determine_support(void)
+{
+    struct sigaction old_action, new_action;
+
+    sigset_t old_mask;
+    if (sigprocmask(0, NULL, &old_mask)) {
+        return 0;
+    }
+
+    sigemptyset(&new_action.sa_mask);
+    new_action.sa_flags = 0;
+    new_action.sa_handler = sigill_handler;
+
+    sigaction(SIGILL, &new_action, &old_action);
+
+    static int ret = 0;
+
+    if (setjmp(return_from_sigill) == 0) {         /* First return only */
+        /* If this traps, we will return a second time from setjmp() with 1 */
+        asm ("sha256h q0, q0, v0.4s" : : : "v0");
+        ret = 1;
+    }
+
+    sigaction(SIGILL, &old_action, NULL);
+    sigprocmask(SIG_SETMASK, &old_mask, NULL);
+
+    return ret;
+}
+#else
+#warning "No mechanism to detect A64_CRYPTO found, using C code only"
+#undef MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
+#endif  /* HWCAP_SHA2, __APPLE__, __unix__ && SIG_SETMASK */
+
+#endif  /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT */
 
 #if !defined(MBEDTLS_SHA256_ALT)
 
-void mbedtls_sha256_init( mbedtls_sha256_context *ctx )
-{
-    SHA256_VALIDATE( ctx != NULL );
+#define SHA256_BLOCK_SIZE 64
 
-    memset( ctx, 0, sizeof( mbedtls_sha256_context ) );
+void mbedtls_sha256_init(mbedtls_sha256_context *ctx)
+{
+    memset(ctx, 0, sizeof(mbedtls_sha256_context));
 }
 
-void mbedtls_sha256_free( mbedtls_sha256_context *ctx )
+void mbedtls_sha256_free(mbedtls_sha256_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha256_context ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha256_context));
 }
 
-void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
-                           const mbedtls_sha256_context *src )
+void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
+                          const mbedtls_sha256_context *src)
 {
-    SHA256_VALIDATE( dst != NULL );
-    SHA256_VALIDATE( src != NULL );
-
     *dst = *src;
 }
 
 /*
  * SHA-256 context setup
  */
-int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 )
+int mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224)
 {
-    SHA256_VALIDATE_RET( ctx != NULL );
-    SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 );
+#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)
+    if (is224 != 0 && is224 != 1) {
+        return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
+    }
+#elif defined(MBEDTLS_SHA256_C)
+    if (is224 != 0) {
+        return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
+    }
+#else /* defined MBEDTLS_SHA224_C only */
+    if (is224 == 0) {
+        return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
+    }
+#endif
 
     ctx->total[0] = 0;
     ctx->total[1] = 0;
 
-    if( is224 == 0 )
-    {
-        /* SHA-256 */
+    if (is224 == 0) {
+#if defined(MBEDTLS_SHA256_C)
         ctx->state[0] = 0x6A09E667;
         ctx->state[1] = 0xBB67AE85;
         ctx->state[2] = 0x3C6EF372;
@@ -96,10 +237,9 @@
         ctx->state[5] = 0x9B05688C;
         ctx->state[6] = 0x1F83D9AB;
         ctx->state[7] = 0x5BE0CD19;
-    }
-    else
-    {
-        /* SHA-224 */
+#endif
+    } else {
+#if defined(MBEDTLS_SHA224_C)
         ctx->state[0] = 0xC1059ED8;
         ctx->state[1] = 0x367CD507;
         ctx->state[2] = 0x3070DD17;
@@ -108,21 +248,16 @@
         ctx->state[5] = 0x68581511;
         ctx->state[6] = 0x64F98FA7;
         ctx->state[7] = 0xBEFA4FA4;
+#endif
     }
 
+#if defined(MBEDTLS_SHA224_C)
     ctx->is224 = is224;
-
-    return( 0 );
-}
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_sha256_starts( mbedtls_sha256_context *ctx,
-                            int is224 )
-{
-    mbedtls_sha256_starts_ret( ctx, is224 );
-}
 #endif
 
+    return 0;
+}
+
 #if !defined(MBEDTLS_SHA256_PROCESS_ALT)
 static const uint32_t K[] =
 {
@@ -144,17 +279,157 @@
     0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
 };
 
-#define  SHR(x,n) (((x) & 0xFFFFFFFF) >> (n))
-#define ROTR(x,n) (SHR(x,n) | ((x) << (32 - (n))))
+#endif
 
-#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^  SHR(x, 3))
-#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^  SHR(x,10))
+#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \
+    defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
 
-#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
-#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
+#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
+#  define mbedtls_internal_sha256_process_many_a64_crypto mbedtls_internal_sha256_process_many
+#  define mbedtls_internal_sha256_process_a64_crypto      mbedtls_internal_sha256_process
+#endif
 
-#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
-#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
+static size_t mbedtls_internal_sha256_process_many_a64_crypto(
+    mbedtls_sha256_context *ctx, const uint8_t *msg, size_t len)
+{
+    uint32x4_t abcd = vld1q_u32(&ctx->state[0]);
+    uint32x4_t efgh = vld1q_u32(&ctx->state[4]);
+
+    size_t processed = 0;
+
+    for (;
+         len >= SHA256_BLOCK_SIZE;
+         processed += SHA256_BLOCK_SIZE,
+         msg += SHA256_BLOCK_SIZE,
+         len -= SHA256_BLOCK_SIZE) {
+        uint32x4_t tmp, abcd_prev;
+
+        uint32x4_t abcd_orig = abcd;
+        uint32x4_t efgh_orig = efgh;
+
+        uint32x4_t sched0 = (uint32x4_t) vld1q_u8(msg + 16 * 0);
+        uint32x4_t sched1 = (uint32x4_t) vld1q_u8(msg + 16 * 1);
+        uint32x4_t sched2 = (uint32x4_t) vld1q_u8(msg + 16 * 2);
+        uint32x4_t sched3 = (uint32x4_t) vld1q_u8(msg + 16 * 3);
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__  /* Will be true if not defined */
+                                               /* Untested on BE */
+        sched0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched0)));
+        sched1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched1)));
+        sched2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched2)));
+        sched3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched3)));
+#endif
+
+        /* Rounds 0 to 3 */
+        tmp = vaddq_u32(sched0, vld1q_u32(&K[0]));
+        abcd_prev = abcd;
+        abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
+        efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
+
+        /* Rounds 4 to 7 */
+        tmp = vaddq_u32(sched1, vld1q_u32(&K[4]));
+        abcd_prev = abcd;
+        abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
+        efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
+
+        /* Rounds 8 to 11 */
+        tmp = vaddq_u32(sched2, vld1q_u32(&K[8]));
+        abcd_prev = abcd;
+        abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
+        efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
+
+        /* Rounds 12 to 15 */
+        tmp = vaddq_u32(sched3, vld1q_u32(&K[12]));
+        abcd_prev = abcd;
+        abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
+        efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
+
+        for (int t = 16; t < 64; t += 16) {
+            /* Rounds t to t + 3 */
+            sched0 = vsha256su1q_u32(vsha256su0q_u32(sched0, sched1), sched2, sched3);
+            tmp = vaddq_u32(sched0, vld1q_u32(&K[t]));
+            abcd_prev = abcd;
+            abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
+            efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
+
+            /* Rounds t + 4 to t + 7 */
+            sched1 = vsha256su1q_u32(vsha256su0q_u32(sched1, sched2), sched3, sched0);
+            tmp = vaddq_u32(sched1, vld1q_u32(&K[t + 4]));
+            abcd_prev = abcd;
+            abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
+            efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
+
+            /* Rounds t + 8 to t + 11 */
+            sched2 = vsha256su1q_u32(vsha256su0q_u32(sched2, sched3), sched0, sched1);
+            tmp = vaddq_u32(sched2, vld1q_u32(&K[t + 8]));
+            abcd_prev = abcd;
+            abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
+            efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
+
+            /* Rounds t + 12 to t + 15 */
+            sched3 = vsha256su1q_u32(vsha256su0q_u32(sched3, sched0), sched1, sched2);
+            tmp = vaddq_u32(sched3, vld1q_u32(&K[t + 12]));
+            abcd_prev = abcd;
+            abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
+            efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
+        }
+
+        abcd = vaddq_u32(abcd, abcd_orig);
+        efgh = vaddq_u32(efgh, efgh_orig);
+    }
+
+    vst1q_u32(&ctx->state[0], abcd);
+    vst1q_u32(&ctx->state[4], efgh);
+
+    return processed;
+}
+
+#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
+/*
+ * This function is for internal use only if we are building both C and A64
+ * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process()
+ */
+static
+#endif
+int mbedtls_internal_sha256_process_a64_crypto(mbedtls_sha256_context *ctx,
+                                               const unsigned char data[SHA256_BLOCK_SIZE])
+{
+    return (mbedtls_internal_sha256_process_many_a64_crypto(ctx, data,
+                                                            SHA256_BLOCK_SIZE) ==
+            SHA256_BLOCK_SIZE) ? 0 : -1;
+}
+
+#if defined(MBEDTLS_POP_TARGET_PRAGMA)
+#if defined(__clang__)
+#pragma clang attribute pop
+#elif defined(__GNUC__)
+#pragma GCC pop_options
+#endif
+#undef MBEDTLS_POP_TARGET_PRAGMA
+#endif
+
+#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */
+
+#if !defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
+#define mbedtls_internal_sha256_process_many_c mbedtls_internal_sha256_process_many
+#define mbedtls_internal_sha256_process_c      mbedtls_internal_sha256_process
+#endif
+
+
+#if !defined(MBEDTLS_SHA256_PROCESS_ALT) && \
+    !defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
+
+#define  SHR(x, n) (((x) & 0xFFFFFFFF) >> (n))
+#define ROTR(x, n) (SHR(x, n) | ((x) << (32 - (n))))
+
+#define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^  SHR(x, 3))
+#define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^  SHR(x, 10))
+
+#define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+
+#define F0(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))
+#define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
 
 #define R(t)                                                        \
     (                                                               \
@@ -162,41 +437,45 @@
                      S0(local.W[(t) - 15]) + local.W[(t) - 16]      \
     )
 
-#define P(a,b,c,d,e,f,g,h,x,K)                                      \
+#define P(a, b, c, d, e, f, g, h, x, K)                                      \
     do                                                              \
     {                                                               \
-        local.temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x);    \
-        local.temp2 = S2(a) + F0((a),(b),(c));                      \
+        local.temp1 = (h) + S3(e) + F1((e), (f), (g)) + (K) + (x);    \
+        local.temp2 = S2(a) + F0((a), (b), (c));                      \
         (d) += local.temp1; (h) = local.temp1 + local.temp2;        \
-    } while( 0 )
+    } while (0)
 
-int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx,
-                                const unsigned char data[64] )
+#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
+/*
+ * This function is for internal use only if we are building both C and A64
+ * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process()
+ */
+static
+#endif
+int mbedtls_internal_sha256_process_c(mbedtls_sha256_context *ctx,
+                                      const unsigned char data[SHA256_BLOCK_SIZE])
 {
-    struct
-    {
+    struct {
         uint32_t temp1, temp2, W[64];
         uint32_t A[8];
     } local;
 
     unsigned int i;
 
-    SHA256_VALIDATE_RET( ctx != NULL );
-    SHA256_VALIDATE_RET( (const unsigned char *)data != NULL );
-
-    for( i = 0; i < 8; i++ )
+    for (i = 0; i < 8; i++) {
         local.A[i] = ctx->state[i];
+    }
 
 #if defined(MBEDTLS_SHA256_SMALLER)
-    for( i = 0; i < 64; i++ )
-    {
-        if( i < 16 )
-            local.W[i] = MBEDTLS_GET_UINT32_BE( data, 4 * i );
-        else
-            R( i );
+    for (i = 0; i < 64; i++) {
+        if (i < 16) {
+            local.W[i] = MBEDTLS_GET_UINT32_BE(data, 4 * i);
+        } else {
+            R(i);
+        }
 
-        P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
-           local.A[5], local.A[6], local.A[7], local.W[i], K[i] );
+        P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
+          local.A[5], local.A[6], local.A[7], local.W[i], K[i]);
 
         local.temp1 = local.A[7]; local.A[7] = local.A[6];
         local.A[6] = local.A[5]; local.A[5] = local.A[4];
@@ -205,143 +484,189 @@
         local.A[0] = local.temp1;
     }
 #else /* MBEDTLS_SHA256_SMALLER */
-    for( i = 0; i < 16; i++ )
-        local.W[i] = MBEDTLS_GET_UINT32_BE( data, 4 * i );
-
-    for( i = 0; i < 16; i += 8 )
-    {
-        P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
-           local.A[5], local.A[6], local.A[7], local.W[i+0], K[i+0] );
-        P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],
-           local.A[4], local.A[5], local.A[6], local.W[i+1], K[i+1] );
-        P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],
-           local.A[3], local.A[4], local.A[5], local.W[i+2], K[i+2] );
-        P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],
-           local.A[2], local.A[3], local.A[4], local.W[i+3], K[i+3] );
-        P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],
-           local.A[1], local.A[2], local.A[3], local.W[i+4], K[i+4] );
-        P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],
-           local.A[0], local.A[1], local.A[2], local.W[i+5], K[i+5] );
-        P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],
-           local.A[7], local.A[0], local.A[1], local.W[i+6], K[i+6] );
-        P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],
-           local.A[6], local.A[7], local.A[0], local.W[i+7], K[i+7] );
+    for (i = 0; i < 16; i++) {
+        local.W[i] = MBEDTLS_GET_UINT32_BE(data, 4 * i);
     }
 
-    for( i = 16; i < 64; i += 8 )
-    {
-        P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
-           local.A[5], local.A[6], local.A[7], R(i+0), K[i+0] );
-        P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],
-           local.A[4], local.A[5], local.A[6], R(i+1), K[i+1] );
-        P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],
-           local.A[3], local.A[4], local.A[5], R(i+2), K[i+2] );
-        P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],
-           local.A[2], local.A[3], local.A[4], R(i+3), K[i+3] );
-        P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],
-           local.A[1], local.A[2], local.A[3], R(i+4), K[i+4] );
-        P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],
-           local.A[0], local.A[1], local.A[2], R(i+5), K[i+5] );
-        P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],
-           local.A[7], local.A[0], local.A[1], R(i+6), K[i+6] );
-        P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],
-           local.A[6], local.A[7], local.A[0], R(i+7), K[i+7] );
+    for (i = 0; i < 16; i += 8) {
+        P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
+          local.A[5], local.A[6], local.A[7], local.W[i+0], K[i+0]);
+        P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],
+          local.A[4], local.A[5], local.A[6], local.W[i+1], K[i+1]);
+        P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],
+          local.A[3], local.A[4], local.A[5], local.W[i+2], K[i+2]);
+        P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],
+          local.A[2], local.A[3], local.A[4], local.W[i+3], K[i+3]);
+        P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],
+          local.A[1], local.A[2], local.A[3], local.W[i+4], K[i+4]);
+        P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],
+          local.A[0], local.A[1], local.A[2], local.W[i+5], K[i+5]);
+        P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],
+          local.A[7], local.A[0], local.A[1], local.W[i+6], K[i+6]);
+        P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],
+          local.A[6], local.A[7], local.A[0], local.W[i+7], K[i+7]);
+    }
+
+    for (i = 16; i < 64; i += 8) {
+        P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
+          local.A[5], local.A[6], local.A[7], R(i+0), K[i+0]);
+        P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],
+          local.A[4], local.A[5], local.A[6], R(i+1), K[i+1]);
+        P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],
+          local.A[3], local.A[4], local.A[5], R(i+2), K[i+2]);
+        P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],
+          local.A[2], local.A[3], local.A[4], R(i+3), K[i+3]);
+        P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],
+          local.A[1], local.A[2], local.A[3], R(i+4), K[i+4]);
+        P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],
+          local.A[0], local.A[1], local.A[2], R(i+5), K[i+5]);
+        P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],
+          local.A[7], local.A[0], local.A[1], R(i+6), K[i+6]);
+        P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],
+          local.A[6], local.A[7], local.A[0], R(i+7), K[i+7]);
     }
 #endif /* MBEDTLS_SHA256_SMALLER */
 
-    for( i = 0; i < 8; i++ )
+    for (i = 0; i < 8; i++) {
         ctx->state[i] += local.A[i];
+    }
 
     /* Zeroise buffers and variables to clear sensitive data from memory. */
-    mbedtls_platform_zeroize( &local, sizeof( local ) );
+    mbedtls_platform_zeroize(&local, sizeof(local));
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_sha256_process( mbedtls_sha256_context *ctx,
-                             const unsigned char data[64] )
+#endif /* !MBEDTLS_SHA256_PROCESS_ALT && !MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */
+
+
+#if !defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
+
+static size_t mbedtls_internal_sha256_process_many_c(
+    mbedtls_sha256_context *ctx, const uint8_t *data, size_t len)
 {
-    mbedtls_internal_sha256_process( ctx, data );
+    size_t processed = 0;
+
+    while (len >= SHA256_BLOCK_SIZE) {
+        if (mbedtls_internal_sha256_process_c(ctx, data) != 0) {
+            return 0;
+        }
+
+        data += SHA256_BLOCK_SIZE;
+        len  -= SHA256_BLOCK_SIZE;
+
+        processed += SHA256_BLOCK_SIZE;
+    }
+
+    return processed;
 }
-#endif
-#endif /* !MBEDTLS_SHA256_PROCESS_ALT */
+
+#endif /* !MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */
+
+
+#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
+
+static int mbedtls_a64_crypto_sha256_has_support(void)
+{
+    static int done = 0;
+    static int supported = 0;
+
+    if (!done) {
+        supported = mbedtls_a64_crypto_sha256_determine_support();
+        done = 1;
+    }
+
+    return supported;
+}
+
+static size_t mbedtls_internal_sha256_process_many(mbedtls_sha256_context *ctx,
+                                                   const uint8_t *msg, size_t len)
+{
+    if (mbedtls_a64_crypto_sha256_has_support()) {
+        return mbedtls_internal_sha256_process_many_a64_crypto(ctx, msg, len);
+    } else {
+        return mbedtls_internal_sha256_process_many_c(ctx, msg, len);
+    }
+}
+
+int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx,
+                                    const unsigned char data[SHA256_BLOCK_SIZE])
+{
+    if (mbedtls_a64_crypto_sha256_has_support()) {
+        return mbedtls_internal_sha256_process_a64_crypto(ctx, data);
+    } else {
+        return mbedtls_internal_sha256_process_c(ctx, data);
+    }
+}
+
+#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT */
+
 
 /*
  * SHA-256 process buffer
  */
-int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx,
-                               const unsigned char *input,
-                               size_t ilen )
+int mbedtls_sha256_update(mbedtls_sha256_context *ctx,
+                          const unsigned char *input,
+                          size_t ilen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t fill;
     uint32_t left;
 
-    SHA256_VALIDATE_RET( ctx != NULL );
-    SHA256_VALIDATE_RET( ilen == 0 || input != NULL );
-
-    if( ilen == 0 )
-        return( 0 );
+    if (ilen == 0) {
+        return 0;
+    }
 
     left = ctx->total[0] & 0x3F;
-    fill = 64 - left;
+    fill = SHA256_BLOCK_SIZE - left;
 
     ctx->total[0] += (uint32_t) ilen;
     ctx->total[0] &= 0xFFFFFFFF;
 
-    if( ctx->total[0] < (uint32_t) ilen )
+    if (ctx->total[0] < (uint32_t) ilen) {
         ctx->total[1]++;
+    }
 
-    if( left && ilen >= fill )
-    {
-        memcpy( (void *) (ctx->buffer + left), input, fill );
+    if (left && ilen >= fill) {
+        memcpy((void *) (ctx->buffer + left), input, fill);
 
-        if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 )
-            return( ret );
+        if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) {
+            return ret;
+        }
 
         input += fill;
         ilen  -= fill;
         left = 0;
     }
 
-    while( ilen >= 64 )
-    {
-        if( ( ret = mbedtls_internal_sha256_process( ctx, input ) ) != 0 )
-            return( ret );
+    while (ilen >= SHA256_BLOCK_SIZE) {
+        size_t processed =
+            mbedtls_internal_sha256_process_many(ctx, input, ilen);
+        if (processed < SHA256_BLOCK_SIZE) {
+            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
+        }
 
-        input += 64;
-        ilen  -= 64;
+        input += processed;
+        ilen  -= processed;
     }
 
-    if( ilen > 0 )
-        memcpy( (void *) (ctx->buffer + left), input, ilen );
+    if (ilen > 0) {
+        memcpy((void *) (ctx->buffer + left), input, ilen);
+    }
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_sha256_update( mbedtls_sha256_context *ctx,
-                            const unsigned char *input,
-                            size_t ilen )
-{
-    mbedtls_sha256_update_ret( ctx, input, ilen );
-}
-#endif
-
 /*
  * SHA-256 final digest
  */
-int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx,
-                               unsigned char output[32] )
+int mbedtls_sha256_finish(mbedtls_sha256_context *ctx,
+                          unsigned char *output)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     uint32_t used;
     uint32_t high, low;
 
-    SHA256_VALIDATE_RET( ctx != NULL );
-    SHA256_VALIDATE_RET( (unsigned char *)output != NULL );
-
     /*
      * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
      */
@@ -349,125 +674,127 @@
 
     ctx->buffer[used++] = 0x80;
 
-    if( used <= 56 )
-    {
+    if (used <= 56) {
         /* Enough room for padding + length in current block */
-        memset( ctx->buffer + used, 0, 56 - used );
-    }
-    else
-    {
+        memset(ctx->buffer + used, 0, 56 - used);
+    } else {
         /* We'll need an extra block */
-        memset( ctx->buffer + used, 0, 64 - used );
+        memset(ctx->buffer + used, 0, SHA256_BLOCK_SIZE - used);
 
-        if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 )
-            return( ret );
+        if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) {
+            return ret;
+        }
 
-        memset( ctx->buffer, 0, 56 );
+        memset(ctx->buffer, 0, 56);
     }
 
     /*
      * Add message length
      */
-    high = ( ctx->total[0] >> 29 )
-         | ( ctx->total[1] <<  3 );
-    low  = ( ctx->total[0] <<  3 );
+    high = (ctx->total[0] >> 29)
+           | (ctx->total[1] <<  3);
+    low  = (ctx->total[0] <<  3);
 
-    MBEDTLS_PUT_UINT32_BE( high, ctx->buffer, 56 );
-    MBEDTLS_PUT_UINT32_BE( low,  ctx->buffer, 60 );
+    MBEDTLS_PUT_UINT32_BE(high, ctx->buffer, 56);
+    MBEDTLS_PUT_UINT32_BE(low,  ctx->buffer, 60);
 
-    if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) {
+        return ret;
+    }
 
     /*
      * Output final state
      */
-    MBEDTLS_PUT_UINT32_BE( ctx->state[0], output,  0 );
-    MBEDTLS_PUT_UINT32_BE( ctx->state[1], output,  4 );
-    MBEDTLS_PUT_UINT32_BE( ctx->state[2], output,  8 );
-    MBEDTLS_PUT_UINT32_BE( ctx->state[3], output, 12 );
-    MBEDTLS_PUT_UINT32_BE( ctx->state[4], output, 16 );
-    MBEDTLS_PUT_UINT32_BE( ctx->state[5], output, 20 );
-    MBEDTLS_PUT_UINT32_BE( ctx->state[6], output, 24 );
+    MBEDTLS_PUT_UINT32_BE(ctx->state[0], output,  0);
+    MBEDTLS_PUT_UINT32_BE(ctx->state[1], output,  4);
+    MBEDTLS_PUT_UINT32_BE(ctx->state[2], output,  8);
+    MBEDTLS_PUT_UINT32_BE(ctx->state[3], output, 12);
+    MBEDTLS_PUT_UINT32_BE(ctx->state[4], output, 16);
+    MBEDTLS_PUT_UINT32_BE(ctx->state[5], output, 20);
+    MBEDTLS_PUT_UINT32_BE(ctx->state[6], output, 24);
 
-    if( ctx->is224 == 0 )
-        MBEDTLS_PUT_UINT32_BE( ctx->state[7], output, 28 );
-
-    return( 0 );
-}
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_sha256_finish( mbedtls_sha256_context *ctx,
-                            unsigned char output[32] )
-{
-    mbedtls_sha256_finish_ret( ctx, output );
-}
+    int truncated = 0;
+#if defined(MBEDTLS_SHA224_C)
+    truncated = ctx->is224;
 #endif
+    if (!truncated) {
+        MBEDTLS_PUT_UINT32_BE(ctx->state[7], output, 28);
+    }
+
+    return 0;
+}
 
 #endif /* !MBEDTLS_SHA256_ALT */
 
 /*
  * output = SHA-256( input buffer )
  */
-int mbedtls_sha256_ret( const unsigned char *input,
-                        size_t ilen,
-                        unsigned char output[32],
-                        int is224 )
+int mbedtls_sha256(const unsigned char *input,
+                   size_t ilen,
+                   unsigned char *output,
+                   int is224)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_sha256_context ctx;
 
-    SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 );
-    SHA256_VALIDATE_RET( ilen == 0 || input != NULL );
-    SHA256_VALIDATE_RET( (unsigned char *)output != NULL );
+#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)
+    if (is224 != 0 && is224 != 1) {
+        return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
+    }
+#elif defined(MBEDTLS_SHA256_C)
+    if (is224 != 0) {
+        return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
+    }
+#else /* defined MBEDTLS_SHA224_C only */
+    if (is224 == 0) {
+        return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
+    }
+#endif
 
-    mbedtls_sha256_init( &ctx );
+    mbedtls_sha256_init(&ctx);
 
-    if( ( ret = mbedtls_sha256_starts_ret( &ctx, is224 ) ) != 0 )
+    if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) {
         goto exit;
+    }
 
-    if( ( ret = mbedtls_sha256_update_ret( &ctx, input, ilen ) ) != 0 )
+    if ((ret = mbedtls_sha256_update(&ctx, input, ilen)) != 0) {
         goto exit;
+    }
 
-    if( ( ret = mbedtls_sha256_finish_ret( &ctx, output ) ) != 0 )
+    if ((ret = mbedtls_sha256_finish(&ctx, output)) != 0) {
         goto exit;
+    }
 
 exit:
-    mbedtls_sha256_free( &ctx );
+    mbedtls_sha256_free(&ctx);
 
-    return( ret );
+    return ret;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_sha256( const unsigned char *input,
-                     size_t ilen,
-                     unsigned char output[32],
-                     int is224 )
-{
-    mbedtls_sha256_ret( input, ilen, output, is224 );
-}
-#endif
-
 #if defined(MBEDTLS_SELF_TEST)
 /*
  * FIPS-180-2 test vectors
  */
-static const unsigned char sha256_test_buf[3][57] =
+static const unsigned char sha_test_buf[3][57] =
 {
     { "abc" },
     { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
     { "" }
 };
 
-static const size_t sha256_test_buflen[3] =
+static const size_t sha_test_buflen[3] =
 {
     3, 56, 1000
 };
 
-static const unsigned char sha256_test_sum[6][32] =
+typedef const unsigned char (sha_test_sum_t)[32];
+
+/*
+ * SHA-224 test vectors
+ */
+#if defined(MBEDTLS_SHA224_C)
+static sha_test_sum_t sha224_test_sum[] =
 {
-    /*
-     * SHA-224 test vectors
-     */
     { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
       0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
       0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
@@ -479,11 +806,16 @@
     { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
       0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
       0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
-      0x4E, 0xE7, 0xAD, 0x67 },
+      0x4E, 0xE7, 0xAD, 0x67 }
+};
+#endif
 
-    /*
-     * SHA-256 test vectors
-     */
+/*
+ * SHA-256 test vectors
+ */
+#if defined(MBEDTLS_SHA256_C)
+static sha_test_sum_t sha256_test_sum[] =
+{
     { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
       0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
       0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
@@ -497,89 +829,111 @@
       0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
       0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
 };
+#endif
 
 /*
  * Checkup routine
  */
-int mbedtls_sha256_self_test( int verbose )
+static int mbedtls_sha256_common_self_test(int verbose, int is224)
 {
-    int i, j, k, buflen, ret = 0;
+    int i, buflen, ret = 0;
     unsigned char *buf;
     unsigned char sha256sum[32];
     mbedtls_sha256_context ctx;
 
-    buf = mbedtls_calloc( 1024, sizeof(unsigned char) );
-    if( NULL == buf )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "Buffer allocation failed\n" );
+#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)
+    sha_test_sum_t *sha_test_sum = (is224) ? sha224_test_sum : sha256_test_sum;
+#elif defined(MBEDTLS_SHA256_C)
+    sha_test_sum_t *sha_test_sum = sha256_test_sum;
+#else
+    sha_test_sum_t *sha_test_sum = sha224_test_sum;
+#endif
 
-        return( 1 );
+    buf = mbedtls_calloc(1024, sizeof(unsigned char));
+    if (NULL == buf) {
+        if (verbose != 0) {
+            mbedtls_printf("Buffer allocation failed\n");
+        }
+
+        return 1;
     }
 
-    mbedtls_sha256_init( &ctx );
+    mbedtls_sha256_init(&ctx);
 
-    for( i = 0; i < 6; i++ )
-    {
-        j = i % 3;
-        k = i < 3;
+    for (i = 0; i < 3; i++) {
+        if (verbose != 0) {
+            mbedtls_printf("  SHA-%d test #%d: ", 256 - is224 * 32, i + 1);
+        }
 
-        if( verbose != 0 )
-            mbedtls_printf( "  SHA-%d test #%d: ", 256 - k * 32, j + 1 );
-
-        if( ( ret = mbedtls_sha256_starts_ret( &ctx, k ) ) != 0 )
+        if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) {
             goto fail;
+        }
 
-        if( j == 2 )
-        {
-            memset( buf, 'a', buflen = 1000 );
+        if (i == 2) {
+            memset(buf, 'a', buflen = 1000);
 
-            for( j = 0; j < 1000; j++ )
-            {
-                ret = mbedtls_sha256_update_ret( &ctx, buf, buflen );
-                if( ret != 0 )
+            for (int j = 0; j < 1000; j++) {
+                ret = mbedtls_sha256_update(&ctx, buf, buflen);
+                if (ret != 0) {
                     goto fail;
+                }
             }
 
-        }
-        else
-        {
-            ret = mbedtls_sha256_update_ret( &ctx, sha256_test_buf[j],
-                                             sha256_test_buflen[j] );
-            if( ret != 0 )
-                 goto fail;
+        } else {
+            ret = mbedtls_sha256_update(&ctx, sha_test_buf[i],
+                                        sha_test_buflen[i]);
+            if (ret != 0) {
+                goto fail;
+            }
         }
 
-        if( ( ret = mbedtls_sha256_finish_ret( &ctx, sha256sum ) ) != 0 )
+        if ((ret = mbedtls_sha256_finish(&ctx, sha256sum)) != 0) {
             goto fail;
+        }
 
 
-        if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 )
-        {
+        if (memcmp(sha256sum, sha_test_sum[i], 32 - is224 * 4) != 0) {
             ret = 1;
             goto fail;
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
     goto exit;
 
 fail:
-    if( verbose != 0 )
-        mbedtls_printf( "failed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("failed\n");
+    }
 
 exit:
-    mbedtls_sha256_free( &ctx );
-    mbedtls_free( buf );
+    mbedtls_sha256_free(&ctx);
+    mbedtls_free(buf);
 
-    return( ret );
+    return ret;
 }
 
+#if defined(MBEDTLS_SHA256_C)
+int mbedtls_sha256_self_test(int verbose)
+{
+    return mbedtls_sha256_common_self_test(verbose, 0);
+}
+#endif /* MBEDTLS_SHA256_C */
+
+#if defined(MBEDTLS_SHA224_C)
+int mbedtls_sha224_self_test(int verbose)
+{
+    return mbedtls_sha256_common_self_test(verbose, 1);
+}
+#endif /* MBEDTLS_SHA224_C */
+
 #endif /* MBEDTLS_SELF_TEST */
 
-#endif /* MBEDTLS_SHA256_C */
+#endif /* MBEDTLS_SHA256_C || MBEDTLS_SHA224_C */
diff --git a/lib/libmbedtls/mbedtls/library/sha512.c b/lib/libmbedtls/mbedtls/library/sha512.c
index 02a135c..67acfee 100644
--- a/lib/libmbedtls/mbedtls/library/sha512.c
+++ b/lib/libmbedtls/mbedtls/library/sha512.c
@@ -22,9 +22,25 @@
  *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
  */
 
+#if defined(__aarch64__) && !defined(__ARM_FEATURE_SHA512) && \
+    defined(__clang__) && __clang_major__ >= 7
+/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged.
+ *
+ * The intrinsic declaration are guarded by predefined ACLE macros in clang:
+ * these are normally only enabled by the -march option on the command line.
+ * By defining the macros ourselves we gain access to those declarations without
+ * requiring -march on the command line.
+ *
+ * `arm_neon.h` could be included by any header file, so we put these defines
+ * at the top of this file, before any includes.
+ */
+#define __ARM_FEATURE_SHA512 1
+#define MBEDTLS_ENABLE_ARM_SHA3_EXTENSIONS_COMPILER_FLAG
+#endif
+
 #include "common.h"
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA384_C)
 
 #include "mbedtls/sha512.h"
 #include "mbedtls/platform_util.h"
@@ -38,26 +54,161 @@
 
 #include <string.h>
 
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#define mbedtls_printf printf
-#define mbedtls_calloc    calloc
-#define mbedtls_free       free
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
 
-#define SHA512_VALIDATE_RET(cond)                           \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA )
-#define SHA512_VALIDATE(cond)  MBEDTLS_INTERNAL_VALIDATE( cond )
+#if defined(__aarch64__)
+#  if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \
+    defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
+/* *INDENT-OFF* */
+/*
+ * Best performance comes from most recent compilers, with intrinsics and -O3.
+ * Must compile with -march=armv8.2-a+sha3, but we can't detect armv8.2-a, and
+ * can't always detect __ARM_FEATURE_SHA512 (notably clang 7-12).
+ *
+ * GCC < 8 won't work at all (lacks the sha512 instructions)
+ * GCC >= 8 uses intrinsics, sets __ARM_FEATURE_SHA512
+ *
+ * Clang < 7 won't work at all (lacks the sha512 instructions)
+ * Clang 7-12 don't have intrinsics (but we work around that with inline
+ *            assembler) or __ARM_FEATURE_SHA512
+ * Clang == 13.0.0 same as clang 12 (only seen on macOS)
+ * Clang >= 13.0.1 has __ARM_FEATURE_SHA512 and intrinsics
+ */
+#    if !defined(__ARM_FEATURE_SHA512) || defined(MBEDTLS_ENABLE_ARM_SHA3_EXTENSIONS_COMPILER_FLAG)
+       /* Test Clang first, as it defines __GNUC__ */
+#      if defined(__clang__)
+#        if __clang_major__ < 7
+#          error "A more recent Clang is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
+#        else
+#          pragma clang attribute push (__attribute__((target("sha3"))), apply_to=function)
+#          define MBEDTLS_POP_TARGET_PRAGMA
+#        endif
+#      elif defined(__GNUC__)
+#        if __GNUC__ < 8
+#          error "A more recent GCC is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
+#        else
+#          pragma GCC push_options
+#          pragma GCC target ("arch=armv8.2-a+sha3")
+#          define MBEDTLS_POP_TARGET_PRAGMA
+#        endif
+#      else
+#        error "Only GCC and Clang supported for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
+#      endif
+#    endif
+/* *INDENT-ON* */
+#    include <arm_neon.h>
+#  endif
+#  if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
+#    if defined(__unix__)
+#      if defined(__linux__)
+/* Our preferred method of detection is getauxval() */
+#        include <sys/auxv.h>
+#      endif
+/* Use SIGILL on Unix, and fall back to it on Linux */
+#      include <signal.h>
+#    endif
+#  endif
+#elif defined(_M_ARM64)
+#  if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \
+    defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
+#    include <arm64_neon.h>
+#  endif
+#else
+#  undef MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY
+#  undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
+#endif
+
+#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
+/*
+ * Capability detection code comes early, so we can disable
+ * MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT if no detection mechanism found
+ */
+#if defined(HWCAP_SHA512)
+static int mbedtls_a64_crypto_sha512_determine_support(void)
+{
+    return (getauxval(AT_HWCAP) & HWCAP_SHA512) ? 1 : 0;
+}
+#elif defined(__APPLE__)
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+static int mbedtls_a64_crypto_sha512_determine_support(void)
+{
+    int value = 0;
+    size_t value_len = sizeof(value);
+
+    int ret = sysctlbyname("hw.optional.armv8_2_sha512", &value, &value_len,
+                           NULL, 0);
+    return ret == 0 && value != 0;
+}
+#elif defined(_M_ARM64)
+/*
+ * As of March 2022, there don't appear to be any PF_ARM_V8_* flags
+ * available to pass to IsProcessorFeaturePresent() to check for
+ * SHA-512 support. So we fall back to the C code only.
+ */
+#if defined(_MSC_VER)
+#pragma message "No mechanism to detect A64_CRYPTO found, using C code only"
+#else
+#warning "No mechanism to detect A64_CRYPTO found, using C code only"
+#endif
+#elif defined(__unix__) && defined(SIG_SETMASK)
+/* Detection with SIGILL, setjmp() and longjmp() */
+#include <signal.h>
+#include <setjmp.h>
+
+static jmp_buf return_from_sigill;
+
+/*
+ * A64 SHA512 support detection via SIGILL
+ */
+static void sigill_handler(int signal)
+{
+    (void) signal;
+    longjmp(return_from_sigill, 1);
+}
+
+static int mbedtls_a64_crypto_sha512_determine_support(void)
+{
+    struct sigaction old_action, new_action;
+
+    sigset_t old_mask;
+    if (sigprocmask(0, NULL, &old_mask)) {
+        return 0;
+    }
+
+    sigemptyset(&new_action.sa_mask);
+    new_action.sa_flags = 0;
+    new_action.sa_handler = sigill_handler;
+
+    sigaction(SIGILL, &new_action, &old_action);
+
+    static int ret = 0;
+
+    if (setjmp(return_from_sigill) == 0) {         /* First return only */
+        /* If this traps, we will return a second time from setjmp() with 1 */
+        asm ("sha512h q0, q0, v0.2d" : : : "v0");
+        ret = 1;
+    }
+
+    sigaction(SIGILL, &old_action, NULL);
+    sigprocmask(SIG_SETMASK, &old_mask, NULL);
+
+    return ret;
+}
+#else
+#warning "No mechanism to detect A64_CRYPTO found, using C code only"
+#undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
+#endif  /* HWCAP_SHA512, __APPLE__, __unix__ && SIG_SETMASK */
+
+#endif  /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */
 
 #if !defined(MBEDTLS_SHA512_ALT)
 
+#define SHA512_BLOCK_SIZE 128
+
 #if defined(MBEDTLS_SHA512_SMALLER)
-static void sha512_put_uint64_be( uint64_t n, unsigned char *b, uint8_t i )
+static void sha512_put_uint64_be(uint64_t n, unsigned char *b, uint8_t i)
 {
     MBEDTLS_PUT_UINT64_BE(n, b, i);
 }
@@ -65,48 +216,50 @@
 #define sha512_put_uint64_be    MBEDTLS_PUT_UINT64_BE
 #endif /* MBEDTLS_SHA512_SMALLER */
 
-void mbedtls_sha512_init( mbedtls_sha512_context *ctx )
+void mbedtls_sha512_init(mbedtls_sha512_context *ctx)
 {
-    SHA512_VALIDATE( ctx != NULL );
-
-    memset( ctx, 0, sizeof( mbedtls_sha512_context ) );
+    memset(ctx, 0, sizeof(mbedtls_sha512_context));
 }
 
-void mbedtls_sha512_free( mbedtls_sha512_context *ctx )
+void mbedtls_sha512_free(mbedtls_sha512_context *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha512_context ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha512_context));
 }
 
-void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
-                           const mbedtls_sha512_context *src )
+void mbedtls_sha512_clone(mbedtls_sha512_context *dst,
+                          const mbedtls_sha512_context *src)
 {
-    SHA512_VALIDATE( dst != NULL );
-    SHA512_VALIDATE( src != NULL );
-
     *dst = *src;
 }
 
 /*
  * SHA-512 context setup
  */
-int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 )
+int mbedtls_sha512_starts(mbedtls_sha512_context *ctx, int is384)
 {
-    SHA512_VALIDATE_RET( ctx != NULL );
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
-    SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 );
-#else
-    SHA512_VALIDATE_RET( is384 == 0 );
+#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C)
+    if (is384 != 0 && is384 != 1) {
+        return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
+    }
+#elif defined(MBEDTLS_SHA512_C)
+    if (is384 != 0) {
+        return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
+    }
+#else /* defined MBEDTLS_SHA384_C only */
+    if (is384 == 0) {
+        return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
+    }
 #endif
 
     ctx->total[0] = 0;
     ctx->total[1] = 0;
 
-    if( is384 == 0 )
-    {
-        /* SHA-512 */
+    if (is384 == 0) {
+#if defined(MBEDTLS_SHA512_C)
         ctx->state[0] = UL64(0x6A09E667F3BCC908);
         ctx->state[1] = UL64(0xBB67AE8584CAA73B);
         ctx->state[2] = UL64(0x3C6EF372FE94F82B);
@@ -115,13 +268,9 @@
         ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
         ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
         ctx->state[7] = UL64(0x5BE0CD19137E2179);
-    }
-    else
-    {
-#if defined(MBEDTLS_SHA512_NO_SHA384)
-        return( MBEDTLS_ERR_SHA512_BAD_INPUT_DATA );
-#else
-        /* SHA-384 */
+#endif /* MBEDTLS_SHA512_C */
+    } else {
+#if defined(MBEDTLS_SHA384_C)
         ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
         ctx->state[1] = UL64(0x629A292A367CD507);
         ctx->state[2] = UL64(0x9159015A3070DD17);
@@ -130,24 +279,16 @@
         ctx->state[5] = UL64(0x8EB44A8768581511);
         ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
         ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
-#endif /* MBEDTLS_SHA512_NO_SHA384 */
+#endif /* MBEDTLS_SHA384_C */
     }
 
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
+#if defined(MBEDTLS_SHA384_C)
     ctx->is384 = is384;
 #endif
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_sha512_starts( mbedtls_sha512_context *ctx,
-                            int is384 )
-{
-    mbedtls_sha512_starts_ret( ctx, is384 );
-}
-#endif
-
 #if !defined(MBEDTLS_SHA512_PROCESS_ALT)
 
 /*
@@ -196,58 +337,309 @@
     UL64(0x4CC5D4BECB3E42B6),  UL64(0x597F299CFC657E2A),
     UL64(0x5FCB6FAB3AD6FAEC),  UL64(0x6C44198C4A475817)
 };
+#endif
 
-int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx,
-                                     const unsigned char data[128] )
+#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \
+    defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
+
+#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
+#  define mbedtls_internal_sha512_process_many_a64_crypto mbedtls_internal_sha512_process_many
+#  define mbedtls_internal_sha512_process_a64_crypto      mbedtls_internal_sha512_process
+#endif
+
+/* Accelerated SHA-512 implementation originally written by Simon Tatham for PuTTY,
+ * under the MIT licence; dual-licensed as Apache 2 with his kind permission.
+ */
+
+#if defined(__clang__) && \
+    (__clang_major__ < 13 || \
+     (__clang_major__ == 13 && __clang_minor__ == 0 && __clang_patchlevel__ == 0))
+static inline uint64x2_t vsha512su0q_u64(uint64x2_t x, uint64x2_t y)
+{
+    asm ("sha512su0 %0.2D,%1.2D" : "+w" (x) : "w" (y));
+    return x;
+}
+static inline uint64x2_t vsha512su1q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)
+{
+    asm ("sha512su1 %0.2D,%1.2D,%2.2D" : "+w" (x) : "w" (y), "w" (z));
+    return x;
+}
+static inline uint64x2_t vsha512hq_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)
+{
+    asm ("sha512h %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z));
+    return x;
+}
+static inline uint64x2_t vsha512h2q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)
+{
+    asm ("sha512h2 %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z));
+    return x;
+}
+#endif  /* __clang__ etc */
+
+static size_t mbedtls_internal_sha512_process_many_a64_crypto(
+    mbedtls_sha512_context *ctx, const uint8_t *msg, size_t len)
+{
+    uint64x2_t ab = vld1q_u64(&ctx->state[0]);
+    uint64x2_t cd = vld1q_u64(&ctx->state[2]);
+    uint64x2_t ef = vld1q_u64(&ctx->state[4]);
+    uint64x2_t gh = vld1q_u64(&ctx->state[6]);
+
+    size_t processed = 0;
+
+    for (;
+         len >= SHA512_BLOCK_SIZE;
+         processed += SHA512_BLOCK_SIZE,
+         msg += SHA512_BLOCK_SIZE,
+         len -= SHA512_BLOCK_SIZE) {
+        uint64x2_t initial_sum, sum, intermed;
+
+        uint64x2_t ab_orig = ab;
+        uint64x2_t cd_orig = cd;
+        uint64x2_t ef_orig = ef;
+        uint64x2_t gh_orig = gh;
+
+        uint64x2_t s0 = (uint64x2_t) vld1q_u8(msg + 16 * 0);
+        uint64x2_t s1 = (uint64x2_t) vld1q_u8(msg + 16 * 1);
+        uint64x2_t s2 = (uint64x2_t) vld1q_u8(msg + 16 * 2);
+        uint64x2_t s3 = (uint64x2_t) vld1q_u8(msg + 16 * 3);
+        uint64x2_t s4 = (uint64x2_t) vld1q_u8(msg + 16 * 4);
+        uint64x2_t s5 = (uint64x2_t) vld1q_u8(msg + 16 * 5);
+        uint64x2_t s6 = (uint64x2_t) vld1q_u8(msg + 16 * 6);
+        uint64x2_t s7 = (uint64x2_t) vld1q_u8(msg + 16 * 7);
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__  /* assume LE if these not defined; untested on BE */
+        s0 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s0)));
+        s1 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s1)));
+        s2 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s2)));
+        s3 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s3)));
+        s4 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s4)));
+        s5 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s5)));
+        s6 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s6)));
+        s7 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s7)));
+#endif
+
+        /* Rounds 0 and 1 */
+        initial_sum = vaddq_u64(s0, vld1q_u64(&K[0]));
+        sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh);
+        intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1));
+        gh = vsha512h2q_u64(intermed, cd, ab);
+        cd = vaddq_u64(cd, intermed);
+
+        /* Rounds 2 and 3 */
+        initial_sum = vaddq_u64(s1, vld1q_u64(&K[2]));
+        sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef);
+        intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1));
+        ef = vsha512h2q_u64(intermed, ab, gh);
+        ab = vaddq_u64(ab, intermed);
+
+        /* Rounds 4 and 5 */
+        initial_sum = vaddq_u64(s2, vld1q_u64(&K[4]));
+        sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd);
+        intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1));
+        cd = vsha512h2q_u64(intermed, gh, ef);
+        gh = vaddq_u64(gh, intermed);
+
+        /* Rounds 6 and 7 */
+        initial_sum = vaddq_u64(s3, vld1q_u64(&K[6]));
+        sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab);
+        intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1));
+        ab = vsha512h2q_u64(intermed, ef, cd);
+        ef = vaddq_u64(ef, intermed);
+
+        /* Rounds 8 and 9 */
+        initial_sum = vaddq_u64(s4, vld1q_u64(&K[8]));
+        sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh);
+        intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1));
+        gh = vsha512h2q_u64(intermed, cd, ab);
+        cd = vaddq_u64(cd, intermed);
+
+        /* Rounds 10 and 11 */
+        initial_sum = vaddq_u64(s5, vld1q_u64(&K[10]));
+        sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef);
+        intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1));
+        ef = vsha512h2q_u64(intermed, ab, gh);
+        ab = vaddq_u64(ab, intermed);
+
+        /* Rounds 12 and 13 */
+        initial_sum = vaddq_u64(s6, vld1q_u64(&K[12]));
+        sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd);
+        intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1));
+        cd = vsha512h2q_u64(intermed, gh, ef);
+        gh = vaddq_u64(gh, intermed);
+
+        /* Rounds 14 and 15 */
+        initial_sum = vaddq_u64(s7, vld1q_u64(&K[14]));
+        sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab);
+        intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1));
+        ab = vsha512h2q_u64(intermed, ef, cd);
+        ef = vaddq_u64(ef, intermed);
+
+        for (unsigned int t = 16; t < 80; t += 16) {
+            /* Rounds t and t + 1 */
+            s0 = vsha512su1q_u64(vsha512su0q_u64(s0, s1), s7, vextq_u64(s4, s5, 1));
+            initial_sum = vaddq_u64(s0, vld1q_u64(&K[t]));
+            sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh);
+            intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1));
+            gh = vsha512h2q_u64(intermed, cd, ab);
+            cd = vaddq_u64(cd, intermed);
+
+            /* Rounds t + 2 and t + 3 */
+            s1 = vsha512su1q_u64(vsha512su0q_u64(s1, s2), s0, vextq_u64(s5, s6, 1));
+            initial_sum = vaddq_u64(s1, vld1q_u64(&K[t + 2]));
+            sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef);
+            intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1));
+            ef = vsha512h2q_u64(intermed, ab, gh);
+            ab = vaddq_u64(ab, intermed);
+
+            /* Rounds t + 4 and t + 5 */
+            s2 = vsha512su1q_u64(vsha512su0q_u64(s2, s3), s1, vextq_u64(s6, s7, 1));
+            initial_sum = vaddq_u64(s2, vld1q_u64(&K[t + 4]));
+            sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd);
+            intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1));
+            cd = vsha512h2q_u64(intermed, gh, ef);
+            gh = vaddq_u64(gh, intermed);
+
+            /* Rounds t + 6 and t + 7 */
+            s3 = vsha512su1q_u64(vsha512su0q_u64(s3, s4), s2, vextq_u64(s7, s0, 1));
+            initial_sum = vaddq_u64(s3, vld1q_u64(&K[t + 6]));
+            sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab);
+            intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1));
+            ab = vsha512h2q_u64(intermed, ef, cd);
+            ef = vaddq_u64(ef, intermed);
+
+            /* Rounds t + 8 and t + 9 */
+            s4 = vsha512su1q_u64(vsha512su0q_u64(s4, s5), s3, vextq_u64(s0, s1, 1));
+            initial_sum = vaddq_u64(s4, vld1q_u64(&K[t + 8]));
+            sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh);
+            intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1));
+            gh = vsha512h2q_u64(intermed, cd, ab);
+            cd = vaddq_u64(cd, intermed);
+
+            /* Rounds t + 10 and t + 11 */
+            s5 = vsha512su1q_u64(vsha512su0q_u64(s5, s6), s4, vextq_u64(s1, s2, 1));
+            initial_sum = vaddq_u64(s5, vld1q_u64(&K[t + 10]));
+            sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef);
+            intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1));
+            ef = vsha512h2q_u64(intermed, ab, gh);
+            ab = vaddq_u64(ab, intermed);
+
+            /* Rounds t + 12 and t + 13 */
+            s6 = vsha512su1q_u64(vsha512su0q_u64(s6, s7), s5, vextq_u64(s2, s3, 1));
+            initial_sum = vaddq_u64(s6, vld1q_u64(&K[t + 12]));
+            sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd);
+            intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1));
+            cd = vsha512h2q_u64(intermed, gh, ef);
+            gh = vaddq_u64(gh, intermed);
+
+            /* Rounds t + 14 and t + 15 */
+            s7 = vsha512su1q_u64(vsha512su0q_u64(s7, s0), s6, vextq_u64(s3, s4, 1));
+            initial_sum = vaddq_u64(s7, vld1q_u64(&K[t + 14]));
+            sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab);
+            intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1));
+            ab = vsha512h2q_u64(intermed, ef, cd);
+            ef = vaddq_u64(ef, intermed);
+        }
+
+        ab = vaddq_u64(ab, ab_orig);
+        cd = vaddq_u64(cd, cd_orig);
+        ef = vaddq_u64(ef, ef_orig);
+        gh = vaddq_u64(gh, gh_orig);
+    }
+
+    vst1q_u64(&ctx->state[0], ab);
+    vst1q_u64(&ctx->state[2], cd);
+    vst1q_u64(&ctx->state[4], ef);
+    vst1q_u64(&ctx->state[6], gh);
+
+    return processed;
+}
+
+#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
+/*
+ * This function is for internal use only if we are building both C and A64
+ * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process()
+ */
+static
+#endif
+int mbedtls_internal_sha512_process_a64_crypto(mbedtls_sha512_context *ctx,
+                                               const unsigned char data[SHA512_BLOCK_SIZE])
+{
+    return (mbedtls_internal_sha512_process_many_a64_crypto(ctx, data,
+                                                            SHA512_BLOCK_SIZE) ==
+            SHA512_BLOCK_SIZE) ? 0 : -1;
+}
+
+#if defined(MBEDTLS_POP_TARGET_PRAGMA)
+#if defined(__clang__)
+#pragma clang attribute pop
+#elif defined(__GNUC__)
+#pragma GCC pop_options
+#endif
+#undef MBEDTLS_POP_TARGET_PRAGMA
+#endif
+
+#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
+
+
+#if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
+#define mbedtls_internal_sha512_process_many_c mbedtls_internal_sha512_process_many
+#define mbedtls_internal_sha512_process_c      mbedtls_internal_sha512_process
+#endif
+
+
+#if !defined(MBEDTLS_SHA512_PROCESS_ALT) && !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
+
+#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
+/*
+ * This function is for internal use only if we are building both C and A64
+ * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process()
+ */
+static
+#endif
+int mbedtls_internal_sha512_process_c(mbedtls_sha512_context *ctx,
+                                      const unsigned char data[SHA512_BLOCK_SIZE])
 {
     int i;
-    struct
-    {
+    struct {
         uint64_t temp1, temp2, W[80];
         uint64_t A[8];
     } local;
 
-    SHA512_VALIDATE_RET( ctx != NULL );
-    SHA512_VALIDATE_RET( (const unsigned char *)data != NULL );
-
-#define  SHR(x,n) ((x) >> (n))
-#define ROTR(x,n) (SHR((x),(n)) | ((x) << (64 - (n))))
+#define  SHR(x, n) ((x) >> (n))
+#define ROTR(x, n) (SHR((x), (n)) | ((x) << (64 - (n))))
 
 #define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^  SHR(x, 7))
-#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^  SHR(x, 6))
+#define S1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^  SHR(x, 6))
 
-#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
-#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
+#define S2(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
+#define S3(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
 
-#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
-#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
+#define F0(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))
+#define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
 
-#define P(a,b,c,d,e,f,g,h,x,K)                                      \
+#define P(a, b, c, d, e, f, g, h, x, K)                                      \
     do                                                              \
     {                                                               \
-        local.temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x);    \
-        local.temp2 = S2(a) + F0((a),(b),(c));                      \
+        local.temp1 = (h) + S3(e) + F1((e), (f), (g)) + (K) + (x);    \
+        local.temp2 = S2(a) + F0((a), (b), (c));                      \
         (d) += local.temp1; (h) = local.temp1 + local.temp2;        \
-    } while( 0 )
+    } while (0)
 
-    for( i = 0; i < 8; i++ )
+    for (i = 0; i < 8; i++) {
         local.A[i] = ctx->state[i];
+    }
 
 #if defined(MBEDTLS_SHA512_SMALLER)
-    for( i = 0; i < 80; i++ )
-    {
-        if( i < 16 )
-        {
-            local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 );
-        }
-        else
-        {
+    for (i = 0; i < 80; i++) {
+        if (i < 16) {
+            local.W[i] = MBEDTLS_GET_UINT64_BE(data, i << 3);
+        } else {
             local.W[i] = S1(local.W[i -  2]) + local.W[i -  7] +
-                   S0(local.W[i - 15]) + local.W[i - 16];
+                         S0(local.W[i - 15]) + local.W[i - 16];
         }
 
-        P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
-           local.A[5], local.A[6], local.A[7], local.W[i], K[i] );
+        P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
+          local.A[5], local.A[6], local.A[7], local.W[i], K[i]);
 
         local.temp1 = local.A[7]; local.A[7] = local.A[6];
         local.A[6] = local.A[5]; local.A[5] = local.A[4];
@@ -256,132 +648,174 @@
         local.A[0] = local.temp1;
     }
 #else /* MBEDTLS_SHA512_SMALLER */
-    for( i = 0; i < 16; i++ )
-    {
-        local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 );
+    for (i = 0; i < 16; i++) {
+        local.W[i] = MBEDTLS_GET_UINT64_BE(data, i << 3);
     }
 
-    for( ; i < 80; i++ )
-    {
+    for (; i < 80; i++) {
         local.W[i] = S1(local.W[i -  2]) + local.W[i -  7] +
-               S0(local.W[i - 15]) + local.W[i - 16];
+                     S0(local.W[i - 15]) + local.W[i - 16];
     }
 
     i = 0;
-    do
-    {
-        P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
-           local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); i++;
-        P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],
-           local.A[4], local.A[5], local.A[6], local.W[i], K[i] ); i++;
-        P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],
-           local.A[3], local.A[4], local.A[5], local.W[i], K[i] ); i++;
-        P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],
-           local.A[2], local.A[3], local.A[4], local.W[i], K[i] ); i++;
-        P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],
-           local.A[1], local.A[2], local.A[3], local.W[i], K[i] ); i++;
-        P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],
-           local.A[0], local.A[1], local.A[2], local.W[i], K[i] ); i++;
-        P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],
-           local.A[7], local.A[0], local.A[1], local.W[i], K[i] ); i++;
-        P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],
-           local.A[6], local.A[7], local.A[0], local.W[i], K[i] ); i++;
-    }
-    while( i < 80 );
+    do {
+        P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
+          local.A[5], local.A[6], local.A[7], local.W[i], K[i]); i++;
+        P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],
+          local.A[4], local.A[5], local.A[6], local.W[i], K[i]); i++;
+        P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],
+          local.A[3], local.A[4], local.A[5], local.W[i], K[i]); i++;
+        P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],
+          local.A[2], local.A[3], local.A[4], local.W[i], K[i]); i++;
+        P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],
+          local.A[1], local.A[2], local.A[3], local.W[i], K[i]); i++;
+        P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],
+          local.A[0], local.A[1], local.A[2], local.W[i], K[i]); i++;
+        P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],
+          local.A[7], local.A[0], local.A[1], local.W[i], K[i]); i++;
+        P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],
+          local.A[6], local.A[7], local.A[0], local.W[i], K[i]); i++;
+    } while (i < 80);
 #endif /* MBEDTLS_SHA512_SMALLER */
 
-    for( i = 0; i < 8; i++ )
+    for (i = 0; i < 8; i++) {
         ctx->state[i] += local.A[i];
+    }
 
     /* Zeroise buffers and variables to clear sensitive data from memory. */
-    mbedtls_platform_zeroize( &local, sizeof( local ) );
+    mbedtls_platform_zeroize(&local, sizeof(local));
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_sha512_process( mbedtls_sha512_context *ctx,
-                             const unsigned char data[128] )
+#endif /* !MBEDTLS_SHA512_PROCESS_ALT && !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
+
+
+#if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
+
+static size_t mbedtls_internal_sha512_process_many_c(
+    mbedtls_sha512_context *ctx, const uint8_t *data, size_t len)
 {
-    mbedtls_internal_sha512_process( ctx, data );
+    size_t processed = 0;
+
+    while (len >= SHA512_BLOCK_SIZE) {
+        if (mbedtls_internal_sha512_process_c(ctx, data) != 0) {
+            return 0;
+        }
+
+        data += SHA512_BLOCK_SIZE;
+        len  -= SHA512_BLOCK_SIZE;
+
+        processed += SHA512_BLOCK_SIZE;
+    }
+
+    return processed;
 }
-#endif
-#endif /* !MBEDTLS_SHA512_PROCESS_ALT */
+
+#endif /* !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
+
+
+#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
+
+static int mbedtls_a64_crypto_sha512_has_support(void)
+{
+    static int done = 0;
+    static int supported = 0;
+
+    if (!done) {
+        supported = mbedtls_a64_crypto_sha512_determine_support();
+        done = 1;
+    }
+
+    return supported;
+}
+
+static size_t mbedtls_internal_sha512_process_many(mbedtls_sha512_context *ctx,
+                                                   const uint8_t *msg, size_t len)
+{
+    if (mbedtls_a64_crypto_sha512_has_support()) {
+        return mbedtls_internal_sha512_process_many_a64_crypto(ctx, msg, len);
+    } else {
+        return mbedtls_internal_sha512_process_many_c(ctx, msg, len);
+    }
+}
+
+int mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx,
+                                    const unsigned char data[SHA512_BLOCK_SIZE])
+{
+    if (mbedtls_a64_crypto_sha512_has_support()) {
+        return mbedtls_internal_sha512_process_a64_crypto(ctx, data);
+    } else {
+        return mbedtls_internal_sha512_process_c(ctx, data);
+    }
+}
+
+#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */
 
 /*
  * SHA-512 process buffer
  */
-int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx,
-                               const unsigned char *input,
-                               size_t ilen )
+int mbedtls_sha512_update(mbedtls_sha512_context *ctx,
+                          const unsigned char *input,
+                          size_t ilen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t fill;
     unsigned int left;
 
-    SHA512_VALIDATE_RET( ctx != NULL );
-    SHA512_VALIDATE_RET( ilen == 0 || input != NULL );
-
-    if( ilen == 0 )
-        return( 0 );
+    if (ilen == 0) {
+        return 0;
+    }
 
     left = (unsigned int) (ctx->total[0] & 0x7F);
-    fill = 128 - left;
+    fill = SHA512_BLOCK_SIZE - left;
 
     ctx->total[0] += (uint64_t) ilen;
 
-    if( ctx->total[0] < (uint64_t) ilen )
+    if (ctx->total[0] < (uint64_t) ilen) {
         ctx->total[1]++;
+    }
 
-    if( left && ilen >= fill )
-    {
-        memcpy( (void *) (ctx->buffer + left), input, fill );
+    if (left && ilen >= fill) {
+        memcpy((void *) (ctx->buffer + left), input, fill);
 
-        if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
-            return( ret );
+        if ((ret = mbedtls_internal_sha512_process(ctx, ctx->buffer)) != 0) {
+            return ret;
+        }
 
         input += fill;
         ilen  -= fill;
         left = 0;
     }
 
-    while( ilen >= 128 )
-    {
-        if( ( ret = mbedtls_internal_sha512_process( ctx, input ) ) != 0 )
-            return( ret );
+    while (ilen >= SHA512_BLOCK_SIZE) {
+        size_t processed =
+            mbedtls_internal_sha512_process_many(ctx, input, ilen);
+        if (processed < SHA512_BLOCK_SIZE) {
+            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
+        }
 
-        input += 128;
-        ilen  -= 128;
+        input += processed;
+        ilen  -= processed;
     }
 
-    if( ilen > 0 )
-        memcpy( (void *) (ctx->buffer + left), input, ilen );
+    if (ilen > 0) {
+        memcpy((void *) (ctx->buffer + left), input, ilen);
+    }
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_sha512_update( mbedtls_sha512_context *ctx,
-                            const unsigned char *input,
-                            size_t ilen )
-{
-    mbedtls_sha512_update_ret( ctx, input, ilen );
-}
-#endif
-
 /*
  * SHA-512 final digest
  */
-int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx,
-                               unsigned char output[64] )
+int mbedtls_sha512_finish(mbedtls_sha512_context *ctx,
+                          unsigned char *output)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned used;
     uint64_t high, low;
 
-    SHA512_VALIDATE_RET( ctx != NULL );
-    SHA512_VALIDATE_RET( (unsigned char *)output != NULL );
-
     /*
      * Add padding: 0x80 then 0x00 until 16 bytes remain for the length
      */
@@ -389,135 +823,130 @@
 
     ctx->buffer[used++] = 0x80;
 
-    if( used <= 112 )
-    {
+    if (used <= 112) {
         /* Enough room for padding + length in current block */
-        memset( ctx->buffer + used, 0, 112 - used );
-    }
-    else
-    {
+        memset(ctx->buffer + used, 0, 112 - used);
+    } else {
         /* We'll need an extra block */
-        memset( ctx->buffer + used, 0, 128 - used );
+        memset(ctx->buffer + used, 0, SHA512_BLOCK_SIZE - used);
 
-        if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
-            return( ret );
+        if ((ret = mbedtls_internal_sha512_process(ctx, ctx->buffer)) != 0) {
+            return ret;
+        }
 
-        memset( ctx->buffer, 0, 112 );
+        memset(ctx->buffer, 0, 112);
     }
 
     /*
      * Add message length
      */
-    high = ( ctx->total[0] >> 61 )
-         | ( ctx->total[1] <<  3 );
-    low  = ( ctx->total[0] <<  3 );
+    high = (ctx->total[0] >> 61)
+           | (ctx->total[1] <<  3);
+    low  = (ctx->total[0] <<  3);
 
-    sha512_put_uint64_be( high, ctx->buffer, 112 );
-    sha512_put_uint64_be( low,  ctx->buffer, 120 );
+    sha512_put_uint64_be(high, ctx->buffer, 112);
+    sha512_put_uint64_be(low,  ctx->buffer, 120);
 
-    if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_internal_sha512_process(ctx, ctx->buffer)) != 0) {
+        return ret;
+    }
 
     /*
      * Output final state
      */
-    sha512_put_uint64_be( ctx->state[0], output,  0 );
-    sha512_put_uint64_be( ctx->state[1], output,  8 );
-    sha512_put_uint64_be( ctx->state[2], output, 16 );
-    sha512_put_uint64_be( ctx->state[3], output, 24 );
-    sha512_put_uint64_be( ctx->state[4], output, 32 );
-    sha512_put_uint64_be( ctx->state[5], output, 40 );
+    sha512_put_uint64_be(ctx->state[0], output,  0);
+    sha512_put_uint64_be(ctx->state[1], output,  8);
+    sha512_put_uint64_be(ctx->state[2], output, 16);
+    sha512_put_uint64_be(ctx->state[3], output, 24);
+    sha512_put_uint64_be(ctx->state[4], output, 32);
+    sha512_put_uint64_be(ctx->state[5], output, 40);
 
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
-    if( ctx->is384 == 0 )
+    int truncated = 0;
+#if defined(MBEDTLS_SHA384_C)
+    truncated = ctx->is384;
 #endif
-    {
-        sha512_put_uint64_be( ctx->state[6], output, 48 );
-        sha512_put_uint64_be( ctx->state[7], output, 56 );
+    if (!truncated) {
+        sha512_put_uint64_be(ctx->state[6], output, 48);
+        sha512_put_uint64_be(ctx->state[7], output, 56);
     }
 
-    return( 0 );
+    return 0;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_sha512_finish( mbedtls_sha512_context *ctx,
-                            unsigned char output[64] )
-{
-    mbedtls_sha512_finish_ret( ctx, output );
-}
-#endif
-
 #endif /* !MBEDTLS_SHA512_ALT */
 
 /*
  * output = SHA-512( input buffer )
  */
-int mbedtls_sha512_ret( const unsigned char *input,
-                    size_t ilen,
-                    unsigned char output[64],
-                    int is384 )
+int mbedtls_sha512(const unsigned char *input,
+                   size_t ilen,
+                   unsigned char *output,
+                   int is384)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_sha512_context ctx;
 
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
-    SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 );
-#else
-    SHA512_VALIDATE_RET( is384 == 0 );
+#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C)
+    if (is384 != 0 && is384 != 1) {
+        return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
+    }
+#elif defined(MBEDTLS_SHA512_C)
+    if (is384 != 0) {
+        return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
+    }
+#else /* defined MBEDTLS_SHA384_C only */
+    if (is384 == 0) {
+        return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
+    }
 #endif
-    SHA512_VALIDATE_RET( ilen == 0 || input != NULL );
-    SHA512_VALIDATE_RET( (unsigned char *)output != NULL );
 
-    mbedtls_sha512_init( &ctx );
+    mbedtls_sha512_init(&ctx);
 
-    if( ( ret = mbedtls_sha512_starts_ret( &ctx, is384 ) ) != 0 )
+    if ((ret = mbedtls_sha512_starts(&ctx, is384)) != 0) {
         goto exit;
+    }
 
-    if( ( ret = mbedtls_sha512_update_ret( &ctx, input, ilen ) ) != 0 )
+    if ((ret = mbedtls_sha512_update(&ctx, input, ilen)) != 0) {
         goto exit;
+    }
 
-    if( ( ret = mbedtls_sha512_finish_ret( &ctx, output ) ) != 0 )
+    if ((ret = mbedtls_sha512_finish(&ctx, output)) != 0) {
         goto exit;
+    }
 
 exit:
-    mbedtls_sha512_free( &ctx );
+    mbedtls_sha512_free(&ctx);
 
-    return( ret );
+    return ret;
 }
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-void mbedtls_sha512( const unsigned char *input,
-                     size_t ilen,
-                     unsigned char output[64],
-                     int is384 )
-{
-    mbedtls_sha512_ret( input, ilen, output, is384 );
-}
-#endif
-
 #if defined(MBEDTLS_SELF_TEST)
 
 /*
  * FIPS-180-2 test vectors
  */
-static const unsigned char sha512_test_buf[3][113] =
+static const unsigned char sha_test_buf[3][113] =
 {
     { "abc" },
-    { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
+    {
+        "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
+    },
     { "" }
 };
 
-static const size_t sha512_test_buflen[3] =
+static const size_t sha_test_buflen[3] =
 {
     3, 112, 1000
 };
 
-static const unsigned char sha512_test_sum[][64] =
+typedef const unsigned char (sha_test_sum_t)[64];
+
+/*
+ * SHA-384 test vectors
+ */
+#if defined(MBEDTLS_SHA384_C)
+static sha_test_sum_t sha384_test_sum[] =
 {
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
-    /*
-     * SHA-384 test vectors
-     */
     { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
       0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
       0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
@@ -535,12 +964,16 @@
       0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52,
       0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,
       0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,
-      0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 },
-#endif /* !MBEDTLS_SHA512_NO_SHA384 */
+      0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }
+};
+#endif /* MBEDTLS_SHA384_C */
 
-    /*
-     * SHA-512 test vectors
-     */
+/*
+ * SHA-512 test vectors
+ */
+#if defined(MBEDTLS_SHA512_C)
+static sha_test_sum_t sha512_test_sum[] =
+{
     { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
       0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
       0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
@@ -566,95 +999,110 @@
       0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,
       0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
 };
+#endif /* MBEDTLS_SHA512_C */
 
-#define ARRAY_LENGTH( a )   ( sizeof( a ) / sizeof( ( a )[0] ) )
+#define ARRAY_LENGTH(a)   (sizeof(a) / sizeof((a)[0]))
 
-/*
- * Checkup routine
- */
-int mbedtls_sha512_self_test( int verbose )
+static int mbedtls_sha512_common_self_test(int verbose, int is384)
 {
-    int i, j, k, buflen, ret = 0;
+    int i, buflen, ret = 0;
     unsigned char *buf;
     unsigned char sha512sum[64];
     mbedtls_sha512_context ctx;
 
-    buf = mbedtls_calloc( 1024, sizeof(unsigned char) );
-    if( NULL == buf )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "Buffer allocation failed\n" );
-
-        return( 1 );
-    }
-
-    mbedtls_sha512_init( &ctx );
-
-    for( i = 0; i < (int) ARRAY_LENGTH(sha512_test_sum); i++ )
-    {
-        j = i % 3;
-#if !defined(MBEDTLS_SHA512_NO_SHA384)
-        k = i < 3;
+#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C)
+    sha_test_sum_t *sha_test_sum = (is384) ? sha384_test_sum : sha512_test_sum;
+#elif defined(MBEDTLS_SHA512_C)
+    sha_test_sum_t *sha_test_sum = sha512_test_sum;
 #else
-        k = 0;
+    sha_test_sum_t *sha_test_sum = sha384_test_sum;
 #endif
 
-        if( verbose != 0 )
-            mbedtls_printf( "  SHA-%d test #%d: ", 512 - k * 128, j + 1 );
+    buf = mbedtls_calloc(1024, sizeof(unsigned char));
+    if (NULL == buf) {
+        if (verbose != 0) {
+            mbedtls_printf("Buffer allocation failed\n");
+        }
 
-        if( ( ret = mbedtls_sha512_starts_ret( &ctx, k ) ) != 0 )
+        return 1;
+    }
+
+    mbedtls_sha512_init(&ctx);
+
+    for (i = 0; i < 3; i++) {
+        if (verbose != 0) {
+            mbedtls_printf("  SHA-%d test #%d: ", 512 - is384 * 128, i + 1);
+        }
+
+        if ((ret = mbedtls_sha512_starts(&ctx, is384)) != 0) {
             goto fail;
+        }
 
-        if( j == 2 )
-        {
-            memset( buf, 'a', buflen = 1000 );
+        if (i == 2) {
+            memset(buf, 'a', buflen = 1000);
 
-            for( j = 0; j < 1000; j++ )
-            {
-                ret = mbedtls_sha512_update_ret( &ctx, buf, buflen );
-                if( ret != 0 )
+            for (int j = 0; j < 1000; j++) {
+                ret = mbedtls_sha512_update(&ctx, buf, buflen);
+                if (ret != 0) {
                     goto fail;
+                }
+            }
+        } else {
+            ret = mbedtls_sha512_update(&ctx, sha_test_buf[i],
+                                        sha_test_buflen[i]);
+            if (ret != 0) {
+                goto fail;
             }
         }
-        else
-        {
-            ret = mbedtls_sha512_update_ret( &ctx, sha512_test_buf[j],
-                                             sha512_test_buflen[j] );
-            if( ret != 0 )
-                goto fail;
+
+        if ((ret = mbedtls_sha512_finish(&ctx, sha512sum)) != 0) {
+            goto fail;
         }
 
-        if( ( ret = mbedtls_sha512_finish_ret( &ctx, sha512sum ) ) != 0 )
-            goto fail;
-
-        if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 )
-        {
+        if (memcmp(sha512sum, sha_test_sum[i], 64 - is384 * 16) != 0) {
             ret = 1;
             goto fail;
         }
 
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
+        if (verbose != 0) {
+            mbedtls_printf("passed\n");
+        }
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
 
     goto exit;
 
 fail:
-    if( verbose != 0 )
-        mbedtls_printf( "failed\n" );
+    if (verbose != 0) {
+        mbedtls_printf("failed\n");
+    }
 
 exit:
-    mbedtls_sha512_free( &ctx );
-    mbedtls_free( buf );
+    mbedtls_sha512_free(&ctx);
+    mbedtls_free(buf);
 
-    return( ret );
+    return ret;
 }
 
+#if defined(MBEDTLS_SHA512_C)
+int mbedtls_sha512_self_test(int verbose)
+{
+    return mbedtls_sha512_common_self_test(verbose, 0);
+}
+#endif /* MBEDTLS_SHA512_C */
+
+#if defined(MBEDTLS_SHA384_C)
+int mbedtls_sha384_self_test(int verbose)
+{
+    return mbedtls_sha512_common_self_test(verbose, 1);
+}
+#endif /* MBEDTLS_SHA384_C */
+
 #undef ARRAY_LENGTH
 
 #endif /* MBEDTLS_SELF_TEST */
 
-#endif /* MBEDTLS_SHA512_C */
+#endif /* MBEDTLS_SHA512_C || MBEDTLS_SHA384_C */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_cache.c b/lib/libmbedtls/mbedtls/library/ssl_cache.c
index 32188cf..048c21d 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_cache.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_cache.c
@@ -25,319 +25,397 @@
 
 #if defined(MBEDTLS_SSL_CACHE_C)
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free      free
-#endif
 
 #include "mbedtls/ssl_cache.h"
-#include "mbedtls/ssl_internal.h"
+#include "ssl_misc.h"
 
 #include <string.h>
 
-void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache )
+void mbedtls_ssl_cache_init(mbedtls_ssl_cache_context *cache)
 {
-    memset( cache, 0, sizeof( mbedtls_ssl_cache_context ) );
+    memset(cache, 0, sizeof(mbedtls_ssl_cache_context));
 
     cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT;
     cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES;
 
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_init( &cache->mutex );
+    mbedtls_mutex_init(&cache->mutex);
 #endif
 }
 
-int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session )
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_cache_find_entry(mbedtls_ssl_cache_context *cache,
+                                unsigned char const *session_id,
+                                size_t session_id_len,
+                                mbedtls_ssl_cache_entry **dst)
 {
     int ret = 1;
 #if defined(MBEDTLS_HAVE_TIME)
-    mbedtls_time_t t = mbedtls_time( NULL );
+    mbedtls_time_t t = mbedtls_time(NULL);
 #endif
-    mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
-    mbedtls_ssl_cache_entry *cur, *entry;
+    mbedtls_ssl_cache_entry *cur;
 
-#if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_lock( &cache->mutex ) != 0 )
-        return( 1 );
-#endif
-
-    cur = cache->chain;
-    entry = NULL;
-
-    while( cur != NULL )
-    {
-        entry = cur;
-        cur = cur->next;
-
+    for (cur = cache->chain; cur != NULL; cur = cur->next) {
 #if defined(MBEDTLS_HAVE_TIME)
-        if( cache->timeout != 0 &&
-            (int) ( t - entry->timestamp ) > cache->timeout )
+        if (cache->timeout != 0 &&
+            (int) (t - cur->timestamp) > cache->timeout) {
             continue;
+        }
 #endif
 
-        if( session->id_len != entry->session.id_len ||
-            memcmp( session->id, entry->session.id,
-                    entry->session.id_len ) != 0 )
-        {
+        if (session_id_len != cur->session_id_len ||
+            memcmp(session_id, cur->session_id,
+                   cur->session_id_len) != 0) {
             continue;
         }
 
-        ret = mbedtls_ssl_session_copy( session, &entry->session );
-        if( ret != 0 )
-        {
-            ret = 1;
-            goto exit;
-        }
+        break;
+    }
 
-#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
-    defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-        /*
-         * Restore peer certificate (without rest of the original chain)
-         */
-        if( entry->peer_cert.p != NULL )
-        {
-            /* `session->peer_cert` is NULL after the call to
-             * mbedtls_ssl_session_copy(), because cache entries
-             * have the `peer_cert` field set to NULL. */
-
-            if( ( session->peer_cert = mbedtls_calloc( 1,
-                                 sizeof(mbedtls_x509_crt) ) ) == NULL )
-            {
-                ret = 1;
-                goto exit;
-            }
-
-            mbedtls_x509_crt_init( session->peer_cert );
-            if( mbedtls_x509_crt_parse( session->peer_cert, entry->peer_cert.p,
-                                entry->peer_cert.len ) != 0 )
-            {
-                mbedtls_free( session->peer_cert );
-                session->peer_cert = NULL;
-                ret = 1;
-                goto exit;
-            }
-        }
-#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-
+    if (cur != NULL) {
+        *dst = cur;
         ret = 0;
-        goto exit;
     }
 
-exit:
-#if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_unlock( &cache->mutex ) != 0 )
-        ret = 1;
-#endif
-
-    return( ret );
+    return ret;
 }
 
-int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session )
+
+int mbedtls_ssl_cache_get(void *data,
+                          unsigned char const *session_id,
+                          size_t session_id_len,
+                          mbedtls_ssl_session *session)
 {
     int ret = 1;
-#if defined(MBEDTLS_HAVE_TIME)
-    mbedtls_time_t t = mbedtls_time( NULL ), oldest = 0;
-    mbedtls_ssl_cache_entry *old = NULL;
-#endif
     mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
-    mbedtls_ssl_cache_entry *cur, *prv;
-    int count = 0;
+    mbedtls_ssl_cache_entry *entry;
 
 #if defined(MBEDTLS_THREADING_C)
-    if( ( ret = mbedtls_mutex_lock( &cache->mutex ) ) != 0 )
-        return( ret );
-#endif
-
-    cur = cache->chain;
-    prv = NULL;
-
-    while( cur != NULL )
-    {
-        count++;
-
-#if defined(MBEDTLS_HAVE_TIME)
-        if( cache->timeout != 0 &&
-            (int) ( t - cur->timestamp ) > cache->timeout )
-        {
-            cur->timestamp = t;
-            break; /* expired, reuse this slot, update timestamp */
-        }
-#endif
-
-        if( memcmp( session->id, cur->session.id, cur->session.id_len ) == 0 )
-            break; /* client reconnected, keep timestamp for session id */
-
-#if defined(MBEDTLS_HAVE_TIME)
-        if( oldest == 0 || cur->timestamp < oldest )
-        {
-            oldest = cur->timestamp;
-            old = cur;
-        }
-#endif
-
-        prv = cur;
-        cur = cur->next;
+    if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) {
+        return ret;
     }
-
-    if( cur == NULL )
-    {
-#if defined(MBEDTLS_HAVE_TIME)
-        /*
-         * Reuse oldest entry if max_entries reached
-         */
-        if( count >= cache->max_entries )
-        {
-            if( old == NULL )
-            {
-                ret = 1;
-                goto exit;
-            }
-
-            cur = old;
-        }
-#else /* MBEDTLS_HAVE_TIME */
-        /*
-         * Reuse first entry in chain if max_entries reached,
-         * but move to last place
-         */
-        if( count >= cache->max_entries )
-        {
-            if( cache->chain == NULL )
-            {
-                ret = 1;
-                goto exit;
-            }
-
-            cur = cache->chain;
-            cache->chain = cur->next;
-            cur->next = NULL;
-            prv->next = cur;
-        }
-#endif /* MBEDTLS_HAVE_TIME */
-        else
-        {
-            /*
-             * max_entries not reached, create new entry
-             */
-            cur = mbedtls_calloc( 1, sizeof(mbedtls_ssl_cache_entry) );
-            if( cur == NULL )
-            {
-                ret = 1;
-                goto exit;
-            }
-
-            if( prv == NULL )
-                cache->chain = cur;
-            else
-                prv->next = cur;
-        }
-
-#if defined(MBEDTLS_HAVE_TIME)
-        cur->timestamp = t;
 #endif
-    }
 
-#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
-    defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    /*
-     * If we're reusing an entry, free its certificate first
-     */
-    if( cur->peer_cert.p != NULL )
-    {
-        mbedtls_free( cur->peer_cert.p );
-        memset( &cur->peer_cert, 0, sizeof(mbedtls_x509_buf) );
-    }
-#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-
-    /* Copy the entire session; this temporarily makes a copy of the
-     * X.509 CRT structure even though we only want to store the raw CRT.
-     * This inefficiency will go away as soon as we implement on-demand
-     * parsing of CRTs, in which case there's no need for the `peer_cert`
-     * field anymore in the first place, and we're done after this call. */
-    ret = mbedtls_ssl_session_copy( &cur->session, session );
-    if( ret != 0 )
-    {
-        ret = 1;
+    ret = ssl_cache_find_entry(cache, session_id, session_id_len, &entry);
+    if (ret != 0) {
         goto exit;
     }
 
-#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
-    defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    /* If present, free the X.509 structure and only store the raw CRT data. */
-    if( cur->session.peer_cert != NULL )
-    {
-        cur->peer_cert.p =
-            mbedtls_calloc( 1, cur->session.peer_cert->raw.len );
-        if( cur->peer_cert.p == NULL )
-        {
-            ret = 1;
-            goto exit;
-        }
-
-        memcpy( cur->peer_cert.p,
-                cur->session.peer_cert->raw.p,
-                cur->session.peer_cert->raw.len );
-        cur->peer_cert.len = session->peer_cert->raw.len;
-
-        mbedtls_x509_crt_free( cur->session.peer_cert );
-        mbedtls_free( cur->session.peer_cert );
-        cur->session.peer_cert = NULL;
+    ret = mbedtls_ssl_session_load(session,
+                                   entry->session,
+                                   entry->session_len);
+    if (ret != 0) {
+        goto exit;
     }
-#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 
     ret = 0;
 
 exit:
 #if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_unlock( &cache->mutex ) != 0 )
-        ret = 1;
+    if (mbedtls_mutex_unlock(&cache->mutex) != 0) {
+        ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
+    }
 #endif
 
-    return( ret );
+    return ret;
+}
+
+/* zeroize a cache entry */
+static void ssl_cache_entry_zeroize(mbedtls_ssl_cache_entry *entry)
+{
+    if (entry == NULL) {
+        return;
+    }
+
+    /* zeroize and free session structure */
+    if (entry->session != NULL) {
+        mbedtls_platform_zeroize(entry->session, entry->session_len);
+        mbedtls_free(entry->session);
+    }
+
+    /* zeroize the whole entry structure */
+    mbedtls_platform_zeroize(entry, sizeof(mbedtls_ssl_cache_entry));
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_cache_pick_writing_slot(mbedtls_ssl_cache_context *cache,
+                                       unsigned char const *session_id,
+                                       size_t session_id_len,
+                                       mbedtls_ssl_cache_entry **dst)
+{
+#if defined(MBEDTLS_HAVE_TIME)
+    mbedtls_time_t t = mbedtls_time(NULL), oldest = 0;
+#endif /* MBEDTLS_HAVE_TIME */
+
+    mbedtls_ssl_cache_entry *old = NULL;
+    int count = 0;
+    mbedtls_ssl_cache_entry *cur, *last;
+
+    /* Check 1: Is there already an entry with the given session ID?
+     *
+     * If yes, overwrite it.
+     *
+     * If not, `count` will hold the size of the session cache
+     * at the end of this loop, and `last` will point to the last
+     * entry, both of which will be used later. */
+
+    last = NULL;
+    for (cur = cache->chain; cur != NULL; cur = cur->next) {
+        count++;
+        if (session_id_len == cur->session_id_len &&
+            memcmp(session_id, cur->session_id, cur->session_id_len) == 0) {
+            goto found;
+        }
+        last = cur;
+    }
+
+    /* Check 2: Is there an outdated entry in the cache?
+     *
+     * If so, overwrite it.
+     *
+     * If not, remember the oldest entry in `old` for later.
+     */
+
+#if defined(MBEDTLS_HAVE_TIME)
+    for (cur = cache->chain; cur != NULL; cur = cur->next) {
+        if (cache->timeout != 0 &&
+            (int) (t - cur->timestamp) > cache->timeout) {
+            goto found;
+        }
+
+        if (oldest == 0 || cur->timestamp < oldest) {
+            oldest = cur->timestamp;
+            old = cur;
+        }
+    }
+#endif /* MBEDTLS_HAVE_TIME */
+
+    /* Check 3: Is there free space in the cache? */
+
+    if (count < cache->max_entries) {
+        /* Create new entry */
+        cur = mbedtls_calloc(1, sizeof(mbedtls_ssl_cache_entry));
+        if (cur == NULL) {
+            return 1;
+        }
+
+        /* Append to the end of the linked list. */
+        if (last == NULL) {
+            cache->chain = cur;
+        } else {
+            last->next = cur;
+        }
+
+        goto found;
+    }
+
+    /* Last resort: The cache is full and doesn't contain any outdated
+     * elements. In this case, we evict the oldest one, judged by timestamp
+     * (if present) or cache-order. */
+
+#if defined(MBEDTLS_HAVE_TIME)
+    if (old == NULL) {
+        /* This should only happen on an ill-configured cache
+         * with max_entries == 0. */
+        return 1;
+    }
+#else /* MBEDTLS_HAVE_TIME */
+    /* Reuse first entry in chain, but move to last place. */
+    if (cache->chain == NULL) {
+        return 1;
+    }
+
+    old = cache->chain;
+    cache->chain = old->next;
+    old->next = NULL;
+    last->next = old;
+#endif /* MBEDTLS_HAVE_TIME */
+
+    /* Now `old` points to the oldest entry to be overwritten. */
+    cur = old;
+
+found:
+
+    /* If we're reusing an entry, free it first. */
+    if (cur->session != NULL) {
+        /* `ssl_cache_entry_zeroize` would break the chain,
+         * so we reuse `old` to record `next` temporarily. */
+        old = cur->next;
+        ssl_cache_entry_zeroize(cur);
+        cur->next = old;
+    }
+
+#if defined(MBEDTLS_HAVE_TIME)
+    cur->timestamp = t;
+#endif
+
+    *dst = cur;
+    return 0;
+}
+
+int mbedtls_ssl_cache_set(void *data,
+                          unsigned char const *session_id,
+                          size_t session_id_len,
+                          const mbedtls_ssl_session *session)
+{
+    int ret = 1;
+    mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
+    mbedtls_ssl_cache_entry *cur;
+
+    size_t session_serialized_len;
+    unsigned char *session_serialized = NULL;
+
+#if defined(MBEDTLS_THREADING_C)
+    if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) {
+        return ret;
+    }
+#endif
+
+    ret = ssl_cache_pick_writing_slot(cache,
+                                      session_id, session_id_len,
+                                      &cur);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    /* Check how much space we need to serialize the session
+     * and allocate a sufficiently large buffer. */
+    ret = mbedtls_ssl_session_save(session, NULL, 0, &session_serialized_len);
+    if (ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) {
+        ret = 1;
+        goto exit;
+    }
+
+    session_serialized = mbedtls_calloc(1, session_serialized_len);
+    if (session_serialized == NULL) {
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        goto exit;
+    }
+
+    /* Now serialize the session into the allocated buffer. */
+    ret = mbedtls_ssl_session_save(session,
+                                   session_serialized,
+                                   session_serialized_len,
+                                   &session_serialized_len);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    if (session_id_len > sizeof(cur->session_id)) {
+        ret = 1;
+        goto exit;
+    }
+    cur->session_id_len = session_id_len;
+    memcpy(cur->session_id, session_id, session_id_len);
+
+    cur->session = session_serialized;
+    cur->session_len = session_serialized_len;
+    session_serialized = NULL;
+
+    ret = 0;
+
+exit:
+#if defined(MBEDTLS_THREADING_C)
+    if (mbedtls_mutex_unlock(&cache->mutex) != 0) {
+        ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
+    }
+#endif
+
+    if (session_serialized != NULL) {
+        mbedtls_platform_zeroize(session_serialized, session_serialized_len);
+        mbedtls_free(session_serialized);
+        session_serialized = NULL;
+    }
+
+    return ret;
+}
+
+int mbedtls_ssl_cache_remove(void *data,
+                             unsigned char const *session_id,
+                             size_t session_id_len)
+{
+    int ret = 1;
+    mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
+    mbedtls_ssl_cache_entry *entry;
+    mbedtls_ssl_cache_entry *prev;
+
+#if defined(MBEDTLS_THREADING_C)
+    if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) {
+        return ret;
+    }
+#endif
+
+    ret = ssl_cache_find_entry(cache, session_id, session_id_len, &entry);
+    /* No valid entry found, exit with success */
+    if (ret != 0) {
+        ret = 0;
+        goto exit;
+    }
+
+    /* Now we remove the entry from the chain */
+    if (entry == cache->chain) {
+        cache->chain = entry->next;
+        goto free;
+    }
+    for (prev = cache->chain; prev->next != NULL; prev = prev->next) {
+        if (prev->next == entry) {
+            prev->next = entry->next;
+            break;
+        }
+    }
+
+free:
+    ssl_cache_entry_zeroize(entry);
+    mbedtls_free(entry);
+    ret = 0;
+
+exit:
+#if defined(MBEDTLS_THREADING_C)
+    if (mbedtls_mutex_unlock(&cache->mutex) != 0) {
+        ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
+    }
+#endif
+
+    return ret;
 }
 
 #if defined(MBEDTLS_HAVE_TIME)
-void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout )
+void mbedtls_ssl_cache_set_timeout(mbedtls_ssl_cache_context *cache, int timeout)
 {
-    if( timeout < 0 ) timeout = 0;
+    if (timeout < 0) {
+        timeout = 0;
+    }
 
     cache->timeout = timeout;
 }
 #endif /* MBEDTLS_HAVE_TIME */
 
-void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max )
+void mbedtls_ssl_cache_set_max_entries(mbedtls_ssl_cache_context *cache, int max)
 {
-    if( max < 0 ) max = 0;
+    if (max < 0) {
+        max = 0;
+    }
 
     cache->max_entries = max;
 }
 
-void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache )
+void mbedtls_ssl_cache_free(mbedtls_ssl_cache_context *cache)
 {
     mbedtls_ssl_cache_entry *cur, *prv;
 
     cur = cache->chain;
 
-    while( cur != NULL )
-    {
+    while (cur != NULL) {
         prv = cur;
         cur = cur->next;
 
-        mbedtls_ssl_session_free( &prv->session );
-
-#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
-    defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-        mbedtls_free( prv->peer_cert.p );
-#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-
-        mbedtls_free( prv );
+        ssl_cache_entry_zeroize(prv);
+        mbedtls_free(prv);
     }
 
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_free( &cache->mutex );
+    mbedtls_mutex_free(&cache->mutex);
 #endif
     cache->chain = NULL;
 }
diff --git a/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c b/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c
index ceec77e..501608a 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c
@@ -23,26 +23,20 @@
 
 #if defined(MBEDTLS_SSL_TLS_C)
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#endif
 
 #include "mbedtls/ssl_ciphersuites.h"
 #include "mbedtls/ssl.h"
+#include "ssl_misc.h"
+
+#include "mbedtls/legacy_or_psa.h"
 
 #include <string.h>
 
-#undef HAVE_SHA384
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
-#define HAVE_SHA384
-#endif
-
 /*
  * Ordered from most preferred to least preferred in terms of security.
  *
- * Current rule (except RC4 and 3DES, weak and null which come last):
+ * Current rule (except weak and null which come last):
  * 1. By key exchange:
  *    Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK
  * 2. By key length and cipher:
@@ -56,6 +50,15 @@
 #if defined(MBEDTLS_SSL_CIPHERSUITES)
     MBEDTLS_SSL_CIPHERSUITES,
 #else
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    /* TLS 1.3 ciphersuites */
+    MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256,
+    MBEDTLS_TLS1_3_AES_256_GCM_SHA384,
+    MBEDTLS_TLS1_3_AES_128_GCM_SHA256,
+    MBEDTLS_TLS1_3_AES_128_CCM_SHA256,
+    MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256,
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
     /* Chacha-Poly ephemeral suites */
     MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
     MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
@@ -259,34 +262,6 @@
     MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
     MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
 
-    /* 3DES suites */
-    MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
-    MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
-    MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
-    MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
-    MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
-    MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
-    MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
-    MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
-    MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
-    MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
-
-    /* RC4 suites */
-    MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
-    MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA,
-    MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA,
-    MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA,
-    MBEDTLS_TLS_RSA_WITH_RC4_128_SHA,
-    MBEDTLS_TLS_RSA_WITH_RC4_128_MD5,
-    MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA,
-    MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
-    MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA,
-    MBEDTLS_TLS_PSK_WITH_RC4_128_SHA,
-
-    /* Weak suites */
-    MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA,
-    MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA,
-
     /* NULL suites */
     MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA,
     MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA,
@@ -315,1325 +290,1043 @@
 
 static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
 {
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+#if defined(MBEDTLS_AES_C)
+#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS1_3_AES_256_GCM_SHA384, "TLS1-3-AES-256-GCM-SHA384",
+      MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384,
+      MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS1_3_AES_128_GCM_SHA256, "TLS1-3-AES-128-GCM-SHA256",
+      MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256,
+      MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_GCM_C */
+#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS1_3_AES_128_CCM_SHA256, "TLS1-3-AES-128-CCM-SHA256",
+      MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256,
+      MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 },
+    { MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256, "TLS1-3-AES-128-CCM-8-SHA256",
+      MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256,
+      MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */
+      MBEDTLS_CIPHERSUITE_SHORT_TAG,
+      MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA && MBEDTLS_CCM_C */
+#endif /* MBEDTLS_AES_C */
+#if defined(MBEDTLS_CHACHAPOLY_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256,
+      "TLS1-3-CHACHA20-POLY1305-SHA256",
+      MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
+      MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 },
+#endif /* MBEDTLS_CHACHAPOLY_C && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
 #if defined(MBEDTLS_CHACHAPOLY_C) && \
-    defined(MBEDTLS_SHA256_C) && \
+    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
     defined(MBEDTLS_SSL_PROTO_TLS1_2)
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
       "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
       MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
       MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
       "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256",
       MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
       MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
     { MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
       "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256",
       MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
       MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
     { MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
       "TLS-PSK-WITH-CHACHA20-POLY1305-SHA256",
       MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
       MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
     { MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
       "TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256",
       MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
       MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
     { MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
       "TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256",
       MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
       MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
     { MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,
       "TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256",
       MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
       MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 #endif /* MBEDTLS_CHACHAPOLY_C &&
-          MBEDTLS_SHA256_C &&
+          MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA &&
           MBEDTLS_SSL_PROTO_TLS1_2 */
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
 #if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_SHA1_C */
-#if defined(MBEDTLS_SHA256_C)
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #if defined(MBEDTLS_GCM_C)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_SHA256_C */
-#if defined(HAVE_SHA384)
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #if defined(MBEDTLS_GCM_C)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_GCM_C */
-#endif /* HAVE_SHA384 */
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #if defined(MBEDTLS_CCM_C)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM",
       MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8",
       MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_SHORT_TAG },
+      MBEDTLS_CIPHERSUITE_SHORT_TAG,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM",
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8",
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_SHORT_TAG },
+      MBEDTLS_CIPHERSUITE_SHORT_TAG,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CCM_C */
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_CAMELLIA_C)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA256_C)
-    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256",
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+      "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
-#if defined(HAVE_SHA384)
-    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384",
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+      "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_SHA256_C)
-    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256",
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
+      "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
-#if defined(HAVE_SHA384)
-    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384",
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
+      "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
-#if defined(MBEDTLS_DES_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA",
-      MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_DES_C */
-
-#if defined(MBEDTLS_ARC4_C)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA",
-      MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_NODTLS },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_ARC4_C */
-
 #if defined(MBEDTLS_CIPHER_NULL_CIPHER)
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
-#endif /* MBEDTLS_SHA1_C */
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_NULL_CIPHER */
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
 #if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_SHA1_C */
-#if defined(MBEDTLS_SHA256_C)
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #if defined(MBEDTLS_GCM_C)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_SHA256_C */
-#if defined(HAVE_SHA384)
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #if defined(MBEDTLS_GCM_C)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_GCM_C */
-#endif /* HAVE_SHA384 */
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_CAMELLIA_C)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA256_C)
-    { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256",
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+      "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
-#if defined(HAVE_SHA384)
-    { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384",
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
+      "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_SHA256_C)
-    { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256",
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+      "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
-#if defined(HAVE_SHA384)
-    { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384",
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+      "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
-#if defined(MBEDTLS_DES_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA",
-      MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_DES_C */
-
-#if defined(MBEDTLS_ARC4_C)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS-ECDHE-RSA-WITH-RC4-128-SHA",
-      MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_NODTLS },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_ARC4_C */
-
 #if defined(MBEDTLS_CIPHER_NULL_CIPHER)
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
-#endif /* MBEDTLS_SHA1_C */
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_NULL_CIPHER */
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
 #if defined(MBEDTLS_AES_C)
-#if defined(HAVE_SHA384) && defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
+    defined(MBEDTLS_GCM_C)
     { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 && MBEDTLS_GCM_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA && MBEDTLS_GCM_C */
 
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_GCM_C)
     { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_GCM_C */
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 
     { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_SHA256_C */
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 
     { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA1_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #if defined(MBEDTLS_CCM_C)
     { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM",
       MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8",
       MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_SHORT_TAG },
+      MBEDTLS_CIPHERSUITE_SHORT_TAG,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM",
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8",
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_SHORT_TAG },
+      MBEDTLS_CIPHERSUITE_SHORT_TAG,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CCM_C */
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_CAMELLIA_C)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 
     { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 
     { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA1_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
-#if defined(MBEDTLS_DES_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA",
-      MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_DES_C */
 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
 #if defined(MBEDTLS_AES_C)
-#if defined(HAVE_SHA384) && defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
+    defined(MBEDTLS_GCM_C)
     { MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 && MBEDTLS_GCM_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA && MBEDTLS_GCM_C */
 
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_GCM_C)
     { MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_GCM_C */
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 
     { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_SHA256_C */
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 
     { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_SHA1_C */
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #if defined(MBEDTLS_CCM_C)
     { MBEDTLS_TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM",
       MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8",
       MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_SHORT_TAG },
+      MBEDTLS_CIPHERSUITE_SHORT_TAG,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM",
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8",
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_SHORT_TAG },
+      MBEDTLS_CIPHERSUITE_SHORT_TAG,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CCM_C */
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_CAMELLIA_C)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 
     { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 
     { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA1_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
-#if defined(MBEDTLS_DES_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-WITH-3DES-EDE-CBC-SHA",
-      MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_DES_C */
-
-#if defined(MBEDTLS_ARC4_C)
-#if defined(MBEDTLS_MD5_C)
-    { MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, "TLS-RSA-WITH-RC4-128-MD5",
-      MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_NODTLS },
-#endif
-
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, "TLS-RSA-WITH-RC4-128-SHA",
-      MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_NODTLS },
-#endif
-#endif /* MBEDTLS_ARC4_C */
 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)
 #if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_SHA1_C */
-#if defined(MBEDTLS_SHA256_C)
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #if defined(MBEDTLS_GCM_C)
     { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_SHA256_C */
-#if defined(HAVE_SHA384)
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #if defined(MBEDTLS_GCM_C)
     { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_GCM_C */
-#endif /* HAVE_SHA384 */
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_CAMELLIA_C)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA256_C)
-    { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256",
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+      "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
-#if defined(HAVE_SHA384)
-    { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384",
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
+      "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_SHA256_C)
-    { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256",
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+      "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
-#if defined(HAVE_SHA384)
-    { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384",
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+      "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
-#if defined(MBEDTLS_DES_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA",
-      MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_DES_C */
-
-#if defined(MBEDTLS_ARC4_C)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, "TLS-ECDH-RSA-WITH-RC4-128-SHA",
-      MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_NODTLS },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_ARC4_C */
-
 #if defined(MBEDTLS_CIPHER_NULL_CIPHER)
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
-#endif /* MBEDTLS_SHA1_C */
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_NULL_CIPHER */
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
 #if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_SHA1_C */
-#if defined(MBEDTLS_SHA256_C)
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #if defined(MBEDTLS_GCM_C)
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_SHA256_C */
-#if defined(HAVE_SHA384)
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #if defined(MBEDTLS_GCM_C)
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_GCM_C */
-#endif /* HAVE_SHA384 */
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_CAMELLIA_C)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA256_C)
-    { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256",
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+      "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
-#if defined(HAVE_SHA384)
-    { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384",
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+      "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_SHA256_C)
-    { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256",
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
+      "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
-#if defined(HAVE_SHA384)
-    { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384",
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
+      "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
-#if defined(MBEDTLS_DES_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA",
-      MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_DES_C */
-
-#if defined(MBEDTLS_ARC4_C)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "TLS-ECDH-ECDSA-WITH-RC4-128-SHA",
-      MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_NODTLS },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_ARC4_C */
-
 #if defined(MBEDTLS_CIPHER_NULL_CIPHER)
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
-#endif /* MBEDTLS_SHA1_C */
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_NULL_CIPHER */
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
 #if defined(MBEDTLS_AES_C)
 #if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_GCM_C */
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 
     { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA1_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #if defined(MBEDTLS_CCM_C)
     { MBEDTLS_TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM",
       MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8",
       MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_SHORT_TAG },
+      MBEDTLS_CIPHERSUITE_SHORT_TAG,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM",
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8",
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_SHORT_TAG },
+      MBEDTLS_CIPHERSUITE_SHORT_TAG,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CCM_C */
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_CAMELLIA_C)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
-#if defined(MBEDTLS_DES_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-PSK-WITH-3DES-EDE-CBC-SHA",
-      MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_DES_C */
-
-#if defined(MBEDTLS_ARC4_C)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, "TLS-PSK-WITH-RC4-128-SHA",
-      MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_NODTLS },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_ARC4_C */
 #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
 #if defined(MBEDTLS_AES_C)
 #if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_GCM_C */
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 
     { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA1_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #if defined(MBEDTLS_CCM_C)
     { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM",
       MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8",
       MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_SHORT_TAG },
+      MBEDTLS_CIPHERSUITE_SHORT_TAG,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM",
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
     { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8",
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_SHORT_TAG },
+      MBEDTLS_CIPHERSUITE_SHORT_TAG,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CCM_C */
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_CAMELLIA_C)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
-#if defined(MBEDTLS_DES_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA",
-      MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_DES_C */
-
-#if defined(MBEDTLS_ARC4_C)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, "TLS-DHE-PSK-WITH-RC4-128-SHA",
-      MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_NODTLS },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_ARC4_C */
 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
 #if defined(MBEDTLS_AES_C)
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 
     { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA1_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_CAMELLIA_C)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA256_C)
-    { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256",
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+      "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(HAVE_SHA384)
-    { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384",
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+      "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #endif /* MBEDTLS_CAMELLIA_C */
 
-#if defined(MBEDTLS_DES_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA",
-      MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_DES_C */
-
-#if defined(MBEDTLS_ARC4_C)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, "TLS-ECDHE-PSK-WITH-RC4-128-SHA",
-      MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_NODTLS },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_ARC4_C */
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
 #if defined(MBEDTLS_AES_C)
 #if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_GCM_C */
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 
     { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA1_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_CAMELLIA_C)
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA256_C */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* HAVE_SHA384 */
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_GCM_C */
 #endif /* MBEDTLS_CAMELLIA_C */
 
-#if defined(MBEDTLS_DES_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA",
-      MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_DES_C */
-
-#if defined(MBEDTLS_ARC4_C)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, "TLS-RSA-PSK-WITH-RC4-128-SHA",
-      MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_NODTLS },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_ARC4_C */
 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
@@ -1641,523 +1334,463 @@
 #if defined(MBEDTLS_CCM_C)
     { MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, "TLS-ECJPAKE-WITH-AES-128-CCM-8",
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECJPAKE,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_SHORT_TAG },
+      MBEDTLS_CIPHERSUITE_SHORT_TAG,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif /* MBEDTLS_CCM_C */
 #endif /* MBEDTLS_AES_C */
 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
-#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES)
 #if defined(MBEDTLS_CIPHER_NULL_CIPHER)
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
-#if defined(MBEDTLS_MD5_C)
+#if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
-#endif /* MBEDTLS_SHA1_C */
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
-#endif
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
-#endif /* MBEDTLS_SHA1_C */
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
-#endif
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
-#endif /* MBEDTLS_SHA1_C */
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
-#endif
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
-#endif /* MBEDTLS_SHA1_C */
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
-#if defined(HAVE_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
-#endif
+      MBEDTLS_CIPHERSUITE_WEAK,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
 #endif /* MBEDTLS_CIPHER_NULL_CIPHER */
 
-#if defined(MBEDTLS_DES_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS-DHE-RSA-WITH-DES-CBC-SHA",
-      MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
-#if defined(MBEDTLS_SHA1_C)
-    { MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, "TLS-RSA-WITH-DES-CBC-SHA",
-      MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_CIPHERSUITE_WEAK },
-#endif /* MBEDTLS_SHA1_C */
-#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_DES_C */
-#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */
-
 #if defined(MBEDTLS_ARIA_C)
 
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
-             "TLS-RSA-WITH-ARIA-256-GCM-SHA384",
+      "TLS-RSA-WITH-ARIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
-             "TLS-RSA-WITH-ARIA-256-CBC-SHA384",
+      "TLS-RSA-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
-             "TLS-RSA-WITH-ARIA-128-GCM-SHA256",
+      "TLS-RSA-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
-             "TLS-RSA-WITH-ARIA-128-CBC-SHA256",
+      "TLS-RSA-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
-             "TLS-RSA-PSK-WITH-ARIA-256-GCM-SHA384",
+      "TLS-RSA-PSK-WITH-ARIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
-             "TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384",
+      "TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
-             "TLS-RSA-PSK-WITH-ARIA-128-GCM-SHA256",
+      "TLS-RSA-PSK-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
-             "TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256",
+      "TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
-             "TLS-PSK-WITH-ARIA-256-GCM-SHA384",
-      MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384,MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      "TLS-PSK-WITH-ARIA-256-GCM-SHA384",
+      MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
-             "TLS-PSK-WITH-ARIA-256-CBC-SHA384",
+      "TLS-PSK-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
-             "TLS-PSK-WITH-ARIA-128-GCM-SHA256",
+      "TLS-PSK-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
-             "TLS-PSK-WITH-ARIA-128-CBC-SHA256",
+      "TLS-PSK-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
 #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
-             "TLS-ECDH-RSA-WITH-ARIA-256-GCM-SHA384",
+      "TLS-ECDH-RSA-WITH-ARIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
-             "TLS-ECDH-RSA-WITH-ARIA-256-CBC-SHA384",
+      "TLS-ECDH-RSA-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
-             "TLS-ECDH-RSA-WITH-ARIA-128-GCM-SHA256",
+      "TLS-ECDH-RSA-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
-             "TLS-ECDH-RSA-WITH-ARIA-128-CBC-SHA256",
+      "TLS-ECDH-RSA-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,
-             "TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384",
+      "TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
-             "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384",
+      "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,
-             "TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256",
+      "TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
-             "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256",
+      "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
 
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
-             "TLS-ECDHE-PSK-WITH-ARIA-256-CBC-SHA384",
+      "TLS-ECDHE-PSK-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
-             "TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256",
+      "TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,
-             "TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384",
+      "TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
-             "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384",
+      "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
-             "TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256",
+      "TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
-             "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256",
+      "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
-             "TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384",
+      "TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
-             "TLS-ECDH-ECDSA-WITH-ARIA-256-CBC-SHA384",
+      "TLS-ECDH-ECDSA-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
-             "TLS-ECDH-ECDSA-WITH-ARIA-128-GCM-SHA256",
+      "TLS-ECDH-ECDSA-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
-             "TLS-ECDH-ECDSA-WITH-ARIA-128-CBC-SHA256",
+      "TLS-ECDH-ECDSA-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,
-             "TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384",
+      "TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
-             "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384",
+      "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,
-             "TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256",
+      "TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
-             "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256",
+      "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,
-             "TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384",
+      "TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
-             "TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384",
+      "TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,
-             "TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256",
+      "TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C))
+#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
+    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
     { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
-             "TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256",
+      "TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3,
-      0 },
+      0,
+      MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
@@ -2167,60 +1800,44 @@
 
     { 0, "",
       MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE,
-      0, 0, 0, 0, 0 }
+      0, 0, 0 }
 };
 
 #if defined(MBEDTLS_SSL_CIPHERSUITES)
-const int *mbedtls_ssl_list_ciphersuites( void )
+const int *mbedtls_ssl_list_ciphersuites(void)
 {
-    return( ciphersuite_preference );
+    return ciphersuite_preference;
 }
 #else
-#define MAX_CIPHERSUITES    sizeof( ciphersuite_definitions     ) /         \
-                            sizeof( ciphersuite_definitions[0]  )
+#define MAX_CIPHERSUITES    sizeof(ciphersuite_definitions) /         \
+    sizeof(ciphersuite_definitions[0])
 static int supported_ciphersuites[MAX_CIPHERSUITES];
 static int supported_init = 0;
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ciphersuite_is_removed( const mbedtls_ssl_ciphersuite_t *cs_info )
+static int ciphersuite_is_removed(const mbedtls_ssl_ciphersuite_t *cs_info)
 {
-    (void)cs_info;
+    (void) cs_info;
 
-#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES)
-    if( cs_info->cipher == MBEDTLS_CIPHER_ARC4_128 )
-        return( 1 );
-#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */
-
-#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES)
-    if( cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_ECB ||
-        cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_CBC )
-    {
-        return( 1 );
-    }
-#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */
-
-    return( 0 );
+    return 0;
 }
 
-const int *mbedtls_ssl_list_ciphersuites( void )
+const int *mbedtls_ssl_list_ciphersuites(void)
 {
     /*
      * On initial call filter out all ciphersuites not supported by current
      * build based on presence in the ciphersuite_definitions.
      */
-    if( supported_init == 0 )
-    {
+    if (supported_init == 0) {
         const int *p;
         int *q;
 
-        for( p = ciphersuite_preference, q = supported_ciphersuites;
+        for (p = ciphersuite_preference, q = supported_ciphersuites;
              *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1;
-             p++ )
-        {
+             p++) {
             const mbedtls_ssl_ciphersuite_t *cs_info;
-            if( ( cs_info = mbedtls_ssl_ciphersuite_from_id( *p ) ) != NULL &&
-                !ciphersuite_is_removed( cs_info ) )
-            {
+            if ((cs_info = mbedtls_ssl_ciphersuite_from_id(*p)) != NULL &&
+                !ciphersuite_is_removed(cs_info)) {
                 *(q++) = *p;
             }
         }
@@ -2229,105 +1846,175 @@
         supported_init = 1;
     }
 
-    return( supported_ciphersuites );
+    return supported_ciphersuites;
 }
 #endif /* MBEDTLS_SSL_CIPHERSUITES */
 
 const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string(
-                                                const char *ciphersuite_name )
+    const char *ciphersuite_name)
 {
     const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions;
 
-    if( NULL == ciphersuite_name )
-        return( NULL );
+    if (NULL == ciphersuite_name) {
+        return NULL;
+    }
 
-    while( cur->id != 0 )
-    {
-        if( 0 == strcmp( cur->name, ciphersuite_name ) )
-            return( cur );
+    while (cur->id != 0) {
+        if (0 == strcmp(cur->name, ciphersuite_name)) {
+            return cur;
+        }
 
         cur++;
     }
 
-    return( NULL );
+    return NULL;
 }
 
-const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite )
+const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id(int ciphersuite)
 {
     const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions;
 
-    while( cur->id != 0 )
-    {
-        if( cur->id == ciphersuite )
-            return( cur );
+    while (cur->id != 0) {
+        if (cur->id == ciphersuite) {
+            return cur;
+        }
 
         cur++;
     }
 
-    return( NULL );
+    return NULL;
 }
 
-const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id )
+const char *mbedtls_ssl_get_ciphersuite_name(const int ciphersuite_id)
 {
     const mbedtls_ssl_ciphersuite_t *cur;
 
-    cur = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id );
+    cur = mbedtls_ssl_ciphersuite_from_id(ciphersuite_id);
 
-    if( cur == NULL )
-        return( "unknown" );
+    if (cur == NULL) {
+        return "unknown";
+    }
 
-    return( cur->name );
+    return cur->name;
 }
 
-int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name )
+int mbedtls_ssl_get_ciphersuite_id(const char *ciphersuite_name)
 {
     const mbedtls_ssl_ciphersuite_t *cur;
 
-    cur = mbedtls_ssl_ciphersuite_from_string( ciphersuite_name );
+    cur = mbedtls_ssl_ciphersuite_from_string(ciphersuite_name);
 
-    if( cur == NULL )
-        return( 0 );
+    if (cur == NULL) {
+        return 0;
+    }
 
-    return( cur->id );
+    return cur->id;
+}
+
+size_t mbedtls_ssl_ciphersuite_get_cipher_key_bitlen(const mbedtls_ssl_ciphersuite_t *info)
+{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_type_t key_type;
+    psa_algorithm_t alg;
+    size_t key_bits;
+
+    status = mbedtls_ssl_cipher_to_psa(info->cipher,
+                                       info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16,
+                                       &alg, &key_type, &key_bits);
+
+    if (status != PSA_SUCCESS) {
+        return 0;
+    }
+
+    return key_bits;
+#else
+    const mbedtls_cipher_info_t * const cipher_info =
+        mbedtls_cipher_info_from_type(info->cipher);
+
+    return mbedtls_cipher_info_get_key_bitlen(cipher_info);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 }
 
 #if defined(MBEDTLS_PK_C)
-mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info )
+mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg(const mbedtls_ssl_ciphersuite_t *info)
 {
-    switch( info->key_exchange )
-    {
+    switch (info->key_exchange) {
         case MBEDTLS_KEY_EXCHANGE_RSA:
         case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
         case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
         case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
-            return( MBEDTLS_PK_RSA );
+            return MBEDTLS_PK_RSA;
 
         case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
-            return( MBEDTLS_PK_ECDSA );
+            return MBEDTLS_PK_ECDSA;
 
         case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
         case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
-            return( MBEDTLS_PK_ECKEY );
+            return MBEDTLS_PK_ECKEY;
 
         default:
-            return( MBEDTLS_PK_NONE );
+            return MBEDTLS_PK_NONE;
     }
 }
 
-mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info )
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+psa_algorithm_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(const mbedtls_ssl_ciphersuite_t *info)
 {
-    switch( info->key_exchange )
-    {
+    switch (info->key_exchange) {
         case MBEDTLS_KEY_EXCHANGE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
+            return PSA_ALG_RSA_PKCS1V15_CRYPT;
         case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
         case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
-            return( MBEDTLS_PK_RSA );
+            return PSA_ALG_RSA_PKCS1V15_SIGN(
+                mbedtls_hash_info_psa_from_md(info->mac));
 
         case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
-            return( MBEDTLS_PK_ECDSA );
+            return PSA_ALG_ECDSA(mbedtls_hash_info_psa_from_md(info->mac));
+
+        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
+            return PSA_ALG_ECDH;
 
         default:
-            return( MBEDTLS_PK_NONE );
+            return PSA_ALG_NONE;
+    }
+}
+
+psa_key_usage_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(const mbedtls_ssl_ciphersuite_t *info)
+{
+    switch (info->key_exchange) {
+        case MBEDTLS_KEY_EXCHANGE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
+            return PSA_KEY_USAGE_DECRYPT;
+        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
+            return PSA_KEY_USAGE_SIGN_HASH;
+
+        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
+            return PSA_KEY_USAGE_DERIVE;
+
+        default:
+            return 0;
+    }
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg(const mbedtls_ssl_ciphersuite_t *info)
+{
+    switch (info->key_exchange) {
+        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
+            return MBEDTLS_PK_RSA;
+
+        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
+            return MBEDTLS_PK_ECDSA;
+
+        default:
+            return MBEDTLS_PK_NONE;
     }
 }
 
@@ -2335,37 +2022,35 @@
 
 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info )
+int mbedtls_ssl_ciphersuite_uses_ec(const mbedtls_ssl_ciphersuite_t *info)
 {
-    switch( info->key_exchange )
-    {
+    switch (info->key_exchange) {
         case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
         case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
         case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
         case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
         case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
         case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
-            return( 1 );
+            return 1;
 
         default:
-            return( 0 );
+            return 0;
     }
 }
 #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/
 
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
-int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info )
+int mbedtls_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info)
 {
-    switch( info->key_exchange )
-    {
+    switch (info->key_exchange) {
         case MBEDTLS_KEY_EXCHANGE_PSK:
         case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
         case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
         case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
-            return( 1 );
+            return 1;
 
         default:
-            return( 0 );
+            return 0;
     }
 }
 #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_cli.c b/lib/libmbedtls/mbedtls/library/ssl_cli.c
deleted file mode 100644
index 72351c9..0000000
--- a/lib/libmbedtls/mbedtls/library/ssl_cli.c
+++ /dev/null
@@ -1,4609 +0,0 @@
-/*
- *  SSLv3/TLSv1 client-side functions
- *
- *  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.
- */
-
-#include "common.h"
-
-#if defined(MBEDTLS_SSL_CLI_C)
-
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free      free
-#endif
-
-#include "mbedtls/ssl.h"
-#include "mbedtls/ssl_internal.h"
-#include "mbedtls/debug.h"
-#include "mbedtls/error.h"
-#include "mbedtls/constant_time.h"
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-#include "mbedtls/psa_util.h"
-#include "psa/crypto.h"
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-#include <string.h>
-
-#include <stdint.h>
-
-#if defined(MBEDTLS_HAVE_TIME)
-#include "mbedtls/platform_time.h"
-#endif
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-#include "mbedtls/platform_util.h"
-#endif
-
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_conf_has_static_psk( mbedtls_ssl_config const *conf )
-{
-    if( conf->psk_identity     == NULL ||
-        conf->psk_identity_len == 0     )
-    {
-        return( 0 );
-    }
-
-    if( conf->psk != NULL && conf->psk_len != 0 )
-        return( 1 );
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ! mbedtls_svc_key_id_is_null( conf->psk_opaque ) )
-        return( 1 );
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-    return( 0 );
-}
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_conf_has_static_raw_psk( mbedtls_ssl_config const *conf )
-{
-    if( conf->psk_identity     == NULL ||
-        conf->psk_identity_len == 0     )
-    {
-        return( 0 );
-    }
-
-    if( conf->psk != NULL && conf->psk_len != 0 )
-        return( 1 );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
-
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_hostname_ext( mbedtls_ssl_context *ssl,
-                                   unsigned char *buf,
-                                   const unsigned char *end,
-                                   size_t *olen )
-{
-    unsigned char *p = buf;
-    size_t hostname_len;
-
-    *olen = 0;
-
-    if( ssl->hostname == NULL )
-        return( 0 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3,
-        ( "client hello, adding server name extension: %s",
-          ssl->hostname ) );
-
-    hostname_len = strlen( ssl->hostname );
-
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, hostname_len + 9 );
-
-    /*
-     * Sect. 3, RFC 6066 (TLS Extensions Definitions)
-     *
-     * In order to provide any of the server names, clients MAY include an
-     * extension of type "server_name" in the (extended) client hello. The
-     * "extension_data" field of this extension SHALL contain
-     * "ServerNameList" where:
-     *
-     * struct {
-     *     NameType name_type;
-     *     select (name_type) {
-     *         case host_name: HostName;
-     *     } name;
-     * } ServerName;
-     *
-     * enum {
-     *     host_name(0), (255)
-     * } NameType;
-     *
-     * opaque HostName<1..2^16-1>;
-     *
-     * struct {
-     *     ServerName server_name_list<1..2^16-1>
-     * } ServerNameList;
-     *
-     */
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SERVERNAME, p, 0 );
-    p += 2;
-
-    MBEDTLS_PUT_UINT16_BE( hostname_len + 5, p, 0 );
-    p += 2;
-
-    MBEDTLS_PUT_UINT16_BE( hostname_len + 3, p, 0 );
-    p += 2;
-
-    *p++ = MBEDTLS_BYTE_0( MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME );
-
-    MBEDTLS_PUT_UINT16_BE( hostname_len, p, 0 );
-    p += 2;
-
-    memcpy( p, ssl->hostname, hostname_len );
-
-    *olen = hostname_len + 9;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
-                                        unsigned char *buf,
-                                        const unsigned char *end,
-                                        size_t *olen )
-{
-    unsigned char *p = buf;
-
-    *olen = 0;
-
-    /* We're always including an TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the
-     * initial ClientHello, in which case also adding the renegotiation
-     * info extension is NOT RECOMMENDED as per RFC 5746 Section 3.4. */
-    if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
-        return( 0 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3,
-        ( "client hello, adding renegotiation extension" ) );
-
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 5 + ssl->verify_data_len );
-
-    /*
-     * Secure renegotiation
-     */
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO, p, 0 );
-    p += 2;
-
-    *p++ = 0x00;
-    *p++ = MBEDTLS_BYTE_0( ssl->verify_data_len + 1 );
-    *p++ = MBEDTLS_BYTE_0( ssl->verify_data_len );
-
-    memcpy( p, ssl->own_verify_data, ssl->verify_data_len );
-
-    *olen = 5 + ssl->verify_data_len;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
-
-/*
- * Only if we handle at least one key exchange that needs signatures.
- */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
-    defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl,
-                                               unsigned char *buf,
-                                               const unsigned char *end,
-                                               size_t *olen )
-{
-    unsigned char *p = buf;
-    size_t sig_alg_len = 0;
-    const int *md;
-
-#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C)
-    unsigned char *sig_alg_list = buf + 6;
-#endif
-
-    *olen = 0;
-
-    if( ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 )
-        return( 0 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3,
-        ( "client hello, adding signature_algorithms extension" ) );
-
-    if( ssl->conf->sig_hashes == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_CONFIG );
-
-    for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ )
-    {
-#if defined(MBEDTLS_ECDSA_C)
-        sig_alg_len += 2;
-#endif
-#if defined(MBEDTLS_RSA_C)
-        sig_alg_len += 2;
-#endif
-        if( sig_alg_len > MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3,
-                ( "length in bytes of sig-hash-alg extension too big" ) );
-            return( MBEDTLS_ERR_SSL_BAD_CONFIG );
-        }
-    }
-
-    /* Empty signature algorithms list, this is a configuration error. */
-    if( sig_alg_len == 0 )
-        return( MBEDTLS_ERR_SSL_BAD_CONFIG );
-
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, sig_alg_len + 6 );
-
-    /*
-     * Prepare signature_algorithms extension (TLS 1.2)
-     */
-    sig_alg_len = 0;
-
-    for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ )
-    {
-#if defined(MBEDTLS_ECDSA_C)
-        sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md );
-        sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA;
-#endif
-#if defined(MBEDTLS_RSA_C)
-        sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md );
-        sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA;
-#endif
-    }
-
-    /*
-     * enum {
-     *     none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
-     *     sha512(6), (255)
-     * } HashAlgorithm;
-     *
-     * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
-     *   SignatureAlgorithm;
-     *
-     * struct {
-     *     HashAlgorithm hash;
-     *     SignatureAlgorithm signature;
-     * } SignatureAndHashAlgorithm;
-     *
-     * SignatureAndHashAlgorithm
-     *   supported_signature_algorithms<2..2^16-2>;
-     */
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SIG_ALG, p, 0 );
-    p += 2;
-
-    MBEDTLS_PUT_UINT16_BE( sig_alg_len + 2, p, 0 );
-    p += 2;
-
-    MBEDTLS_PUT_UINT16_BE( sig_alg_len, p, 0 );
-    p += 2;
-
-    *olen = 6 + sig_alg_len;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
-          MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
-
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl,
-                                                    unsigned char *buf,
-                                                    const unsigned char *end,
-                                                    size_t *olen )
-{
-    unsigned char *p = buf;
-    unsigned char *elliptic_curve_list = p + 6;
-    size_t elliptic_curve_len = 0;
-    const mbedtls_ecp_curve_info *info;
-    const mbedtls_ecp_group_id *grp_id;
-
-    *olen = 0;
-
-    MBEDTLS_SSL_DEBUG_MSG( 3,
-        ( "client hello, adding supported_elliptic_curves extension" ) );
-
-    if( ssl->conf->curve_list == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_CONFIG );
-
-    for( grp_id = ssl->conf->curve_list;
-         *grp_id != MBEDTLS_ECP_DP_NONE;
-         grp_id++ )
-    {
-        info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
-        if( info == NULL )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1,
-                ( "invalid curve in ssl configuration" ) );
-            return( MBEDTLS_ERR_SSL_BAD_CONFIG );
-        }
-        elliptic_curve_len += 2;
-
-        if( elliptic_curve_len > MBEDTLS_SSL_MAX_CURVE_LIST_LEN )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3,
-                ( "malformed supported_elliptic_curves extension in config" ) );
-            return( MBEDTLS_ERR_SSL_BAD_CONFIG );
-        }
-    }
-
-    /* Empty elliptic curve list, this is a configuration error. */
-    if( elliptic_curve_len == 0 )
-        return( MBEDTLS_ERR_SSL_BAD_CONFIG );
-
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 + elliptic_curve_len );
-
-    elliptic_curve_len = 0;
-
-    for( grp_id = ssl->conf->curve_list;
-         *grp_id != MBEDTLS_ECP_DP_NONE;
-         grp_id++ )
-    {
-        info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
-        elliptic_curve_list[elliptic_curve_len++] = MBEDTLS_BYTE_1( info->tls_id );
-        elliptic_curve_list[elliptic_curve_len++] = MBEDTLS_BYTE_0( info->tls_id );
-    }
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES, p, 0 );
-    p += 2;
-
-    MBEDTLS_PUT_UINT16_BE( elliptic_curve_len + 2, p, 0 );
-    p += 2;
-
-    MBEDTLS_PUT_UINT16_BE( elliptic_curve_len, p, 0 );
-    p += 2;
-
-    *olen = 6 + elliptic_curve_len;
-
-    return( 0 );
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl,
-                                                  unsigned char *buf,
-                                                  const unsigned char *end,
-                                                  size_t *olen )
-{
-    unsigned char *p = buf;
-    (void) ssl; /* ssl used for debugging only */
-
-    *olen = 0;
-
-    MBEDTLS_SSL_DEBUG_MSG( 3,
-        ( "client hello, adding supported_point_formats extension" ) );
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 );
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, p, 0 );
-    p += 2;
-
-    *p++ = 0x00;
-    *p++ = 2;
-
-    *p++ = 1;
-    *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED;
-
-    *olen = 6;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
-          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
-                                       unsigned char *buf,
-                                       const unsigned char *end,
-                                       size_t *olen )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char *p = buf;
-    size_t kkpp_len;
-
-    *olen = 0;
-
-    /* Skip costly extension if we can't use EC J-PAKE anyway */
-    if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 )
-        return( 0 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3,
-        ( "client hello, adding ecjpake_kkpp extension" ) );
-
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 );
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0 );
-    p += 2;
-
-    /*
-     * We may need to send ClientHello multiple times for Hello verification.
-     * We don't want to compute fresh values every time (both for performance
-     * and consistency reasons), so cache the extension content.
-     */
-    if( ssl->handshake->ecjpake_cache == NULL ||
-        ssl->handshake->ecjpake_cache_len == 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "generating new ecjpake parameters" ) );
-
-        ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx,
-                                               p + 2, end - p - 2, &kkpp_len,
-                                               ssl->conf->f_rng, ssl->conf->p_rng );
-        if( ret != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1 ,
-                "mbedtls_ecjpake_write_round_one", ret );
-            return( ret );
-        }
-
-        ssl->handshake->ecjpake_cache = mbedtls_calloc( 1, kkpp_len );
-        if( ssl->handshake->ecjpake_cache == NULL )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "allocation failed" ) );
-            return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
-        }
-
-        memcpy( ssl->handshake->ecjpake_cache, p + 2, kkpp_len );
-        ssl->handshake->ecjpake_cache_len = kkpp_len;
-    }
-    else
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "re-using cached ecjpake parameters" ) );
-
-        kkpp_len = ssl->handshake->ecjpake_cache_len;
-        MBEDTLS_SSL_CHK_BUF_PTR( p + 2, end, kkpp_len );
-
-        memcpy( p + 2, ssl->handshake->ecjpake_cache, kkpp_len );
-    }
-
-    MBEDTLS_PUT_UINT16_BE( kkpp_len, p, 0 );
-    p += 2;
-
-    *olen = kkpp_len + 4;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_cid_ext( mbedtls_ssl_context *ssl,
-                              unsigned char *buf,
-                              const unsigned char *end,
-                              size_t *olen )
-{
-    unsigned char *p = buf;
-    size_t ext_len;
-
-    /*
-     * Quoting draft-ietf-tls-dtls-connection-id-05
-     * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05
-     *
-     *   struct {
-     *      opaque cid<0..2^8-1>;
-     *   } ConnectionId;
-    */
-
-    *olen = 0;
-    if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
-        ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED )
-    {
-        return( 0 );
-    }
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding CID extension" ) );
-
-    /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX
-     * which is at most 255, so the increment cannot overflow. */
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, (unsigned)( ssl->own_cid_len + 5 ) );
-
-    /* Add extension ID + size */
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_CID, p, 0 );
-    p += 2;
-    ext_len = (size_t) ssl->own_cid_len + 1;
-    MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 );
-    p += 2;
-
-    *p++ = (uint8_t) ssl->own_cid_len;
-    memcpy( p, ssl->own_cid, ssl->own_cid_len );
-
-    *olen = ssl->own_cid_len + 5;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl,
-                                              unsigned char *buf,
-                                              const unsigned char *end,
-                                              size_t *olen )
-{
-    unsigned char *p = buf;
-
-    *olen = 0;
-
-    if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE )
-        return( 0 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3,
-        ( "client hello, adding max_fragment_length extension" ) );
-
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 5 );
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, p, 0 );
-    p += 2;
-
-    *p++ = 0x00;
-    *p++ = 1;
-
-    *p++ = ssl->conf->mfl_code;
-
-    *olen = 5;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
-
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl,
-                                         unsigned char *buf,
-                                         const unsigned char *end,
-                                         size_t *olen )
-{
-    unsigned char *p = buf;
-
-    *olen = 0;
-
-    if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED )
-        return( 0 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3,
-        ( "client hello, adding truncated_hmac extension" ) );
-
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 );
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_TRUNCATED_HMAC, p, 0 );
-    p += 2;
-
-    *p++ = 0x00;
-    *p++ = 0x00;
-
-    *olen = 4;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
-
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
-                                           unsigned char *buf,
-                                           const unsigned char *end,
-                                           size_t *olen )
-{
-    unsigned char *p = buf;
-
-    *olen = 0;
-
-    if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED ||
-        ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
-        return( 0 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3,
-        ( "client hello, adding encrypt_then_mac extension" ) );
-
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 );
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, p, 0 );
-    p += 2;
-
-    *p++ = 0x00;
-    *p++ = 0x00;
-
-    *olen = 4;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
-
-#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl,
-                                      unsigned char *buf,
-                                      const unsigned char *end,
-                                      size_t *olen )
-{
-    unsigned char *p = buf;
-
-    *olen = 0;
-
-    if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED ||
-        ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
-        return( 0 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3,
-        ( "client hello, adding extended_master_secret extension" ) );
-
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 );
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, p, 0 );
-    p += 2;
-
-    *p++ = 0x00;
-    *p++ = 0x00;
-
-    *olen = 4;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl,
-                                         unsigned char *buf,
-                                         const unsigned char *end,
-                                         size_t *olen )
-{
-    unsigned char *p = buf;
-    size_t tlen = ssl->session_negotiate->ticket_len;
-
-    *olen = 0;
-
-    if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED )
-        return( 0 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3,
-        ( "client hello, adding session ticket extension" ) );
-
-    /* The addition is safe here since the ticket length is 16 bit. */
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 + tlen );
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SESSION_TICKET, p, 0 );
-    p += 2;
-
-    MBEDTLS_PUT_UINT16_BE( tlen, p, 0 );
-    p += 2;
-
-    *olen = 4;
-
-    if( ssl->session_negotiate->ticket == NULL || tlen == 0 )
-        return( 0 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3,
-        ( "sending session ticket of length %" MBEDTLS_PRINTF_SIZET, tlen ) );
-
-    memcpy( p, ssl->session_negotiate->ticket, tlen );
-
-    *olen += tlen;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_SESSION_TICKETS */
-
-#if defined(MBEDTLS_SSL_ALPN)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
-                               unsigned char *buf,
-                               const unsigned char *end,
-                               size_t *olen )
-{
-    unsigned char *p = buf;
-    size_t alpnlen = 0;
-    const char **cur;
-
-    *olen = 0;
-
-    if( ssl->conf->alpn_list == NULL )
-        return( 0 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) );
-
-    for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ )
-        alpnlen += strlen( *cur ) + 1;
-
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 + alpnlen );
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ALPN, p, 0 );
-    p += 2;
-
-    /*
-     * opaque ProtocolName<1..2^8-1>;
-     *
-     * struct {
-     *     ProtocolName protocol_name_list<2..2^16-1>
-     * } ProtocolNameList;
-     */
-
-    /* Skip writing extension and list length for now */
-    p += 4;
-
-    for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ )
-    {
-        /*
-         * mbedtls_ssl_conf_set_alpn_protocols() checked that the length of
-         * protocol names is less than 255.
-         */
-        *p = (unsigned char)strlen( *cur );
-        memcpy( p + 1, *cur, *p );
-        p += 1 + *p;
-    }
-
-    *olen = p - buf;
-
-    /* List length = olen - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */
-    MBEDTLS_PUT_UINT16_BE( *olen - 6, buf, 4 );
-
-    /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */
-    MBEDTLS_PUT_UINT16_BE( *olen - 4, buf, 2 );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_ALPN */
-
-#if defined(MBEDTLS_SSL_DTLS_SRTP)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl,
-                                   unsigned char *buf,
-                                   const unsigned char *end,
-                                   size_t *olen )
-{
-    unsigned char *p = buf;
-    size_t protection_profiles_index = 0, ext_len = 0;
-    uint16_t mki_len = 0, profile_value = 0;
-
-    *olen = 0;
-
-    if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) ||
-        ( ssl->conf->dtls_srtp_profile_list == NULL ) ||
-        ( ssl->conf->dtls_srtp_profile_list_len == 0 ) )
-    {
-        return( 0 );
-    }
-
-    /* RFC 5764 section 4.1.1
-     * uint8 SRTPProtectionProfile[2];
-     *
-     * struct {
-     *   SRTPProtectionProfiles SRTPProtectionProfiles;
-     *   opaque srtp_mki<0..255>;
-     * } UseSRTPData;
-     * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>;
-     */
-    if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED )
-    {
-        mki_len = ssl->dtls_srtp_info.mki_len;
-    }
-    /* Extension length = 2 bytes for profiles length,
-     *                    ssl->conf->dtls_srtp_profile_list_len * 2 (each profile is 2 bytes length ),
-     *                    1 byte for srtp_mki vector length and the mki_len value
-     */
-    ext_len = 2 + 2 * ( ssl->conf->dtls_srtp_profile_list_len ) + 1 + mki_len;
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding use_srtp extension" ) );
-
-    /* Check there is room in the buffer for the extension + 4 bytes
-     * - the extension tag (2 bytes)
-     * - the extension length (2 bytes)
-     */
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, ext_len + 4 );
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_USE_SRTP, p, 0 );
-    p += 2;
-
-    MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 );
-    p += 2;
-
-    /* protection profile length: 2*(ssl->conf->dtls_srtp_profile_list_len) */
-    /* micro-optimization:
-     * the list size is limited to MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH
-     * which is lower than 127, so the upper byte of the length is always 0
-     * For the documentation, the more generic code is left in comments
-     * *p++ = (unsigned char)( ( ( 2 * ssl->conf->dtls_srtp_profile_list_len )
-     *                        >> 8 ) & 0xFF );
-     */
-    *p++ = 0;
-    *p++ = MBEDTLS_BYTE_0( 2 * ssl->conf->dtls_srtp_profile_list_len );
-
-    for( protection_profiles_index=0;
-         protection_profiles_index < ssl->conf->dtls_srtp_profile_list_len;
-         protection_profiles_index++ )
-    {
-        profile_value = mbedtls_ssl_check_srtp_profile_value
-                ( ssl->conf->dtls_srtp_profile_list[protection_profiles_index] );
-        if( profile_value != MBEDTLS_TLS_SRTP_UNSET )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_write_use_srtp_ext, add profile: %04x",
-                                        profile_value ) );
-            MBEDTLS_PUT_UINT16_BE( profile_value, p, 0 );
-            p += 2;
-        }
-        else
-        {
-            /*
-             * Note: we shall never arrive here as protection profiles
-             * is checked by mbedtls_ssl_conf_dtls_srtp_protection_profiles function
-             */
-            MBEDTLS_SSL_DEBUG_MSG( 3,
-                    ( "client hello, "
-                      "illegal DTLS-SRTP protection profile %d",
-                      ssl->conf->dtls_srtp_profile_list[protection_profiles_index]
-                    ) );
-            return( MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED );
-        }
-    }
-
-    *p++ = mki_len & 0xFF;
-
-    if( mki_len != 0 )
-    {
-        memcpy( p, ssl->dtls_srtp_info.mki_value, mki_len );
-        /*
-         * Increment p to point to the current position.
-         */
-        p += mki_len;
-        MBEDTLS_SSL_DEBUG_BUF( 3, "sending mki",  ssl->dtls_srtp_info.mki_value,
-                               ssl->dtls_srtp_info.mki_len );
-    }
-
-    /*
-     * total extension length: extension type (2 bytes)
-     *                         + extension length (2 bytes)
-     *                         + protection profile length (2 bytes)
-     *                         + 2 * number of protection profiles
-     *                         + srtp_mki vector length(1 byte)
-     *                         + mki value
-     */
-    *olen = p - buf;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_DTLS_SRTP */
-
-/*
- * Generate random bytes for ClientHello
- */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_generate_random( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char *p = ssl->handshake->randbytes;
-#if defined(MBEDTLS_HAVE_TIME)
-    mbedtls_time_t t;
-#endif
-
-    /*
-     * When responding to a verify request, MUST reuse random (RFC 6347 4.2.1)
-     */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ssl->handshake->verify_cookie != NULL )
-    {
-        return( 0 );
-    }
-#endif
-
-#if defined(MBEDTLS_HAVE_TIME)
-    t = mbedtls_time( NULL );
-    MBEDTLS_PUT_UINT32_BE( t, p, 0 );
-    p += 4;
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %" MBEDTLS_PRINTF_LONGLONG,
-                                (long long) t ) );
-#else
-    if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 )
-        return( ret );
-
-    p += 4;
-#endif /* MBEDTLS_HAVE_TIME */
-
-    if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 )
-        return( ret );
-
-    return( 0 );
-}
-
-/**
- * \brief           Validate cipher suite against config in SSL context.
- *
- * \param suite_info    cipher suite to validate
- * \param ssl           SSL context
- * \param min_minor_ver Minimal minor version to accept a cipher suite
- * \param max_minor_ver Maximal minor version to accept a cipher suite
- *
- * \return          0 if valid, else 1
- */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_validate_ciphersuite(
-    const mbedtls_ssl_ciphersuite_t * suite_info,
-    const mbedtls_ssl_context * ssl,
-    int min_minor_ver, int max_minor_ver )
-{
-    (void) ssl;
-    if( suite_info == NULL )
-        return( 1 );
-
-    if( suite_info->min_minor_ver > max_minor_ver ||
-            suite_info->max_minor_ver < min_minor_ver )
-        return( 1 );
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-            ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) )
-        return( 1 );
-#endif
-
-#if defined(MBEDTLS_ARC4_C)
-    if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED &&
-            suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 )
-        return( 1 );
-#endif
-
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE &&
-            mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 )
-        return( 1 );
-#endif
-
-    /* Don't suggest PSK-based ciphersuite if no PSK is available. */
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
-    if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) &&
-        ssl_conf_has_static_psk( ssl->conf ) == 0 )
-    {
-        return( 1 );
-    }
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
-
-    return( 0 );
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t i, n, olen, ext_len = 0;
-
-    unsigned char *buf;
-    unsigned char *p, *q;
-    const unsigned char *end;
-
-    unsigned char offer_compress;
-    const int *ciphersuites;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    int uses_ec = 0;
-#endif
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) );
-
-    if( ssl->conf->f_rng == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") );
-        return( MBEDTLS_ERR_SSL_NO_RNG );
-    }
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
-#endif
-    {
-        ssl->major_ver = ssl->conf->min_major_ver;
-        ssl->minor_ver = ssl->conf->min_minor_ver;
-    }
-
-    if( ssl->conf->max_major_ver == 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "configured max major version is invalid, consider using mbedtls_ssl_config_defaults()" ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-    }
-
-    buf = ssl->out_msg;
-    end = buf + MBEDTLS_SSL_OUT_CONTENT_LEN;
-
-    /*
-     * Check if there's enough space for the first part of the ClientHello
-     * consisting of the 38 bytes described below, the session identifier (at
-     * most 32 bytes) and its length (1 byte).
-     *
-     * Use static upper bounds instead of the actual values
-     * to allow the compiler to optimize this away.
-     */
-    MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 38 + 1 + 32 );
-
-    /*
-     * The 38 first bytes of the ClientHello:
-     *     0  .   0   handshake type (written later)
-     *     1  .   3   handshake length (written later)
-     *     4  .   5   highest version supported
-     *     6  .   9   current UNIX time
-     *    10  .  37   random bytes
-     *
-     * The current UNIX time (4 bytes) and following 28 random bytes are written
-     * by ssl_generate_random() into ssl->handshake->randbytes buffer and then
-     * copied from there into the output buffer.
-     */
-
-    p = buf + 4;
-    mbedtls_ssl_write_version( ssl->conf->max_major_ver,
-                               ssl->conf->max_minor_ver,
-                               ssl->conf->transport, p );
-    p += 2;
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]",
-                   buf[4], buf[5] ) );
-
-    if( ( ret = ssl_generate_random( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_generate_random", ret );
-        return( ret );
-    }
-
-    memcpy( p, ssl->handshake->randbytes, 32 );
-    MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", p, 32 );
-    p += 32;
-
-    /*
-     *    38  .  38   session id length
-     *    39  . 39+n  session id
-     *   39+n . 39+n  DTLS only: cookie length (1 byte)
-     *   40+n .  ..   DTLS only: cookie
-     *   ..   . ..    ciphersuitelist length (2 bytes)
-     *   ..   . ..    ciphersuitelist
-     *   ..   . ..    compression methods length (1 byte)
-     *   ..   . ..    compression methods
-     *   ..   . ..    extensions length (2 bytes)
-     *   ..   . ..    extensions
-     */
-    n = ssl->session_negotiate->id_len;
-
-    if( n < 16 || n > 32 ||
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-        ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ||
-#endif
-        ssl->handshake->resume == 0 )
-    {
-        n = 0;
-    }
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    /*
-     * RFC 5077 section 3.4: "When presenting a ticket, the client MAY
-     * generate and include a Session ID in the TLS ClientHello."
-     */
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
-#endif
-    {
-        if( ssl->session_negotiate->ticket != NULL &&
-                ssl->session_negotiate->ticket_len != 0 )
-        {
-            ret = ssl->conf->f_rng( ssl->conf->p_rng,
-                                    ssl->session_negotiate->id, 32 );
-
-            if( ret != 0 )
-                return( ret );
-
-            ssl->session_negotiate->id_len = n = 32;
-        }
-    }
-#endif /* MBEDTLS_SSL_SESSION_TICKETS */
-
-    /*
-     * The first check of the output buffer size above (
-     * MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 38 + 1 + 32 );)
-     * has checked that there is enough space in the output buffer for the
-     * session identifier length byte and the session identifier (n <= 32).
-     */
-    *p++ = (unsigned char) n;
-
-    for( i = 0; i < n; i++ )
-        *p++ = ssl->session_negotiate->id[i];
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n ) );
-    MBEDTLS_SSL_DEBUG_BUF( 3,   "client hello, session id", buf + 39, n );
-
-    /*
-     *   With 'n' being the length of the session identifier
-     *
-     *   39+n . 39+n  DTLS only: cookie length (1 byte)
-     *   40+n .  ..   DTLS only: cookie
-     *   ..   . ..    ciphersuitelist length (2 bytes)
-     *   ..   . ..    ciphersuitelist
-     *   ..   . ..    compression methods length (1 byte)
-     *   ..   . ..    compression methods
-     *   ..   . ..    extensions length (2 bytes)
-     *   ..   . ..    extensions
-     */
-
-    /*
-     * DTLS cookie
-     */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        MBEDTLS_SSL_CHK_BUF_PTR( p, end, 1 );
-
-        if( ssl->handshake->verify_cookie == NULL )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "no verify cookie to send" ) );
-            *p++ = 0;
-        }
-        else
-        {
-            MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie",
-                              ssl->handshake->verify_cookie,
-                              ssl->handshake->verify_cookie_len );
-
-            *p++ = ssl->handshake->verify_cookie_len;
-
-            MBEDTLS_SSL_CHK_BUF_PTR( p, end,
-                                     ssl->handshake->verify_cookie_len );
-            memcpy( p, ssl->handshake->verify_cookie,
-                       ssl->handshake->verify_cookie_len );
-            p += ssl->handshake->verify_cookie_len;
-        }
-    }
-#endif
-
-    /*
-     * Ciphersuite list
-     */
-    ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver];
-
-    /* Skip writing ciphersuite length for now */
-    n = 0;
-    q = p;
-
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
-    p += 2;
-
-    for( i = 0; ciphersuites[i] != 0; i++ )
-    {
-        ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] );
-
-        if( ssl_validate_ciphersuite( ciphersuite_info, ssl,
-                                      ssl->conf->min_minor_ver,
-                                      ssl->conf->max_minor_ver ) != 0 )
-            continue;
-
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %#04x (%s)",
-                                    (unsigned int)ciphersuites[i], ciphersuite_info->name ) );
-
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-        uses_ec |= mbedtls_ssl_ciphersuite_uses_ec( ciphersuite_info );
-#endif
-
-        MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
-
-        n++;
-        MBEDTLS_PUT_UINT16_BE( ciphersuites[i], p, 0 );
-        p += 2;
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3,
-        ( "client hello, got %" MBEDTLS_PRINTF_SIZET " ciphersuites (excluding SCSVs)", n ) );
-
-    /*
-     * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV
-     */
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
-#endif
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding EMPTY_RENEGOTIATION_INFO_SCSV" ) );
-        MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
-        MBEDTLS_PUT_UINT16_BE( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO, p, 0 );
-        p += 2;
-        n++;
-    }
-
-    /* Some versions of OpenSSL don't handle it correctly if not at end */
-#if defined(MBEDTLS_SSL_FALLBACK_SCSV)
-    if( ssl->conf->fallback == MBEDTLS_SSL_IS_FALLBACK )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding FALLBACK_SCSV" ) );
-
-        MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
-        MBEDTLS_PUT_UINT16_BE( MBEDTLS_SSL_FALLBACK_SCSV_VALUE, p, 0 );
-        p += 2;
-        n++;
-    }
-#endif
-
-    *q++ = (unsigned char)( n >> 7 );
-    *q++ = (unsigned char)( n << 1 );
-
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-    offer_compress = 1;
-#else
-    offer_compress = 0;
-#endif
-
-    /*
-     * We don't support compression with DTLS right now: if many records come
-     * in the same datagram, uncompressing one could overwrite the next one.
-     * We don't want to add complexity for handling that case unless there is
-     * an actual need for it.
-     */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-        offer_compress = 0;
-#endif
-
-    if( offer_compress )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) );
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d",
-                                    MBEDTLS_SSL_COMPRESS_DEFLATE,
-                                    MBEDTLS_SSL_COMPRESS_NULL ) );
-
-        MBEDTLS_SSL_CHK_BUF_PTR( p, end, 3 );
-        *p++ = 2;
-        *p++ = MBEDTLS_SSL_COMPRESS_DEFLATE;
-        *p++ = MBEDTLS_SSL_COMPRESS_NULL;
-    }
-    else
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) );
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d",
-                            MBEDTLS_SSL_COMPRESS_NULL ) );
-
-        MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
-        *p++ = 1;
-        *p++ = MBEDTLS_SSL_COMPRESS_NULL;
-    }
-
-    /* First write extensions, then the total length */
-
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
-
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-    if( ( ret = ssl_write_hostname_ext( ssl, p + 2 + ext_len,
-                                        end, &olen ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_hostname_ext", ret );
-        return( ret );
-    }
-    ext_len += olen;
-#endif
-
-    /* Note that TLS_EMPTY_RENEGOTIATION_INFO_SCSV is always added
-     * even if MBEDTLS_SSL_RENEGOTIATION is not defined. */
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ( ret = ssl_write_renegotiation_ext( ssl, p + 2 + ext_len,
-                                             end, &olen ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_renegotiation_ext", ret );
-        return( ret );
-    }
-    ext_len += olen;
-#endif
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
-    defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-    if( ( ret = ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len,
-                                                    end, &olen ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_signature_algorithms_ext", ret );
-        return( ret );
-    }
-    ext_len += olen;
-#endif
-
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    if( uses_ec )
-    {
-        if( ( ret = ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len,
-                                                             end, &olen ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_supported_elliptic_curves_ext", ret );
-            return( ret );
-        }
-        ext_len += olen;
-
-        if( ( ret = ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len,
-                                                           end, &olen ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_supported_point_formats_ext", ret );
-            return( ret );
-        }
-        ext_len += olen;
-    }
-#endif
-
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    if( ( ret = ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len,
-                                            end, &olen ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_ecjpake_kkpp_ext", ret );
-        return( ret );
-    }
-    ext_len += olen;
-#endif
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    if( ( ret = ssl_write_cid_ext( ssl, p + 2 + ext_len, end, &olen ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_cid_ext", ret );
-        return( ret );
-    }
-    ext_len += olen;
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-    if( ( ret = ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len,
-                                                   end, &olen ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_max_fragment_length_ext", ret );
-        return( ret );
-    }
-    ext_len += olen;
-#endif
-
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-    if( ( ret = ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len,
-                                              end, &olen ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_truncated_hmac_ext", ret );
-        return( ret );
-    }
-    ext_len += olen;
-#endif
-
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-    if( ( ret = ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len,
-                                                end, &olen ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_encrypt_then_mac_ext", ret );
-        return( ret );
-    }
-    ext_len += olen;
-#endif
-
-#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-    if( ( ret = ssl_write_extended_ms_ext( ssl, p + 2 + ext_len,
-                                           end, &olen ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_extended_ms_ext", ret );
-        return( ret );
-    }
-    ext_len += olen;
-#endif
-
-#if defined(MBEDTLS_SSL_ALPN)
-    if( ( ret = ssl_write_alpn_ext( ssl, p + 2 + ext_len,
-                                    end, &olen ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_alpn_ext", ret );
-        return( ret );
-    }
-    ext_len += olen;
-#endif
-
-#if defined(MBEDTLS_SSL_DTLS_SRTP)
-    if( ( ret = ssl_write_use_srtp_ext( ssl, p + 2 + ext_len,
-                                        end, &olen ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_use_srtp_ext", ret );
-        return( ret );
-    }
-    ext_len += olen;
-#endif
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    if( ( ret = ssl_write_session_ticket_ext( ssl, p + 2 + ext_len,
-                                              end, &olen ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_session_ticket_ext", ret );
-        return( ret );
-    }
-    ext_len += olen;
-#endif
-
-    /* olen unused if all extensions are disabled */
-    ((void) olen);
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %" MBEDTLS_PRINTF_SIZET,
-                                ext_len ) );
-
-    if( ext_len > 0 )
-    {
-        /* No need to check for space here, because the extension
-         * writing functions already took care of that. */
-        MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 );
-        p += 2 + ext_len;
-    }
-
-    ssl->out_msglen  = p - buf;
-    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
-    ssl->out_msg[0]  = MBEDTLS_SSL_HS_CLIENT_HELLO;
-
-    ssl->state++;
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-        mbedtls_ssl_send_flight_completed( ssl );
-#endif
-
-    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
-        return( ret );
-    }
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
-        return( ret );
-    }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) );
-
-    return( 0 );
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
-                                         const unsigned char *buf,
-                                         size_t len )
-{
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
-    {
-        /* Check verify-data in constant-time. The length OTOH is no secret */
-        if( len    != 1 + ssl->verify_data_len * 2 ||
-            buf[0] !=     ssl->verify_data_len * 2 ||
-            mbedtls_ct_memcmp( buf + 1,
-                          ssl->own_verify_data, ssl->verify_data_len ) != 0 ||
-            mbedtls_ct_memcmp( buf + 1 + ssl->verify_data_len,
-                          ssl->peer_verify_data, ssl->verify_data_len ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) );
-            mbedtls_ssl_send_alert_message(
-                ssl,
-                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-            return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-        }
-    }
-    else
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
-    {
-        if( len != 1 || buf[0] != 0x00 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1,
-                ( "non-zero length renegotiation info" ) );
-            mbedtls_ssl_send_alert_message(
-                ssl,
-                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-            return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-        }
-
-        ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION;
-    }
-
-    return( 0 );
-}
-
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl,
-                                              const unsigned char *buf,
-                                              size_t len )
-{
-    /*
-     * server should use the extension only if we did,
-     * and if so the server's value should match ours (and len is always 1)
-     */
-    if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ||
-        len != 1 ||
-        buf[0] != ssl->conf->mfl_code )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "non-matching max fragment length extension" ) );
-        mbedtls_ssl_send_alert_message(
-            ssl,
-            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
-
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl,
-                                         const unsigned char *buf,
-                                         size_t len )
-{
-    if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ||
-        len != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "non-matching truncated HMAC extension" ) );
-        mbedtls_ssl_send_alert_message(
-            ssl,
-            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    ((void) buf);
-
-    ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl,
-                              const unsigned char *buf,
-                              size_t len )
-{
-    size_t peer_cid_len;
-
-    if( /* CID extension only makes sense in DTLS */
-        ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
-        /* The server must only send the CID extension if we have offered it. */
-        ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension unexpected" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                     MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    if( len == 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                     MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    peer_cid_len = *buf++;
-    len--;
-
-    if( peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                     MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    if( len != peer_cid_len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                     MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED;
-    ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len;
-    memcpy( ssl->handshake->peer_cid, buf, peer_cid_len );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use of CID extension negotiated" ) );
-    MBEDTLS_SSL_DEBUG_BUF( 3, "Server CID", buf, peer_cid_len );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
-                                         const unsigned char *buf,
-                                         size_t len )
-{
-    if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED ||
-        ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ||
-        len != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "non-matching encrypt-then-MAC extension" ) );
-        mbedtls_ssl_send_alert_message(
-            ssl,
-            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    ((void) buf);
-
-    ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
-
-#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl,
-                                         const unsigned char *buf,
-                                         size_t len )
-{
-    if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED ||
-        ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ||
-        len != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "non-matching extended master secret extension" ) );
-        mbedtls_ssl_send_alert_message(
-            ssl,
-            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    ((void) buf);
-
-    ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
-                                         const unsigned char *buf,
-                                         size_t len )
-{
-    if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ||
-        len != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "non-matching session ticket extension" ) );
-        mbedtls_ssl_send_alert_message(
-            ssl,
-            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    ((void) buf);
-
-    ssl->handshake->new_session_ticket = 1;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_SESSION_TICKETS */
-
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl,
-                                                  const unsigned char *buf,
-                                                  size_t len )
-{
-    size_t list_size;
-    const unsigned char *p;
-
-    if( len == 0 || (size_t)( buf[0] + 1 ) != len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-    list_size = buf[0];
-
-    p = buf + 1;
-    while( list_size > 0 )
-    {
-        if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED ||
-            p[0] == MBEDTLS_ECP_PF_COMPRESSED )
-        {
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
-            ssl->handshake->ecdh_ctx.point_format = p[0];
-#endif
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-            ssl->handshake->ecjpake_ctx.point_format = p[0];
-#endif
-            MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) );
-            return( 0 );
-        }
-
-        list_size--;
-        p++;
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "no point format in common" ) );
-    mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                    MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-    return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-}
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
-          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
-                                   const unsigned char *buf,
-                                   size_t len )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    if( ssl->handshake->ciphersuite_info->key_exchange !=
-        MBEDTLS_KEY_EXCHANGE_ECJPAKE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) );
-        return( 0 );
-    }
-
-    /* If we got here, we no longer need our cached extension */
-    mbedtls_free( ssl->handshake->ecjpake_cache );
-    ssl->handshake->ecjpake_cache = NULL;
-    ssl->handshake->ecjpake_cache_len = 0;
-
-    if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx,
-                                                buf, len ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret );
-        mbedtls_ssl_send_alert_message(
-            ssl,
-            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-        return( ret );
-    }
-
-    return( 0 );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-
-#if defined(MBEDTLS_SSL_ALPN)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
-                               const unsigned char *buf, size_t len )
-{
-    size_t list_len, name_len;
-    const char **p;
-
-    /* If we didn't send it, the server shouldn't send it */
-    if( ssl->conf->alpn_list == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching ALPN extension" ) );
-        mbedtls_ssl_send_alert_message(
-            ssl,
-            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    /*
-     * opaque ProtocolName<1..2^8-1>;
-     *
-     * struct {
-     *     ProtocolName protocol_name_list<2..2^16-1>
-     * } ProtocolNameList;
-     *
-     * the "ProtocolNameList" MUST contain exactly one "ProtocolName"
-     */
-
-    /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */
-    if( len < 4 )
-    {
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    list_len = ( buf[0] << 8 ) | buf[1];
-    if( list_len != len - 2 )
-    {
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    name_len = buf[2];
-    if( name_len != list_len - 1 )
-    {
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    /* Check that the server chosen protocol was in our list and save it */
-    for( p = ssl->conf->alpn_list; *p != NULL; p++ )
-    {
-        if( name_len == strlen( *p ) &&
-            memcmp( buf + 3, *p, name_len ) == 0 )
-        {
-            ssl->alpn_chosen = *p;
-            return( 0 );
-        }
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "ALPN extension: no matching protocol" ) );
-    mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                    MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-    return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-}
-#endif /* MBEDTLS_SSL_ALPN */
-
-#if defined(MBEDTLS_SSL_DTLS_SRTP)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl,
-                                   const unsigned char *buf,
-                                   size_t len )
-{
-    mbedtls_ssl_srtp_profile server_protection = MBEDTLS_TLS_SRTP_UNSET;
-    size_t i, mki_len = 0;
-    uint16_t server_protection_profile_value = 0;
-
-    /* If use_srtp is not configured, just ignore the extension */
-    if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) ||
-        ( ssl->conf->dtls_srtp_profile_list == NULL ) ||
-        ( ssl->conf->dtls_srtp_profile_list_len == 0 ) )
-        return( 0 );
-
-    /* RFC 5764 section 4.1.1
-     * uint8 SRTPProtectionProfile[2];
-     *
-     * struct {
-     *   SRTPProtectionProfiles SRTPProtectionProfiles;
-     *   opaque srtp_mki<0..255>;
-     * } UseSRTPData;
-
-     * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>;
-     *
-     */
-    if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED )
-    {
-        mki_len = ssl->dtls_srtp_info.mki_len;
-    }
-
-    /*
-     * Length is 5 + optional mki_value : one protection profile length (2 bytes)
-     *                                      + protection profile (2 bytes)
-     *                                      + mki_len(1 byte)
-     *                                      and optional srtp_mki
-     */
-    if( ( len < 5 ) || ( len != ( buf[4] + 5u ) ) )
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-
-    /*
-     * get the server protection profile
-     */
-
-    /*
-     * protection profile length must be 0x0002 as we must have only
-     * one protection profile in server Hello
-     */
-    if( (  buf[0] != 0 ) || ( buf[1] != 2 ) )
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-
-    server_protection_profile_value = ( buf[2] << 8 ) | buf[3];
-    server_protection = mbedtls_ssl_check_srtp_profile_value(
-                    server_protection_profile_value );
-    if( server_protection != MBEDTLS_TLS_SRTP_UNSET )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "found srtp profile: %s",
-                                      mbedtls_ssl_get_srtp_profile_as_string(
-                                              server_protection ) ) );
-    }
-
-    ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET;
-
-    /*
-     * Check we have the server profile in our list
-     */
-    for( i=0; i < ssl->conf->dtls_srtp_profile_list_len; i++)
-    {
-        if( server_protection == ssl->conf->dtls_srtp_profile_list[i] )
-        {
-            ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i];
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "selected srtp profile: %s",
-                                      mbedtls_ssl_get_srtp_profile_as_string(
-                                              server_protection ) ) );
-            break;
-        }
-    }
-
-    /* If no match was found : server problem, it shall never answer with incompatible profile */
-    if( ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET )
-    {
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    /* If server does not use mki in its reply, make sure the client won't keep
-     * one as negotiated */
-    if( len == 5 )
-    {
-        ssl->dtls_srtp_info.mki_len = 0;
-    }
-
-    /*
-     * RFC5764:
-     *  If the client detects a nonzero-length MKI in the server's response
-     *  that is different than the one the client offered, then the client
-     *  MUST abort the handshake and SHOULD send an invalid_parameter alert.
-     */
-    if( len > 5  && ( buf[4] != mki_len ||
-        ( memcmp( ssl->dtls_srtp_info.mki_value, &buf[5], mki_len ) ) ) )
-    {
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-#if defined (MBEDTLS_DEBUG_C)
-    if( len > 5 )
-    {
-        MBEDTLS_SSL_DEBUG_BUF( 3, "received mki", ssl->dtls_srtp_info.mki_value,
-                                                  ssl->dtls_srtp_info.mki_len );
-    }
-#endif
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_DTLS_SRTP */
-
-/*
- * Parse HelloVerifyRequest.  Only called after verifying the HS type.
- */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl )
-{
-    const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
-    int major_ver, minor_ver;
-    unsigned char cookie_len;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse hello verify request" ) );
-
-    /* Check that there is enough room for:
-     * - 2 bytes of version
-     * - 1 byte of cookie_len
-     */
-    if( mbedtls_ssl_hs_hdr_len( ssl ) + 3 > ssl->in_msglen )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "incoming HelloVerifyRequest message is too short" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                    MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    /*
-     * struct {
-     *   ProtocolVersion server_version;
-     *   opaque cookie<0..2^8-1>;
-     * } HelloVerifyRequest;
-     */
-    MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 );
-    mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, p );
-    p += 2;
-
-    /*
-     * Since the RFC is not clear on this point, accept DTLS 1.0 (TLS 1.1)
-     * even is lower than our min version.
-     */
-    if( major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 ||
-        minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ||
-        major_ver > ssl->conf->max_major_ver  ||
-        minor_ver > ssl->conf->max_minor_ver  )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server version" ) );
-
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                     MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION );
-
-        return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
-    }
-
-    cookie_len = *p++;
-    if( ( ssl->in_msg + ssl->in_msglen ) - p < cookie_len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "cookie length does not match incoming message size" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                    MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-    MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len );
-
-    mbedtls_free( ssl->handshake->verify_cookie );
-
-    ssl->handshake->verify_cookie = mbedtls_calloc( 1, cookie_len );
-    if( ssl->handshake->verify_cookie  == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", cookie_len ) );
-        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
-    }
-
-    memcpy( ssl->handshake->verify_cookie, p, cookie_len );
-    ssl->handshake->verify_cookie_len = cookie_len;
-
-    /* Start over at ClientHello */
-    ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
-    mbedtls_ssl_reset_checksum( ssl );
-
-    mbedtls_ssl_recv_flight_completed( ssl );
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse hello verify request" ) );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
-{
-    int ret, i;
-    size_t n;
-    size_t ext_len;
-    unsigned char *buf, *ext;
-    unsigned char comp;
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-    int accept_comp;
-#endif
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    int renegotiation_info_seen = 0;
-#endif
-    int handshake_failure = 0;
-    const mbedtls_ssl_ciphersuite_t *suite_info;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) );
-
-    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
-    {
-        /* No alert on a read error. */
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
-        return( ret );
-    }
-
-    buf = ssl->in_msg;
-
-    if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
-    {
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-        if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
-        {
-            ssl->renego_records_seen++;
-
-            if( ssl->conf->renego_max_records >= 0 &&
-                ssl->renego_records_seen > ssl->conf->renego_max_records )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1,
-                    ( "renegotiation requested, but not honored by server" ) );
-                return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
-            }
-
-            MBEDTLS_SSL_DEBUG_MSG( 1,
-                ( "non-handshake message during renegotiation" ) );
-
-            ssl->keep_current_message = 1;
-            return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO );
-        }
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
-
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-        mbedtls_ssl_send_alert_message(
-            ssl,
-            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
-        return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
-    }
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        if( buf[0] == MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "received hello verify request" ) );
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) );
-            return( ssl_parse_hello_verify_request( ssl ) );
-        }
-        else
-        {
-            /* We made it through the verification process */
-            mbedtls_free( ssl->handshake->verify_cookie );
-            ssl->handshake->verify_cookie = NULL;
-            ssl->handshake->verify_cookie_len = 0;
-        }
-    }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-    if( ssl->in_hslen < 38 + mbedtls_ssl_hs_hdr_len( ssl ) ||
-        buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    /*
-     *  0   .  1    server_version
-     *  2   . 33    random (maybe including 4 bytes of Unix time)
-     * 34   . 34    session_id length = n
-     * 35   . 34+n  session_id
-     * 35+n . 36+n  cipher_suite
-     * 37+n . 37+n  compression_method
-     *
-     * 38+n . 39+n  extensions length (optional)
-     * 40+n .  ..   extensions
-     */
-    buf += mbedtls_ssl_hs_hdr_len( ssl );
-
-    MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, version", buf + 0, 2 );
-    mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver,
-                      ssl->conf->transport, buf + 0 );
-
-    if( ssl->major_ver < ssl->conf->min_major_ver ||
-        ssl->minor_ver < ssl->conf->min_minor_ver ||
-        ssl->major_ver > ssl->conf->max_major_ver ||
-        ssl->minor_ver > ssl->conf->max_minor_ver )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "server version out of bounds -  min: [%d:%d], server: [%d:%d], max: [%d:%d]",
-              ssl->conf->min_major_ver,
-              ssl->conf->min_minor_ver,
-              ssl->major_ver, ssl->minor_ver,
-              ssl->conf->max_major_ver,
-              ssl->conf->max_minor_ver ) );
-
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                     MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION );
-
-        return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu",
-                                     ( (unsigned long) buf[2] << 24 ) |
-                                     ( (unsigned long) buf[3] << 16 ) |
-                                     ( (unsigned long) buf[4] <<  8 ) |
-                                     ( (unsigned long) buf[5]       ) ) );
-
-    memcpy( ssl->handshake->randbytes + 32, buf + 2, 32 );
-
-    n = buf[34];
-
-    MBEDTLS_SSL_DEBUG_BUF( 3,   "server hello, random bytes", buf + 2, 32 );
-
-    if( n > 32 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    if( ssl->in_hslen > mbedtls_ssl_hs_hdr_len( ssl ) + 39 + n )
-    {
-        ext_len = ( ( buf[38 + n] <<  8 )
-                  | ( buf[39 + n]       ) );
-
-        if( ( ext_len > 0 && ext_len < 4 ) ||
-            ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_len )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-            mbedtls_ssl_send_alert_message(
-                ssl,
-                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-            return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-        }
-    }
-    else if( ssl->in_hslen == mbedtls_ssl_hs_hdr_len( ssl ) + 38 + n )
-    {
-        ext_len = 0;
-    }
-    else
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    /* ciphersuite (used later) */
-    i = ( buf[35 + n] << 8 ) | buf[36 + n];
-
-    /*
-     * Read and check compression
-     */
-    comp = buf[37 + n];
-
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-    /* See comments in ssl_write_client_hello() */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-        accept_comp = 0;
-    else
-#endif
-        accept_comp = 1;
-
-    if( comp != MBEDTLS_SSL_COMPRESS_NULL &&
-        ( comp != MBEDTLS_SSL_COMPRESS_DEFLATE || accept_comp == 0 ) )
-#else /* MBEDTLS_ZLIB_SUPPORT */
-    if( comp != MBEDTLS_SSL_COMPRESS_NULL )
-#endif/* MBEDTLS_ZLIB_SUPPORT */
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "server hello, bad compression: %d", comp ) );
-        mbedtls_ssl_send_alert_message(
-            ssl,
-            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-        return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
-    }
-
-    /*
-     * Initialize update checksum functions
-     */
-    ssl->handshake->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( i );
-    if( ssl->handshake->ciphersuite_info == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "ciphersuite info for %04x not found", (unsigned int)i ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-    }
-
-    mbedtls_ssl_optimize_checksum( ssl, ssl->handshake->ciphersuite_info );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n ) );
-    MBEDTLS_SSL_DEBUG_BUF( 3,   "server hello, session id", buf + 35, n );
-
-    /*
-     * Check if the session can be resumed
-     */
-    if( ssl->handshake->resume == 0 || n == 0 ||
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-        ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ||
-#endif
-        ssl->session_negotiate->ciphersuite != i ||
-        ssl->session_negotiate->compression != comp ||
-        ssl->session_negotiate->id_len != n ||
-        memcmp( ssl->session_negotiate->id, buf + 35, n ) != 0 )
-    {
-        ssl->state++;
-        ssl->handshake->resume = 0;
-#if defined(MBEDTLS_HAVE_TIME)
-        ssl->session_negotiate->start = mbedtls_time( NULL );
-#endif
-        ssl->session_negotiate->ciphersuite = i;
-        ssl->session_negotiate->compression = comp;
-        ssl->session_negotiate->id_len = n;
-        memcpy( ssl->session_negotiate->id, buf + 35, n );
-    }
-    else
-    {
-        ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC;
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
-                   ssl->handshake->resume ? "a" : "no" ) );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", (unsigned) i ) );
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d",
-                                buf[37 + n] ) );
-
-    /*
-     * Perform cipher suite validation in same way as in ssl_write_client_hello.
-     */
-    i = 0;
-    while( 1 )
-    {
-        if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-            mbedtls_ssl_send_alert_message(
-                ssl,
-                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-            return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-        }
-
-        if( ssl->conf->ciphersuite_list[ssl->minor_ver][i++] ==
-            ssl->session_negotiate->ciphersuite )
-        {
-            break;
-        }
-    }
-
-    suite_info = mbedtls_ssl_ciphersuite_from_id(
-        ssl->session_negotiate->ciphersuite );
-    if( ssl_validate_ciphersuite( suite_info, ssl, ssl->minor_ver,
-                                  ssl->minor_ver ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-        mbedtls_ssl_send_alert_message(
-            ssl,
-            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3,
-        ( "server hello, chosen ciphersuite: %s", suite_info->name ) );
-
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA &&
-        ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
-    {
-        ssl->handshake->ecrs_enabled = 1;
-    }
-#endif
-
-    if( comp != MBEDTLS_SSL_COMPRESS_NULL
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-        && comp != MBEDTLS_SSL_COMPRESS_DEFLATE
-#endif
-      )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-        mbedtls_ssl_send_alert_message(
-            ssl,
-            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-    ssl->session_negotiate->compression = comp;
-
-    ext = buf + 40 + n;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2,
-        ( "server hello, total extension length: %" MBEDTLS_PRINTF_SIZET, ext_len ) );
-
-    while( ext_len )
-    {
-        unsigned int ext_id   = ( ( ext[0] <<  8 )
-                                | ( ext[1]       ) );
-        unsigned int ext_size = ( ( ext[2] <<  8 )
-                                | ( ext[3]       ) );
-
-        if( ext_size + 4 > ext_len )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-            mbedtls_ssl_send_alert_message(
-                ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-            return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-        }
-
-        switch( ext_id )
-        {
-        case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO:
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) );
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-            renegotiation_info_seen = 1;
-#endif
-
-            if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4,
-                                                      ext_size ) ) != 0 )
-                return( ret );
-
-            break;
-
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-        case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH:
-            MBEDTLS_SSL_DEBUG_MSG( 3,
-                ( "found max_fragment_length extension" ) );
-
-            if( ( ret = ssl_parse_max_fragment_length_ext( ssl,
-                            ext + 4, ext_size ) ) != 0 )
-            {
-                return( ret );
-            }
-
-            break;
-#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
-
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-        case MBEDTLS_TLS_EXT_TRUNCATED_HMAC:
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated_hmac extension" ) );
-
-            if( ( ret = ssl_parse_truncated_hmac_ext( ssl,
-                            ext + 4, ext_size ) ) != 0 )
-            {
-                return( ret );
-            }
-
-            break;
-#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-        case MBEDTLS_TLS_EXT_CID:
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "found CID extension" ) );
-
-            if( ( ret = ssl_parse_cid_ext( ssl,
-                                           ext + 4,
-                                           ext_size ) ) != 0 )
-            {
-                return( ret );
-            }
-
-            break;
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-        case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC:
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt_then_mac extension" ) );
-
-            if( ( ret = ssl_parse_encrypt_then_mac_ext( ssl,
-                            ext + 4, ext_size ) ) != 0 )
-            {
-                return( ret );
-            }
-
-            break;
-#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
-
-#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-        case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET:
-            MBEDTLS_SSL_DEBUG_MSG( 3,
-                ( "found extended_master_secret extension" ) );
-
-            if( ( ret = ssl_parse_extended_ms_ext( ssl,
-                            ext + 4, ext_size ) ) != 0 )
-            {
-                return( ret );
-            }
-
-            break;
-#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-        case MBEDTLS_TLS_EXT_SESSION_TICKET:
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session_ticket extension" ) );
-
-            if( ( ret = ssl_parse_session_ticket_ext( ssl,
-                            ext + 4, ext_size ) ) != 0 )
-            {
-                return( ret );
-            }
-
-            break;
-#endif /* MBEDTLS_SSL_SESSION_TICKETS */
-
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-        case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS:
-            MBEDTLS_SSL_DEBUG_MSG( 3,
-                ( "found supported_point_formats extension" ) );
-
-            if( ( ret = ssl_parse_supported_point_formats_ext( ssl,
-                            ext + 4, ext_size ) ) != 0 )
-            {
-                return( ret );
-            }
-
-            break;
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
-          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-        case MBEDTLS_TLS_EXT_ECJPAKE_KKPP:
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake_kkpp extension" ) );
-
-            if( ( ret = ssl_parse_ecjpake_kkpp( ssl,
-                            ext + 4, ext_size ) ) != 0 )
-            {
-                return( ret );
-            }
-
-            break;
-#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-
-#if defined(MBEDTLS_SSL_ALPN)
-        case MBEDTLS_TLS_EXT_ALPN:
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) );
-
-            if( ( ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ) ) != 0 )
-                return( ret );
-
-            break;
-#endif /* MBEDTLS_SSL_ALPN */
-
-#if defined(MBEDTLS_SSL_DTLS_SRTP)
-        case MBEDTLS_TLS_EXT_USE_SRTP:
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "found use_srtp extension" ) );
-
-            if( ( ret = ssl_parse_use_srtp_ext( ssl, ext + 4, ext_size ) ) != 0 )
-                return( ret );
-
-            break;
-#endif /* MBEDTLS_SSL_DTLS_SRTP */
-
-        default:
-            MBEDTLS_SSL_DEBUG_MSG( 3,
-                ( "unknown extension found: %u (ignoring)", ext_id ) );
-        }
-
-        ext_len -= 4 + ext_size;
-        ext += 4 + ext_size;
-
-        if( ext_len > 0 && ext_len < 4 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) );
-            return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-        }
-    }
-
-    /*
-     * mbedtls_ssl_derive_keys() has to be called after the parsing of the
-     * extensions. It sets the transform data for the resumed session which in
-     * case of DTLS includes the server CID extracted from the CID extension.
-     */
-    if( ssl->handshake->resume )
-    {
-        if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
-            mbedtls_ssl_send_alert_message(
-                ssl,
-                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
-            return( ret );
-        }
-    }
-
-    /*
-     * Renegotiation security checks
-     */
-    if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-        ssl->conf->allow_legacy_renegotiation ==
-        MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "legacy renegotiation, breaking off handshake" ) );
-        handshake_failure = 1;
-    }
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
-             ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION &&
-             renegotiation_info_seen == 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "renegotiation_info extension missing (secure)" ) );
-        handshake_failure = 1;
-    }
-    else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
-             ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-             ssl->conf->allow_legacy_renegotiation ==
-             MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) );
-        handshake_failure = 1;
-    }
-    else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
-             ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-             renegotiation_info_seen == 1 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "renegotiation_info extension present (legacy)" ) );
-        handshake_failure = 1;
-    }
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
-
-    if( handshake_failure == 1 )
-    {
-        mbedtls_ssl_send_alert_message(
-            ssl,
-            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) );
-
-    return( 0 );
-}
-
-#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
-    defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl,
-                                       unsigned char **p,
-                                       unsigned char *end )
-{
-    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-    size_t dhm_actual_bitlen;
-
-    /*
-     * Ephemeral DH parameters:
-     *
-     * struct {
-     *     opaque dh_p<1..2^16-1>;
-     *     opaque dh_g<1..2^16-1>;
-     *     opaque dh_Ys<1..2^16-1>;
-     * } ServerDHParams;
-     */
-    if( ( ret = mbedtls_dhm_read_params( &ssl->handshake->dhm_ctx,
-                                         p, end ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 2, ( "mbedtls_dhm_read_params" ), ret );
-        return( ret );
-    }
-
-    dhm_actual_bitlen = mbedtls_mpi_bitlen( &ssl->handshake->dhm_ctx.P );
-    if( dhm_actual_bitlen < ssl->conf->dhm_min_bitlen )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %" MBEDTLS_PRINTF_SIZET " < %u",
-                                    dhm_actual_bitlen,
-                                    ssl->conf->dhm_min_bitlen ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-    }
-
-    MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P  );
-    MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G  );
-    MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY );
-
-    return( ret );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ||                     \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
-{
-    const mbedtls_ecp_curve_info *curve_info;
-    mbedtls_ecp_group_id grp_id;
-#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
-    grp_id = ssl->handshake->ecdh_ctx.grp.id;
-#else
-    grp_id = ssl->handshake->ecdh_ctx.grp_id;
-#endif
-
-    curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id );
-    if( curve_info == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) );
-
-#if defined(MBEDTLS_ECP_C)
-    if( mbedtls_ssl_check_curve( ssl, grp_id ) != 0 )
-#else
-    if( ssl->handshake->ecdh_ctx.grp.nbits < 163 ||
-        ssl->handshake->ecdh_ctx.grp.nbits > 521 )
-#endif
-        return( -1 );
-
-    MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
-                            MBEDTLS_DEBUG_ECDH_QP );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO) &&                           \
-        ( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||     \
-          defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) )
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl,
-                                             unsigned char **p,
-                                             unsigned char *end )
-{
-    uint16_t tls_id;
-    size_t ecdh_bits = 0;
-    uint8_t ecpoint_len;
-    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
-
-    /*
-     * Parse ECC group
-     */
-
-    if( end - *p < 4 )
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-
-    /* First byte is curve_type; only named_curve is handled */
-    if( *(*p)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-
-    /* Next two bytes are the namedcurve value */
-    tls_id = *(*p)++;
-    tls_id <<= 8;
-    tls_id |= *(*p)++;
-
-    /* Check it's a curve we offered */
-    if( mbedtls_ssl_check_curve_tls_id( ssl, tls_id ) != 0 )
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-
-    /* Convert EC group to PSA key type. */
-    if( ( handshake->ecdh_psa_type =
-          mbedtls_psa_parse_tls_ecc_group( tls_id, &ecdh_bits ) ) == 0 )
-    {
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-    }
-    if( ecdh_bits > 0xffff )
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-    handshake->ecdh_bits = (uint16_t) ecdh_bits;
-
-    /*
-     * Put peer's ECDH public key in the format understood by PSA.
-     */
-
-    ecpoint_len = *(*p)++;
-    if( (size_t)( end - *p ) < ecpoint_len )
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-
-    if( mbedtls_psa_tls_ecpoint_to_psa_ec(
-                                    *p, ecpoint_len,
-                                    handshake->ecdh_psa_peerkey,
-                                    sizeof( handshake->ecdh_psa_peerkey ),
-                                    &handshake->ecdh_psa_peerkey_len ) != 0 )
-    {
-        return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-    }
-
-    *p += ecpoint_len;
-    return( 0 );
-}
-#endif /* MBEDTLS_USE_PSA_CRYPTO &&
-            ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
-              MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
-                                         unsigned char **p,
-                                         unsigned char *end )
-{
-    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-
-    /*
-     * Ephemeral ECDH parameters:
-     *
-     * struct {
-     *     ECParameters curve_params;
-     *     ECPoint      public;
-     * } ServerECDHParams;
-     */
-    if( ( ret = mbedtls_ecdh_read_params( &ssl->handshake->ecdh_ctx,
-                                  (const unsigned char **) p, end ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret );
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-        if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
-            ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
-#endif
-        return( ret );
-    }
-
-    if( ssl_check_server_ecdh_params( ssl ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "bad server key exchange message (ECDHE curve)" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-    }
-
-    return( ret );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
-                                      unsigned char **p,
-                                      unsigned char *end )
-{
-    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-    uint16_t  len;
-    ((void) ssl);
-
-    /*
-     * PSK parameters:
-     *
-     * opaque psk_identity_hint<0..2^16-1>;
-     */
-    if( end - (*p) < 2 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "bad server key exchange message (psk_identity_hint length)" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-    }
-    len = (*p)[0] << 8 | (*p)[1];
-    *p += 2;
-
-    if( end - (*p) < len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "bad server key exchange message (psk_identity_hint length)" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-    }
-
-    /*
-     * Note: we currently ignore the PKS identity hint, as we only allow one
-     * PSK to be provisionned on the client. This could be changed later if
-     * someone needs that feature.
-     */
-    *p += len;
-    ret = 0;
-
-    return( ret );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) ||                           \
-    defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
-/*
- * Generate a pre-master secret and encrypt it with the server's RSA key
- */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
-                                    size_t offset, size_t *olen,
-                                    size_t pms_offset )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2;
-    unsigned char *p = ssl->handshake->premaster + pms_offset;
-    mbedtls_pk_context * peer_pk;
-
-    if( offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) );
-        return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
-    }
-
-    /*
-     * Generate (part of) the pre-master as
-     *  struct {
-     *      ProtocolVersion client_version;
-     *      opaque random[46];
-     *  } PreMasterSecret;
-     */
-    mbedtls_ssl_write_version( ssl->conf->max_major_ver,
-                               ssl->conf->max_minor_ver,
-                               ssl->conf->transport, p );
-
-    if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p + 2, 46 ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret );
-        return( ret );
-    }
-
-    ssl->handshake->pmslen = 48;
-
-#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    peer_pk = &ssl->handshake->peer_pubkey;
-#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-    if( ssl->session_negotiate->peer_cert == NULL )
-    {
-        /* Should never happen */
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-    peer_pk = &ssl->session_negotiate->peer_cert->pk;
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-
-    /*
-     * Now write it out, encrypted
-     */
-    if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_RSA ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) );
-        return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
-    }
-
-    if( ( ret = mbedtls_pk_encrypt( peer_pk,
-                            p, ssl->handshake->pmslen,
-                            ssl->out_msg + offset + len_bytes, olen,
-                            MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes,
-                            ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret );
-        return( ret );
-    }
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    if( len_bytes == 2 )
-    {
-        MBEDTLS_PUT_UINT16_BE( *olen, ssl->out_msg, offset );
-        *olen += 2;
-    }
-#endif
-
-#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    /* We don't need the peer's public key anymore. Free it. */
-    mbedtls_pk_free( peer_pk );
-#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-    return( 0 );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl,
-                                          unsigned char **p,
-                                          unsigned char *end,
-                                          mbedtls_md_type_t *md_alg,
-                                          mbedtls_pk_type_t *pk_alg )
-{
-    ((void) ssl);
-    *md_alg = MBEDTLS_MD_NONE;
-    *pk_alg = MBEDTLS_PK_NONE;
-
-    /* Only in TLS 1.2 */
-    if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 )
-    {
-        return( 0 );
-    }
-
-    if( (*p) + 2 > end )
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-
-    /*
-     * Get hash algorithm
-     */
-    if( ( *md_alg = mbedtls_ssl_md_alg_from_hash( (*p)[0] ) )
-        == MBEDTLS_MD_NONE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "Server used unsupported HashAlgorithm %d", *(p)[0] ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-    }
-
-    /*
-     * Get signature algorithm
-     */
-    if( ( *pk_alg = mbedtls_ssl_pk_alg_from_sig( (*p)[1] ) )
-        == MBEDTLS_PK_NONE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "server used unsupported SignatureAlgorithm %d", (*p)[1] ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-    }
-
-    /*
-     * Check if the hash is acceptable
-     */
-    if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "server used HashAlgorithm %d that was not offered", *(p)[0] ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d",
-                                (*p)[1] ) );
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d",
-                                (*p)[0] ) );
-    *p += 2;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    const mbedtls_ecp_keypair *peer_key;
-    mbedtls_pk_context * peer_pk;
-
-#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    peer_pk = &ssl->handshake->peer_pubkey;
-#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-    if( ssl->session_negotiate->peer_cert == NULL )
-    {
-        /* Should never happen */
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-    peer_pk = &ssl->session_negotiate->peer_cert->pk;
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-
-    /* This is a public key, so it can't be opaque, so can_do() is a good
-     * enough check to ensure pk_ec() is safe to use below. */
-    if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_ECKEY ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
-        return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
-    }
-
-    peer_key = mbedtls_pk_ec( *peer_pk );
-
-    if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key,
-                                 MBEDTLS_ECDH_THEIRS ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret );
-        return( ret );
-    }
-
-    if( ssl_check_server_ecdh_params( ssl ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server certificate (ECDH curve)" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
-    }
-
-#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    /* We don't need the peer's public key anymore. Free it,
-     * so that more RAM is available for upcoming expensive
-     * operations like ECDHE. */
-    mbedtls_pk_free( peer_pk );
-#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-
-    return( ret );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
-          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-    unsigned char *p = NULL, *end = NULL;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) );
-
-#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) );
-        ssl->state++;
-        return( 0 );
-    }
-    ((void) p);
-    ((void) end);
-#endif
-
-#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA )
-    {
-        if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret );
-            mbedtls_ssl_send_alert_message(
-                ssl,
-                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-            return( ret );
-        }
-
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) );
-        ssl->state++;
-        return( 0 );
-    }
-    ((void) p);
-    ((void) end);
-#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
-
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    if( ssl->handshake->ecrs_enabled &&
-        ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing )
-    {
-        goto start_processing;
-    }
-#endif
-
-    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
-        return( ret );
-    }
-
-    if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-        mbedtls_ssl_send_alert_message(
-            ssl,
-            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
-        return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
-    }
-
-    /*
-     * ServerKeyExchange may be skipped with PSK and RSA-PSK when the server
-     * doesn't use a psk_identity_hint
-     */
-    if( ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE )
-    {
-        if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
-            ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
-        {
-            /* Current message is probably either
-             * CertificateRequest or ServerHelloDone */
-            ssl->keep_current_message = 1;
-            goto exit;
-        }
-
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "server key exchange message must not be skipped" ) );
-        mbedtls_ssl_send_alert_message(
-            ssl,
-            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
-
-        return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
-    }
-
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    if( ssl->handshake->ecrs_enabled )
-        ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing;
-
-start_processing:
-#endif
-    p   = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
-    end = ssl->in_msg + ssl->in_hslen;
-    MBEDTLS_SSL_DEBUG_BUF( 3,   "server key exchange", p, end - p );
-
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
-    {
-        if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-            mbedtls_ssl_send_alert_message(
-                ssl,
-                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-            return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-        }
-    } /* FALLTHROUGH */
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) ||                       \
-    defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
-        ; /* nothing more to do */
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
-    defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK )
-    {
-        if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-            mbedtls_ssl_send_alert_message(
-                ssl,
-                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-            return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-        }
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
-#if defined(MBEDTLS_USE_PSA_CRYPTO) &&                           \
-        ( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||     \
-          defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) )
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA )
-    {
-        if( ssl_parse_server_ecdh_params_psa( ssl, &p, end ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-            mbedtls_ssl_send_alert_message(
-                ssl,
-                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-            return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-        }
-    }
-    else
-#endif /* MBEDTLS_USE_PSA_CRYPTO &&
-            ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
-              MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */
-#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ||                     \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA )
-    {
-        if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-            mbedtls_ssl_send_alert_message(
-                ssl,
-                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-            return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-        }
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
-    {
-        ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx,
-                                              p, end - p );
-        if( ret != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret );
-            mbedtls_ssl_send_alert_message(
-                ssl,
-                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-            return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-        }
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
-    if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) )
-    {
-        size_t sig_len, hashlen;
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-        unsigned char hash[PSA_HASH_MAX_SIZE];
-#else
-        unsigned char hash[MBEDTLS_MD_MAX_SIZE];
-#endif
-        mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;
-        mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
-        unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
-        size_t params_len = p - params;
-        void *rs_ctx = NULL;
-
-        mbedtls_pk_context * peer_pk;
-
-        /*
-         * Handle the digitally-signed structure
-         */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
-        {
-            if( ssl_parse_signature_algorithm( ssl, &p, end,
-                                               &md_alg, &pk_alg ) != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1,
-                    ( "bad server key exchange message" ) );
-                mbedtls_ssl_send_alert_message(
-                    ssl,
-                    MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                    MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-                return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-            }
-
-            if( pk_alg !=
-                mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1,
-                    ( "bad server key exchange message" ) );
-                mbedtls_ssl_send_alert_message(
-                    ssl,
-                    MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                    MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-                return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-            }
-        }
-        else
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_1)
-        if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 )
-        {
-            pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
-
-            /* Default hash for ECDSA is SHA-1 */
-            if( pk_alg == MBEDTLS_PK_ECDSA && md_alg == MBEDTLS_MD_NONE )
-                md_alg = MBEDTLS_MD_SHA1;
-        }
-        else
-#endif
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-        }
-
-        /*
-         * Read signature
-         */
-
-        if( p > end - 2 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-            mbedtls_ssl_send_alert_message(
-                ssl,
-                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-            return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-        }
-        sig_len = ( p[0] << 8 ) | p[1];
-        p += 2;
-
-        if( p != end - sig_len )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-            mbedtls_ssl_send_alert_message(
-                ssl,
-                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-            return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-        }
-
-        MBEDTLS_SSL_DEBUG_BUF( 3, "signature", p, sig_len );
-
-        /*
-         * Compute the hash that has been signed
-         */
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_1)
-        if( md_alg == MBEDTLS_MD_NONE )
-        {
-            hashlen = 36;
-            ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash, params,
-                                                           params_len );
-            if( ret != 0 )
-                return( ret );
-        }
-        else
-#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \
-          MBEDTLS_SSL_PROTO_TLS1_1 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        if( md_alg != MBEDTLS_MD_NONE )
-        {
-            ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen,
-                                                          params, params_len,
-                                                          md_alg );
-            if( ret != 0 )
-                return( ret );
-        }
-        else
-#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
-          MBEDTLS_SSL_PROTO_TLS1_2 */
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-        }
-
-        MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
-
-#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-        peer_pk = &ssl->handshake->peer_pubkey;
-#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-        if( ssl->session_negotiate->peer_cert == NULL )
-        {
-            /* Should never happen */
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-        }
-        peer_pk = &ssl->session_negotiate->peer_cert->pk;
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-
-        /*
-         * Verify signature
-         */
-        if( !mbedtls_pk_can_do( peer_pk, pk_alg ) )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
-            mbedtls_ssl_send_alert_message(
-                ssl,
-                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-            return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
-        }
-
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-        if( ssl->handshake->ecrs_enabled )
-            rs_ctx = &ssl->handshake->ecrs_ctx.pk;
-#endif
-
-        if( ( ret = mbedtls_pk_verify_restartable( peer_pk,
-                        md_alg, hash, hashlen, p, sig_len, rs_ctx ) ) != 0 )
-        {
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-            if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
-#endif
-                mbedtls_ssl_send_alert_message(
-                    ssl,
-                    MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                    MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret );
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-            if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
-                ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
-#endif
-            return( ret );
-        }
-
-#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-        /* We don't need the peer's public key anymore. Free it,
-         * so that more RAM is available for upcoming expensive
-         * operations like ECDHE. */
-        mbedtls_pk_free( peer_pk );
-#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-    }
-#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */
-
-exit:
-    ssl->state++;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) );
-
-    return( 0 );
-}
-
-#if ! defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
-{
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
-
-    if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) );
-        ssl->state++;
-        return( 0 );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-    return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-}
-#else /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char *buf;
-    size_t n = 0;
-    size_t cert_type_len = 0, dn_len = 0;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
-
-    if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) );
-        ssl->state++;
-        return( 0 );
-    }
-
-    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
-        return( ret );
-    }
-
-    if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
-        mbedtls_ssl_send_alert_message(
-            ssl,
-            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
-        return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
-    }
-
-    ssl->state++;
-    ssl->client_auth = ( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request",
-                        ssl->client_auth ? "a" : "no" ) );
-
-    if( ssl->client_auth == 0 )
-    {
-        /* Current message is probably the ServerHelloDone */
-        ssl->keep_current_message = 1;
-        goto exit;
-    }
-
-    /*
-     *  struct {
-     *      ClientCertificateType certificate_types<1..2^8-1>;
-     *      SignatureAndHashAlgorithm
-     *        supported_signature_algorithms<2^16-1>; -- TLS 1.2 only
-     *      DistinguishedName certificate_authorities<0..2^16-1>;
-     *  } CertificateRequest;
-     *
-     *  Since we only support a single certificate on clients, let's just
-     *  ignore all the information that's supposed to help us pick a
-     *  certificate.
-     *
-     *  We could check that our certificate matches the request, and bail out
-     *  if it doesn't, but it's simpler to just send the certificate anyway,
-     *  and give the server the opportunity to decide if it should terminate
-     *  the connection when it doesn't like our certificate.
-     *
-     *  Same goes for the hash in TLS 1.2's signature_algorithms: at this
-     *  point we only have one hash available (see comments in
-     *  write_certificate_verify), so let's just use what we have.
-     *
-     *  However, we still minimally parse the message to check it is at least
-     *  superficially sane.
-     */
-    buf = ssl->in_msg;
-
-    /* certificate_types */
-    if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
-    }
-    cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )];
-    n = cert_type_len;
-
-    /*
-     * In the subsequent code there are two paths that read from buf:
-     *     * the length of the signature algorithms field (if minor version of
-     *       SSL is 3),
-     *     * distinguished name length otherwise.
-     * Both reach at most the index:
-     *    ...hdr_len + 2 + n,
-     * therefore the buffer length at this point must be greater than that
-     * regardless of the actual code path.
-     */
-    if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
-    }
-
-    /* supported_signature_algorithms */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
-    {
-        size_t sig_alg_len =
-            ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] <<  8 )
-              | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n]   ) );
-#if defined(MBEDTLS_DEBUG_C)
-        unsigned char* sig_alg;
-        size_t i;
-#endif
-
-        /*
-         * The furthest access in buf is in the loop few lines below:
-         *     sig_alg[i + 1],
-         * where:
-         *     sig_alg = buf + ...hdr_len + 3 + n,
-         *     max(i) = sig_alg_len - 1.
-         * Therefore the furthest access is:
-         *     buf[...hdr_len + 3 + n + sig_alg_len - 1 + 1],
-         * which reduces to:
-         *     buf[...hdr_len + 3 + n + sig_alg_len],
-         * which is one less than we need the buf to be.
-         */
-        if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl )
-                                + 3 + n + sig_alg_len )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
-            mbedtls_ssl_send_alert_message(
-                ssl,
-                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
-        }
-
-#if defined(MBEDTLS_DEBUG_C)
-        sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n;
-        for( i = 0; i < sig_alg_len; i += 2 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3,
-                ( "Supported Signature Algorithm found: %d,%d",
-                  sig_alg[i], sig_alg[i + 1]  ) );
-        }
-#endif
-
-        n += 2 + sig_alg_len;
-    }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-
-    /* certificate_authorities */
-    dn_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] <<  8 )
-             | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n]       ) );
-
-    n += dn_len;
-    if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
-    }
-
-exit:
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
-
-    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
-        return( ret );
-    }
-
-    if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
-        return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
-    }
-
-    if( ssl->in_hslen  != mbedtls_ssl_hs_hdr_len( ssl ) ||
-        ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE );
-    }
-
-    ssl->state++;
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-        mbedtls_ssl_recv_flight_completed( ssl );
-#endif
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) );
-
-    return( 0 );
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    size_t header_len;
-    size_t content_len;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) );
-
-#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA )
-    {
-        /*
-         * DHM key exchange -- send G^X mod P
-         */
-        content_len = ssl->handshake->dhm_ctx.len;
-
-        MBEDTLS_PUT_UINT16_BE( content_len, ssl->out_msg, 4 );
-        header_len = 6;
-
-        ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx,
-                          (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
-                          &ssl->out_msg[header_len], content_len,
-                          ssl->conf->f_rng, ssl->conf->p_rng );
-        if( ret != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret );
-            return( ret );
-        }
-
-        MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X  );
-        MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX );
-
-        if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx,
-                                  ssl->handshake->premaster,
-                                  MBEDTLS_PREMASTER_SIZE,
-                                  &ssl->handshake->pmslen,
-                                  ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret );
-            return( ret );
-        }
-
-        MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K  );
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */
-#if defined(MBEDTLS_USE_PSA_CRYPTO) &&                           \
-        ( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||     \
-          defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) )
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA )
-    {
-        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-        psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED;
-        psa_key_attributes_t key_attributes;
-
-        mbedtls_ssl_handshake_params *handshake = ssl->handshake;
-
-        unsigned char own_pubkey[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
-        size_t own_pubkey_len;
-        unsigned char *own_pubkey_ecpoint;
-        size_t own_pubkey_ecpoint_len;
-
-        header_len = 4;
-
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Perform PSA-based ECDH computation." ) );
-
-        /*
-         * Generate EC private key for ECDHE exchange.
-         */
-
-        /* The master secret is obtained from the shared ECDH secret by
-         * applying the TLS 1.2 PRF with a specific salt and label. While
-         * the PSA Crypto API encourages combining key agreement schemes
-         * such as ECDH with fixed KDFs such as TLS 1.2 PRF, it does not
-         * yet support the provisioning of salt + label to the KDF.
-         * For the time being, we therefore need to split the computation
-         * of the ECDH secret and the application of the TLS 1.2 PRF. */
-        key_attributes = psa_key_attributes_init();
-        psa_set_key_usage_flags( &key_attributes, PSA_KEY_USAGE_DERIVE );
-        psa_set_key_algorithm( &key_attributes, PSA_ALG_ECDH );
-        psa_set_key_type( &key_attributes, handshake->ecdh_psa_type );
-        psa_set_key_bits( &key_attributes, handshake->ecdh_bits );
-
-        /* Generate ECDH private key. */
-        status = psa_generate_key( &key_attributes,
-                                   &handshake->ecdh_psa_privkey );
-        if( status != PSA_SUCCESS )
-            return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-
-        /* Export the public part of the ECDH private key from PSA
-         * and convert it to ECPoint format used in ClientKeyExchange. */
-        status = psa_export_public_key( handshake->ecdh_psa_privkey,
-                                        own_pubkey, sizeof( own_pubkey ),
-                                        &own_pubkey_len );
-        if( status != PSA_SUCCESS )
-        {
-            psa_destroy_key( handshake->ecdh_psa_privkey );
-            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
-            return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-        }
-
-        if( mbedtls_psa_tls_psa_ec_to_ecpoint( own_pubkey,
-                                               own_pubkey_len,
-                                               &own_pubkey_ecpoint,
-                                               &own_pubkey_ecpoint_len ) != 0 )
-        {
-            psa_destroy_key( handshake->ecdh_psa_privkey );
-            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
-            return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-        }
-
-        /* Copy ECPoint structure to outgoing message buffer. */
-        ssl->out_msg[header_len] = (unsigned char) own_pubkey_ecpoint_len;
-        memcpy( ssl->out_msg + header_len + 1,
-                own_pubkey_ecpoint, own_pubkey_ecpoint_len );
-        content_len = own_pubkey_ecpoint_len + 1;
-
-        /* The ECDH secret is the premaster secret used for key derivation. */
-
-        /* Compute ECDH shared secret. */
-        status = psa_raw_key_agreement( PSA_ALG_ECDH,
-                                        handshake->ecdh_psa_privkey,
-                                        handshake->ecdh_psa_peerkey,
-                                        handshake->ecdh_psa_peerkey_len,
-                                        ssl->handshake->premaster,
-                                        sizeof( ssl->handshake->premaster ),
-                                        &ssl->handshake->pmslen );
-
-        destruction_status = psa_destroy_key( handshake->ecdh_psa_privkey );
-        handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
-
-        if( status != PSA_SUCCESS || destruction_status != PSA_SUCCESS )
-            return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-    }
-    else
-#endif /* MBEDTLS_USE_PSA_CRYPTO &&
-            ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
-              MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */
-#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA )
-    {
-        /*
-         * ECDH key exchange -- send client public value
-         */
-        header_len = 4;
-
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-        if( ssl->handshake->ecrs_enabled )
-        {
-            if( ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret )
-                goto ecdh_calc_secret;
-
-            mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx );
-        }
-#endif
-
-        ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx,
-                                &content_len,
-                                &ssl->out_msg[header_len], 1000,
-                                ssl->conf->f_rng, ssl->conf->p_rng );
-        if( ret != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret );
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-            if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
-                ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
-#endif
-            return( ret );
-        }
-
-        MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
-                                MBEDTLS_DEBUG_ECDH_Q );
-
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-        if( ssl->handshake->ecrs_enabled )
-        {
-            ssl->handshake->ecrs_n = content_len;
-            ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret;
-        }
-
-ecdh_calc_secret:
-        if( ssl->handshake->ecrs_enabled )
-            content_len = ssl->handshake->ecrs_n;
-#endif
-        if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
-                                  &ssl->handshake->pmslen,
-                                  ssl->handshake->premaster,
-                                  MBEDTLS_MPI_MAX_SIZE,
-                                  ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret );
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-            if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
-                ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
-#endif
-            return( ret );
-        }
-
-        MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
-                                MBEDTLS_DEBUG_ECDH_Z );
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
-    if( mbedtls_ssl_ciphersuite_uses_psk( ciphersuite_info ) )
-    {
-        /*
-         * opaque psk_identity<0..2^16-1>;
-         */
-        if( ssl_conf_has_static_psk( ssl->conf ) == 0 )
-        {
-            /* We don't offer PSK suites if we don't have a PSK,
-             * and we check that the server's choice is among the
-             * ciphersuites we offered, so this should never happen. */
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-        }
-
-        header_len = 4;
-        content_len = ssl->conf->psk_identity_len;
-
-        if( header_len + 2 + content_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1,
-                ( "psk identity too long or SSL buffer too short" ) );
-            return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
-        }
-
-        ssl->out_msg[header_len++] = MBEDTLS_BYTE_1( content_len );
-        ssl->out_msg[header_len++] = MBEDTLS_BYTE_0( content_len );
-
-        memcpy( ssl->out_msg + header_len,
-                ssl->conf->psk_identity,
-                ssl->conf->psk_identity_len );
-        header_len += ssl->conf->psk_identity_len;
-
-#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
-        if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK )
-        {
-            content_len = 0;
-        }
-        else
-#endif
-#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
-        if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
-        {
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-            /* Opaque PSKs are currently only supported for PSK-only suites. */
-            if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with RSA-PSK" ) );
-                return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
-            }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-            if( ( ret = ssl_write_encrypted_pms( ssl, header_len,
-                                                 &content_len, 2 ) ) != 0 )
-                return( ret );
-        }
-        else
-#endif
-#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
-        if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK )
-        {
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-            /* Opaque PSKs are currently only supported for PSK-only suites. */
-            if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with DHE-PSK" ) );
-                return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
-            }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-            /*
-             * ClientDiffieHellmanPublic public (DHM send G^X mod P)
-             */
-            content_len = ssl->handshake->dhm_ctx.len;
-
-            if( header_len + 2 + content_len >
-                MBEDTLS_SSL_OUT_CONTENT_LEN )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1,
-                    ( "psk identity or DHM size too long or SSL buffer too short" ) );
-                return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
-            }
-
-            ssl->out_msg[header_len++] = MBEDTLS_BYTE_1( content_len );
-            ssl->out_msg[header_len++] = MBEDTLS_BYTE_0( content_len );
-
-            ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx,
-                    (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
-                    &ssl->out_msg[header_len], content_len,
-                    ssl->conf->f_rng, ssl->conf->p_rng );
-            if( ret != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret );
-                return( ret );
-            }
-        }
-        else
-#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
-        if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
-        {
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-            /* Opaque PSKs are currently only supported for PSK-only suites. */
-            if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with ECDHE-PSK" ) );
-                return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
-            }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-            /*
-             * ClientECDiffieHellmanPublic public;
-             */
-            ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx,
-                    &content_len,
-                    &ssl->out_msg[header_len],
-                    MBEDTLS_SSL_OUT_CONTENT_LEN - header_len,
-                    ssl->conf->f_rng, ssl->conf->p_rng );
-            if( ret != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret );
-                return( ret );
-            }
-
-            MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
-                                    MBEDTLS_DEBUG_ECDH_Q );
-        }
-        else
-#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-        }
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO) &&          \
-    defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
-        if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK &&
-            ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 &&
-            ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1,
-                ( "skip PMS generation for opaque PSK" ) );
-        }
-        else
-#endif /* MBEDTLS_USE_PSA_CRYPTO &&
-          MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
-        if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,
-                        ciphersuite_info->key_exchange ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1,
-                "mbedtls_ssl_psk_derive_premaster", ret );
-            return( ret );
-        }
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA )
-    {
-        header_len = 4;
-        if( ( ret = ssl_write_encrypted_pms( ssl, header_len,
-                                             &content_len, 0 ) ) != 0 )
-            return( ret );
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
-    {
-        header_len = 4;
-
-        ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx,
-                ssl->out_msg + header_len,
-                MBEDTLS_SSL_OUT_CONTENT_LEN - header_len,
-                &content_len,
-                ssl->conf->f_rng, ssl->conf->p_rng );
-        if( ret != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret );
-            return( ret );
-        }
-
-        ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx,
-                ssl->handshake->premaster, 32, &ssl->handshake->pmslen,
-                ssl->conf->f_rng, ssl->conf->p_rng );
-        if( ret != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret );
-            return( ret );
-        }
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
-    {
-        ((void) ciphersuite_info);
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-
-    ssl->out_msglen  = header_len + content_len;
-    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
-    ssl->out_msg[0]  = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE;
-
-    ssl->state++;
-
-    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
-        return( ret );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) );
-
-    return( 0 );
-}
-
-#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
-{
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
-
-    if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
-        return( ret );
-    }
-
-    if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
-        ssl->state++;
-        return( 0 );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-    return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-}
-#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-    size_t n = 0, offset = 0;
-    unsigned char hash[48];
-    unsigned char *hash_start = hash;
-    mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;
-    size_t hashlen;
-    void *rs_ctx = NULL;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
-
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    if( ssl->handshake->ecrs_enabled &&
-        ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign )
-    {
-        goto sign;
-    }
-#endif
-
-    if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
-        return( ret );
-    }
-
-    if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
-        ssl->state++;
-        return( 0 );
-    }
-
-    if( ssl->client_auth == 0 || mbedtls_ssl_own_cert( ssl ) == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
-        ssl->state++;
-        return( 0 );
-    }
-
-    if( mbedtls_ssl_own_key( ssl ) == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for certificate" ) );
-        return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
-    }
-
-    /*
-     * Make a signature of the handshake digests
-     */
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    if( ssl->handshake->ecrs_enabled )
-        ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign;
-
-sign:
-#endif
-
-    ssl->handshake->calc_verify( ssl, hash, &hashlen );
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_1)
-    if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 )
-    {
-        /*
-         * digitally-signed struct {
-         *     opaque md5_hash[16];
-         *     opaque sha_hash[20];
-         * };
-         *
-         * md5_hash
-         *     MD5(handshake_messages);
-         *
-         * sha_hash
-         *     SHA(handshake_messages);
-         */
-        md_alg = MBEDTLS_MD_NONE;
-
-        /*
-         * For ECDSA, default hash is SHA-1 only
-         */
-        if( mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECDSA ) )
-        {
-            hash_start += 16;
-            hashlen -= 16;
-            md_alg = MBEDTLS_MD_SHA1;
-        }
-    }
-    else
-#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \
-          MBEDTLS_SSL_PROTO_TLS1_1 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
-    {
-        /*
-         * digitally-signed struct {
-         *     opaque handshake_messages[handshake_messages_length];
-         * };
-         *
-         * Taking shortcut here. We assume that the server always allows the
-         * PRF Hash function and has sent it in the allowed signature
-         * algorithms list received in the Certificate Request message.
-         *
-         * Until we encounter a server that does not, we will take this
-         * shortcut.
-         *
-         * Reason: Otherwise we should have running hashes for SHA512 and
-         *         SHA224 in order to satisfy 'weird' needs from the server
-         *         side.
-         */
-        if( ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384 )
-        {
-            md_alg = MBEDTLS_MD_SHA384;
-            ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384;
-        }
-        else
-        {
-            md_alg = MBEDTLS_MD_SHA256;
-            ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256;
-        }
-        ssl->out_msg[5] = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) );
-
-        /* Info from md_alg will be used instead */
-        hashlen = 0;
-        offset = 2;
-    }
-    else
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    if( ssl->handshake->ecrs_enabled )
-        rs_ctx = &ssl->handshake->ecrs_ctx.pk;
-#endif
-
-    if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ),
-                         md_alg, hash_start, hashlen,
-                         ssl->out_msg + 6 + offset, &n,
-                         ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret );
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-        if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
-            ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
-#endif
-        return( ret );
-    }
-
-    MBEDTLS_PUT_UINT16_BE( n, ssl->out_msg, offset + 4 );
-
-    ssl->out_msglen  = 6 + n + offset;
-    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
-    ssl->out_msg[0]  = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY;
-
-    ssl->state++;
-
-    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
-        return( ret );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) );
-
-    return( ret );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    uint32_t lifetime;
-    size_t ticket_len;
-    unsigned char *ticket;
-    const unsigned char *msg;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) );
-
-    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
-        return( ret );
-    }
-
-    if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) );
-        mbedtls_ssl_send_alert_message(
-            ssl,
-            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
-        return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
-    }
-
-    /*
-     * struct {
-     *     uint32 ticket_lifetime_hint;
-     *     opaque ticket<0..2^16-1>;
-     * } NewSessionTicket;
-     *
-     * 0  .  3   ticket_lifetime_hint
-     * 4  .  5   ticket_len (n)
-     * 6  .  5+n ticket content
-     */
-    if( ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET ||
-        ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len( ssl ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET );
-    }
-
-    msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
-
-    lifetime = ( ((uint32_t) msg[0]) << 24 ) | ( msg[1] << 16 ) |
-               ( msg[2] << 8 ) | ( msg[3] );
-
-    ticket_len = ( msg[4] << 8 ) | ( msg[5] );
-
-    if( ticket_len + 6 + mbedtls_ssl_hs_hdr_len( ssl ) != ssl->in_hslen )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %" MBEDTLS_PRINTF_SIZET, ticket_len ) );
-
-    /* We're not waiting for a NewSessionTicket message any more */
-    ssl->handshake->new_session_ticket = 0;
-    ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC;
-
-    /*
-     * Zero-length ticket means the server changed his mind and doesn't want
-     * to send a ticket after all, so just forget it
-     */
-    if( ticket_len == 0 )
-        return( 0 );
-
-    if( ssl->session != NULL && ssl->session->ticket != NULL )
-    {
-        mbedtls_platform_zeroize( ssl->session->ticket,
-                                  ssl->session->ticket_len );
-        mbedtls_free( ssl->session->ticket );
-        ssl->session->ticket = NULL;
-        ssl->session->ticket_len = 0;
-    }
-
-    mbedtls_platform_zeroize( ssl->session_negotiate->ticket,
-                              ssl->session_negotiate->ticket_len );
-    mbedtls_free( ssl->session_negotiate->ticket );
-    ssl->session_negotiate->ticket = NULL;
-    ssl->session_negotiate->ticket_len = 0;
-
-    if( ( ticket = mbedtls_calloc( 1, ticket_len ) ) == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "ticket alloc failed" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
-        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
-    }
-
-    memcpy( ticket, msg + 6, ticket_len );
-
-    ssl->session_negotiate->ticket = ticket;
-    ssl->session_negotiate->ticket_len = ticket_len;
-    ssl->session_negotiate->ticket_lifetime = lifetime;
-
-    /*
-     * RFC 5077 section 3.4:
-     * "If the client receives a session ticket from the server, then it
-     * discards any Session ID that was sent in the ServerHello."
-     */
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket in use, discarding session id" ) );
-    ssl->session_negotiate->id_len = 0;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse new session ticket" ) );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_SESSION_TICKETS */
-
-/*
- * SSL handshake -- client side -- single step
- */
-int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl )
-{
-    int ret = 0;
-
-    if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) );
-
-    if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
-        return( ret );
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
-    {
-        if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
-            return( ret );
-    }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-    /* Change state now, so that it is right in mbedtls_ssl_read_record(), used
-     * by DTLS for dropping out-of-sequence ChangeCipherSpec records */
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    if( ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC &&
-        ssl->handshake->new_session_ticket != 0 )
-    {
-        ssl->state = MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET;
-    }
-#endif
-
-    switch( ssl->state )
-    {
-        case MBEDTLS_SSL_HELLO_REQUEST:
-            ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
-            break;
-
-       /*
-        *  ==>   ClientHello
-        */
-       case MBEDTLS_SSL_CLIENT_HELLO:
-           ret = ssl_write_client_hello( ssl );
-           break;
-
-       /*
-        *  <==   ServerHello
-        *        Certificate
-        *      ( ServerKeyExchange  )
-        *      ( CertificateRequest )
-        *        ServerHelloDone
-        */
-       case MBEDTLS_SSL_SERVER_HELLO:
-           ret = ssl_parse_server_hello( ssl );
-           break;
-
-       case MBEDTLS_SSL_SERVER_CERTIFICATE:
-           ret = mbedtls_ssl_parse_certificate( ssl );
-           break;
-
-       case MBEDTLS_SSL_SERVER_KEY_EXCHANGE:
-           ret = ssl_parse_server_key_exchange( ssl );
-           break;
-
-       case MBEDTLS_SSL_CERTIFICATE_REQUEST:
-           ret = ssl_parse_certificate_request( ssl );
-           break;
-
-       case MBEDTLS_SSL_SERVER_HELLO_DONE:
-           ret = ssl_parse_server_hello_done( ssl );
-           break;
-
-       /*
-        *  ==> ( Certificate/Alert  )
-        *        ClientKeyExchange
-        *      ( CertificateVerify  )
-        *        ChangeCipherSpec
-        *        Finished
-        */
-       case MBEDTLS_SSL_CLIENT_CERTIFICATE:
-           ret = mbedtls_ssl_write_certificate( ssl );
-           break;
-
-       case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:
-           ret = ssl_write_client_key_exchange( ssl );
-           break;
-
-       case MBEDTLS_SSL_CERTIFICATE_VERIFY:
-           ret = ssl_write_certificate_verify( ssl );
-           break;
-
-       case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC:
-           ret = mbedtls_ssl_write_change_cipher_spec( ssl );
-           break;
-
-       case MBEDTLS_SSL_CLIENT_FINISHED:
-           ret = mbedtls_ssl_write_finished( ssl );
-           break;
-
-       /*
-        *  <==   ( NewSessionTicket )
-        *        ChangeCipherSpec
-        *        Finished
-        */
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-       case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET:
-           ret = ssl_parse_new_session_ticket( ssl );
-           break;
-#endif
-
-       case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC:
-           ret = mbedtls_ssl_parse_change_cipher_spec( ssl );
-           break;
-
-       case MBEDTLS_SSL_SERVER_FINISHED:
-           ret = mbedtls_ssl_parse_finished( ssl );
-           break;
-
-       case MBEDTLS_SSL_FLUSH_BUFFERS:
-           MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
-           ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
-           break;
-
-       case MBEDTLS_SSL_HANDSHAKE_WRAPUP:
-           mbedtls_ssl_handshake_wrapup( ssl );
-           break;
-
-       default:
-           MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
-           return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-   }
-
-    return( ret );
-}
-#endif /* MBEDTLS_SSL_CLI_C */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_client.c b/lib/libmbedtls/mbedtls/library/ssl_client.c
new file mode 100644
index 0000000..ea64b21
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/ssl_client.c
@@ -0,0 +1,999 @@
+/*
+ *  TLS 1.2 and 1.3 client-side functions
+ *
+ *  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.
+ *
+ *  This file is part of mbed TLS ( https://tls.mbed.org )
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_SSL_CLI_C)
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
+
+#include <string.h>
+
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
+#include "mbedtls/platform.h"
+
+#include "ssl_client.h"
+#include "ssl_misc.h"
+#include "ssl_tls13_keys.h"
+#include "ssl_debug_helpers.h"
+
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_hostname_ext(mbedtls_ssl_context *ssl,
+                                  unsigned char *buf,
+                                  const unsigned char *end,
+                                  size_t *olen)
+{
+    unsigned char *p = buf;
+    size_t hostname_len;
+
+    *olen = 0;
+
+    if (ssl->hostname == NULL) {
+        return 0;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3,
+                          ("client hello, adding server name extension: %s",
+                           ssl->hostname));
+
+    hostname_len = strlen(ssl->hostname);
+
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, hostname_len + 9);
+
+    /*
+     * Sect. 3, RFC 6066 (TLS Extensions Definitions)
+     *
+     * In order to provide any of the server names, clients MAY include an
+     * extension of type "server_name" in the (extended) client hello. The
+     * "extension_data" field of this extension SHALL contain
+     * "ServerNameList" where:
+     *
+     * struct {
+     *     NameType name_type;
+     *     select (name_type) {
+     *         case host_name: HostName;
+     *     } name;
+     * } ServerName;
+     *
+     * enum {
+     *     host_name(0), (255)
+     * } NameType;
+     *
+     * opaque HostName<1..2^16-1>;
+     *
+     * struct {
+     *     ServerName server_name_list<1..2^16-1>
+     * } ServerNameList;
+     *
+     */
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SERVERNAME, p, 0);
+    p += 2;
+
+    MBEDTLS_PUT_UINT16_BE(hostname_len + 5, p, 0);
+    p += 2;
+
+    MBEDTLS_PUT_UINT16_BE(hostname_len + 3, p, 0);
+    p += 2;
+
+    *p++ = MBEDTLS_BYTE_0(MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME);
+
+    MBEDTLS_PUT_UINT16_BE(hostname_len, p, 0);
+    p += 2;
+
+    memcpy(p, ssl->hostname, hostname_len);
+
+    *olen = hostname_len + 9;
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_SERVERNAME);
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+    return 0;
+}
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+
+#if defined(MBEDTLS_SSL_ALPN)
+/*
+ * ssl_write_alpn_ext()
+ *
+ * Structure of the application_layer_protocol_negotiation extension in
+ * ClientHello:
+ *
+ * opaque ProtocolName<1..2^8-1>;
+ *
+ * struct {
+ *     ProtocolName protocol_name_list<2..2^16-1>
+ * } ProtocolNameList;
+ *
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_alpn_ext(mbedtls_ssl_context *ssl,
+                              unsigned char *buf,
+                              const unsigned char *end,
+                              size_t *out_len)
+{
+    unsigned char *p = buf;
+
+    *out_len = 0;
+
+    if (ssl->conf->alpn_list == NULL) {
+        return 0;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding alpn extension"));
+
+
+    /* Check we have enough space for the extension type (2 bytes), the
+     * extension length (2 bytes) and the protocol_name_list length (2 bytes).
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6);
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ALPN, p, 0);
+    /* Skip writing extension and list length for now */
+    p += 6;
+
+    /*
+     * opaque ProtocolName<1..2^8-1>;
+     *
+     * struct {
+     *     ProtocolName protocol_name_list<2..2^16-1>
+     * } ProtocolNameList;
+     */
+    for (const char **cur = ssl->conf->alpn_list; *cur != NULL; cur++) {
+        /*
+         * mbedtls_ssl_conf_set_alpn_protocols() checked that the length of
+         * protocol names is less than 255.
+         */
+        size_t protocol_name_len = strlen(*cur);
+
+        MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1 + protocol_name_len);
+        *p++ = (unsigned char) protocol_name_len;
+        memcpy(p, *cur, protocol_name_len);
+        p += protocol_name_len;
+    }
+
+    *out_len = p - buf;
+
+    /* List length = *out_len - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */
+    MBEDTLS_PUT_UINT16_BE(*out_len - 6, buf, 4);
+
+    /* Extension length = *out_len - 2 (ext_type) - 2 (ext_len) */
+    MBEDTLS_PUT_UINT16_BE(*out_len - 4, buf, 2);
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_ALPN);
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+    return 0;
+}
+#endif /* MBEDTLS_SSL_ALPN */
+
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+/*
+ * Function for writing a supported groups (TLS 1.3) or supported elliptic
+ * curves (TLS 1.2) extension.
+ *
+ * The "extension_data" field of a supported groups extension contains a
+ * "NamedGroupList" value (TLS 1.3 RFC8446):
+ *      enum {
+ *          secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019),
+ *          x25519(0x001D), x448(0x001E),
+ *          ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102),
+ *          ffdhe6144(0x0103), ffdhe8192(0x0104),
+ *          ffdhe_private_use(0x01FC..0x01FF),
+ *          ecdhe_private_use(0xFE00..0xFEFF),
+ *          (0xFFFF)
+ *      } NamedGroup;
+ *      struct {
+ *          NamedGroup named_group_list<2..2^16-1>;
+ *      } NamedGroupList;
+ *
+ * The "extension_data" field of a supported elliptic curves extension contains
+ * a "NamedCurveList" value (TLS 1.2 RFC 8422):
+ * enum {
+ *      deprecated(1..22),
+ *      secp256r1 (23), secp384r1 (24), secp521r1 (25),
+ *      x25519(29), x448(30),
+ *      reserved (0xFE00..0xFEFF),
+ *      deprecated(0xFF01..0xFF02),
+ *      (0xFFFF)
+ *  } NamedCurve;
+ * struct {
+ *      NamedCurve named_curve_list<2..2^16-1>
+ *  } NamedCurveList;
+ *
+ * The TLS 1.3 supported groups extension was defined to be a compatible
+ * generalization of the TLS 1.2 supported elliptic curves extension. They both
+ * share the same extension identifier.
+ *
+ * DHE groups are not supported yet.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_supported_groups_ext(mbedtls_ssl_context *ssl,
+                                          unsigned char *buf,
+                                          const unsigned char *end,
+                                          size_t *out_len)
+{
+    unsigned char *p = buf;
+    unsigned char *named_group_list; /* Start of named_group_list */
+    size_t named_group_list_len;     /* Length of named_group_list */
+    const uint16_t *group_list = mbedtls_ssl_get_groups(ssl);
+
+    *out_len = 0;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding supported_groups extension"));
+
+    /* Check if we have space for header and length fields:
+     * - extension_type            (2 bytes)
+     * - extension_data_length     (2 bytes)
+     * - named_group_list_length   (2 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6);
+    p += 6;
+
+    named_group_list = p;
+
+    if (group_list == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_CONFIG;
+    }
+
+    for (; *group_list != 0; group_list++) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("got supported group(%04x)", *group_list));
+
+#if defined(MBEDTLS_ECP_C)
+        if ((mbedtls_ssl_conf_is_tls13_enabled(ssl->conf) &&
+             mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list)) ||
+            (mbedtls_ssl_conf_is_tls12_enabled(ssl->conf) &&
+             mbedtls_ssl_tls12_named_group_is_ecdhe(*group_list))) {
+            if (mbedtls_ssl_get_ecp_group_id_from_tls_id(*group_list) ==
+                MBEDTLS_ECP_DP_NONE) {
+                continue;
+            }
+            MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);
+            MBEDTLS_PUT_UINT16_BE(*group_list, p, 0);
+            p += 2;
+            MBEDTLS_SSL_DEBUG_MSG(3, ("NamedGroup: %s ( %x )",
+                                      mbedtls_ssl_get_curve_name_from_tls_id(*group_list),
+                                      *group_list));
+        }
+#endif /* MBEDTLS_ECP_C */
+        /* Add DHE groups here */
+
+    }
+
+    /* Length of named_group_list */
+    named_group_list_len = p - named_group_list;
+    if (named_group_list_len == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("No group available."));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    /* Write extension_type */
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_GROUPS, buf, 0);
+    /* Write extension_data_length */
+    MBEDTLS_PUT_UINT16_BE(named_group_list_len + 2, buf, 2);
+    /* Write length of named_group_list */
+    MBEDTLS_PUT_UINT16_BE(named_group_list_len, buf, 4);
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "Supported groups extension",
+                          buf + 4, named_group_list_len + 2);
+
+    *out_len = p - buf;
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    mbedtls_ssl_tls13_set_hs_sent_ext_mask(
+        ssl, MBEDTLS_TLS_EXT_SUPPORTED_GROUPS);
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+    return 0;
+}
+
+#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
+          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_client_hello_cipher_suites(
+    mbedtls_ssl_context *ssl,
+    unsigned char *buf,
+    unsigned char *end,
+    int *tls12_uses_ec,
+    size_t *out_len)
+{
+    unsigned char *p = buf;
+    const int *ciphersuite_list;
+    unsigned char *cipher_suites; /* Start of the cipher_suites list */
+    size_t cipher_suites_len;
+
+    *tls12_uses_ec = 0;
+    *out_len = 0;
+
+    /*
+     * Ciphersuite list
+     *
+     * This is a list of the symmetric cipher options supported by
+     * the client, specifically the record protection algorithm
+     * ( including secret key length ) and a hash to be used with
+     * HKDF, in descending order of client preference.
+     */
+    ciphersuite_list = ssl->conf->ciphersuite_list;
+
+    /* Check there is space for the cipher suite list length (2 bytes). */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);
+    p += 2;
+
+    /* Write cipher_suites
+     * CipherSuite cipher_suites<2..2^16-2>;
+     */
+    cipher_suites = p;
+    for (size_t i = 0; ciphersuite_list[i] != 0; i++) {
+        int cipher_suite = ciphersuite_list[i];
+        const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+
+        ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite);
+
+        if (mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info,
+                                             ssl->handshake->min_tls_version,
+                                             ssl->tls_version) != 0) {
+            continue;
+        }
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
+        (defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+        defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED))
+        *tls12_uses_ec |= mbedtls_ssl_ciphersuite_uses_ec(ciphersuite_info);
+#endif
+
+        MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, add ciphersuite: %04x, %s",
+                                  (unsigned int) cipher_suite,
+                                  ciphersuite_info->name));
+
+        /* Check there is space for the cipher suite identifier (2 bytes). */
+        MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);
+        MBEDTLS_PUT_UINT16_BE(cipher_suite, p, 0);
+        p += 2;
+    }
+
+    /*
+     * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+     */
+    int renegotiating = 0;
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    renegotiating = (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE);
+#endif
+    if (!renegotiating) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("adding EMPTY_RENEGOTIATION_INFO_SCSV"));
+        MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);
+        MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO, p, 0);
+        p += 2;
+    }
+
+    /* Write the cipher_suites length in number of bytes */
+    cipher_suites_len = p - cipher_suites;
+    MBEDTLS_PUT_UINT16_BE(cipher_suites_len, buf, 0);
+    MBEDTLS_SSL_DEBUG_MSG(3,
+                          ("client hello, got %" MBEDTLS_PRINTF_SIZET " cipher suites",
+                           cipher_suites_len/2));
+
+    /* Output the total length of cipher_suites field. */
+    *out_len = p - buf;
+
+    return 0;
+}
+
+/*
+ * Structure of the TLS 1.3 ClientHello message:
+ *
+ *    struct {
+ *        ProtocolVersion legacy_version = 0x0303;    // TLS v1.2
+ *        Random random;
+ *        opaque legacy_session_id<0..32>;
+ *        CipherSuite cipher_suites<2..2^16-2>;
+ *        opaque legacy_compression_methods<1..2^8-1>;
+ *        Extension extensions<8..2^16-1>;
+ *    } ClientHello;
+ *
+ * Structure of the (D)TLS 1.2 ClientHello message:
+ *
+ * struct {
+ *     ProtocolVersion client_version;
+ *     Random random;
+ *     SessionID session_id;
+ *     opaque cookie<0..2^8-1>; // DTLS 1.2 ONLY
+ *     CipherSuite cipher_suites<2..2^16-2>;
+ *     CompressionMethod compression_methods<1..2^8-1>;
+ *     select (extensions_present) {
+ *         case false:
+ *             struct {};
+ *         case true:
+ *             Extension extensions<0..2^16-1>;
+ *     };
+ * } ClientHello;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_client_hello_body(mbedtls_ssl_context *ssl,
+                                       unsigned char *buf,
+                                       unsigned char *end,
+                                       size_t *out_len,
+                                       size_t *binders_len)
+{
+    int ret;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    unsigned char *p = buf;
+    unsigned char *p_extensions_len; /* Pointer to extensions length */
+    size_t output_len;               /* Length of buffer used by function */
+    size_t extensions_len;           /* Length of the list of extensions*/
+    int tls12_uses_ec = 0;
+
+    *out_len = 0;
+    *binders_len = 0;
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    unsigned char propose_tls12 =
+        (handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2)
+        &&
+        (MBEDTLS_SSL_VERSION_TLS1_2 <= ssl->tls_version);
+#endif
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    unsigned char propose_tls13 =
+        (handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_3)
+        &&
+        (MBEDTLS_SSL_VERSION_TLS1_3 <= ssl->tls_version);
+#endif
+
+    /*
+     * Write client_version (TLS 1.2) or legacy_version (TLS 1.3)
+     *
+     * In all cases this is the TLS 1.2 version.
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);
+    mbedtls_ssl_write_version(p, ssl->conf->transport,
+                              MBEDTLS_SSL_VERSION_TLS1_2);
+    p += 2;
+
+    /* ...
+     * Random random;
+     * ...
+     *
+     * The random bytes have been prepared by ssl_prepare_client_hello() into
+     * the handshake->randbytes buffer and are copied here into the output
+     * buffer.
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, MBEDTLS_CLIENT_HELLO_RANDOM_LEN);
+    memcpy(p, handshake->randbytes, MBEDTLS_CLIENT_HELLO_RANDOM_LEN);
+    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, random bytes",
+                          p, MBEDTLS_CLIENT_HELLO_RANDOM_LEN);
+    p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN;
+
+    /* TLS 1.2:
+     * ...
+     * SessionID session_id;
+     * ...
+     * with
+     * opaque SessionID<0..32>;
+     *
+     * TLS 1.3:
+     * ...
+     * opaque legacy_session_id<0..32>;
+     * ...
+     *
+     * The (legacy) session identifier bytes have been prepared by
+     * ssl_prepare_client_hello() into the ssl->session_negotiate->id buffer
+     * and are copied here into the output buffer.
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, ssl->session_negotiate->id_len + 1);
+    *p++ = (unsigned char) ssl->session_negotiate->id_len;
+    memcpy(p, ssl->session_negotiate->id, ssl->session_negotiate->id_len);
+    p += ssl->session_negotiate->id_len;
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "session id", ssl->session_negotiate->id,
+                          ssl->session_negotiate->id_len);
+
+    /* DTLS 1.2 ONLY
+     * ...
+     * opaque cookie<0..2^8-1>;
+     * ...
+     */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+#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->cookie_len);
+            cookie_len = handshake->cookie_len;
+        }
+
+        MBEDTLS_SSL_CHK_BUF_PTR(p, end, cookie_len + 1);
+        *p++ = (unsigned char) cookie_len;
+        if (cookie_len > 0) {
+            memcpy(p, handshake->cookie, cookie_len);
+            p += cookie_len;
+        }
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_DTLS */
+
+    /* Write cipher_suites */
+    ret = ssl_write_client_hello_cipher_suites(ssl, p, end,
+                                               &tls12_uses_ec,
+                                               &output_len);
+    if (ret != 0) {
+        return ret;
+    }
+    p += output_len;
+
+    /* Write legacy_compression_methods (TLS 1.3) or
+     * compression_methods (TLS 1.2)
+     *
+     * For every TLS 1.3 ClientHello, this vector MUST contain exactly
+     * one byte set to zero, which corresponds to the 'null' compression
+     * method in prior versions of TLS.
+     *
+     * For TLS 1.2 ClientHello, for security reasons we do not support
+     * compression anymore, thus also just the 'null' compression method.
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);
+    *p++ = 1;
+    *p++ = MBEDTLS_SSL_COMPRESS_NULL;
+
+    /* Write extensions */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    /* Keeping track of the included extensions */
+    handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE;
+#endif
+
+    /* First write extensions, then the total length */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);
+    p_extensions_len = p;
+    p += 2;
+
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    /* Write server name extension */
+    ret = ssl_write_hostname_ext(ssl, p, end, &output_len);
+    if (ret != 0) {
+        return ret;
+    }
+    p += output_len;
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+
+#if defined(MBEDTLS_SSL_ALPN)
+    ret = ssl_write_alpn_ext(ssl, p, end, &output_len);
+    if (ret != 0) {
+        return ret;
+    }
+    p += output_len;
+#endif /* MBEDTLS_SSL_ALPN */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    if (propose_tls13) {
+        ret = mbedtls_ssl_tls13_write_client_hello_exts(ssl, p, end,
+                                                        &output_len);
+        if (ret != 0) {
+            return ret;
+        }
+        p += output_len;
+    }
+#endif
+
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+    if (
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        (propose_tls13 &&
+         mbedtls_ssl_conf_tls13_some_ephemeral_enabled(ssl)) ||
+#endif
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        (propose_tls12 && tls12_uses_ec) ||
+#endif
+        0) {
+        ret = ssl_write_supported_groups_ext(ssl, p, end, &output_len);
+        if (ret != 0) {
+            return ret;
+        }
+        p += output_len;
+    }
+#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+    if (
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        (propose_tls13 && mbedtls_ssl_conf_tls13_ephemeral_enabled(ssl)) ||
+#endif
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        propose_tls12 ||
+#endif
+        0) {
+        ret = mbedtls_ssl_write_sig_alg_ext(ssl, p, end, &output_len);
+        if (ret != 0) {
+            return ret;
+        }
+        p += output_len;
+    }
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    if (propose_tls12) {
+        ret = mbedtls_ssl_tls12_write_client_hello_exts(ssl, p, end,
+                                                        tls12_uses_ec,
+                                                        &output_len);
+        if (ret != 0) {
+            return ret;
+        }
+        p += output_len;
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    /* The "pre_shared_key" extension (RFC 8446 Section 4.2.11)
+     * MUST be the last extension in the ClientHello.
+     */
+    if (propose_tls13 && mbedtls_ssl_conf_tls13_some_psk_enabled(ssl)) {
+        ret = mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext(
+            ssl, p, end, &output_len, binders_len);
+        if (ret != 0) {
+            return ret;
+        }
+        p += output_len;
+    }
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
+
+    /* Write the length of the list of extensions. */
+    extensions_len = p - p_extensions_len - 2;
+
+    if (extensions_len == 0) {
+        p = p_extensions_len;
+    } else {
+        MBEDTLS_PUT_UINT16_BE(extensions_len, p_extensions_len, 0);
+        MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, total extension length: %" \
+                                  MBEDTLS_PRINTF_SIZET, extensions_len));
+        MBEDTLS_SSL_DEBUG_BUF(3, "client hello extensions",
+                              p_extensions_len, extensions_len);
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    MBEDTLS_SSL_PRINT_EXTS(
+        3, MBEDTLS_SSL_HS_CLIENT_HELLO, handshake->sent_extensions);
+#endif
+
+    *out_len = p - buf;
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_generate_random(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *randbytes = ssl->handshake->randbytes;
+    size_t gmt_unix_time_len = 0;
+
+    /*
+     * Generate the random bytes
+     *
+     * TLS 1.2 case:
+     * struct {
+     *     uint32 gmt_unix_time;
+     *     opaque random_bytes[28];
+     * } Random;
+     *
+     * TLS 1.3 case:
+     * opaque Random[32];
+     */
+    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {
+#if defined(MBEDTLS_HAVE_TIME)
+        mbedtls_time_t gmt_unix_time = mbedtls_time(NULL);
+        MBEDTLS_PUT_UINT32_BE(gmt_unix_time, randbytes, 0);
+        gmt_unix_time_len = 4;
+
+        MBEDTLS_SSL_DEBUG_MSG(3,
+                              ("client hello, current time: %" MBEDTLS_PRINTF_LONGLONG,
+                               (long long) gmt_unix_time));
+#endif /* MBEDTLS_HAVE_TIME */
+    }
+
+    ret = ssl->conf->f_rng(ssl->conf->p_rng,
+                           randbytes + gmt_unix_time_len,
+                           MBEDTLS_CLIENT_HELLO_RANDOM_LEN - gmt_unix_time_len);
+    return ret;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_prepare_client_hello(mbedtls_ssl_context *ssl)
+{
+    int ret;
+    size_t session_id_len;
+    mbedtls_ssl_session *session_negotiate = ssl->session_negotiate;
+
+    if (session_negotiate == NULL) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
+    defined(MBEDTLS_SSL_SESSION_TICKETS) && \
+    defined(MBEDTLS_HAVE_TIME)
+
+    /* Check if a tls13 ticket has been configured. */
+    if (ssl->handshake->resume != 0 &&
+        session_negotiate->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 &&
+        session_negotiate->ticket != NULL) {
+        mbedtls_time_t now = mbedtls_time(NULL);
+        uint64_t age = (uint64_t) (now - session_negotiate->ticket_received);
+        if (session_negotiate->ticket_received > now ||
+            age > session_negotiate->ticket_lifetime) {
+            /* Without valid ticket, disable session resumption.*/
+            MBEDTLS_SSL_DEBUG_MSG(
+                3, ("Ticket expired, disable session resumption"));
+            ssl->handshake->resume = 0;
+        }
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 &&
+          MBEDTLS_SSL_SESSION_TICKETS &&
+          MBEDTLS_HAVE_TIME */
+
+    if (ssl->conf->f_rng == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided"));
+        return MBEDTLS_ERR_SSL_NO_RNG;
+    }
+
+    /* Bet on the highest configured version if we are not in a TLS 1.2
+     * renegotiation or session resumption.
+     */
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {
+        ssl->handshake->min_tls_version = ssl->tls_version;
+    } else
+#endif
+    {
+        if (ssl->handshake->resume) {
+            ssl->tls_version = session_negotiate->tls_version;
+            ssl->handshake->min_tls_version = ssl->tls_version;
+        } else {
+            ssl->tls_version = ssl->conf->max_tls_version;
+            ssl->handshake->min_tls_version = ssl->conf->min_tls_version;
+        }
+    }
+
+    /*
+     * Generate the random bytes, except when responding to a verify request
+     * where we MUST reuse the previously generated random bytes
+     * (RFC 6347 4.2.1).
+     */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) ||
+        (ssl->handshake->cookie == NULL))
+#endif
+    {
+        ret = ssl_generate_random(ssl);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "Random bytes generation failed", ret);
+            return ret;
+        }
+    }
+
+    /*
+     * Prepare session identifier. At that point, the length of the session
+     * identifier in the SSL context `ssl->session_negotiate->id_len` is equal
+     * to zero, except in the case of a TLS 1.2 session renegotiation or
+     * session resumption.
+     */
+    session_id_len = session_negotiate->id_len;
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {
+        if (session_id_len < 16 || session_id_len > 32 ||
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+            ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ||
+#endif
+            ssl->handshake->resume == 0) {
+            session_id_len = 0;
+        }
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+        /*
+         * RFC 5077 section 3.4: "When presenting a ticket, the client MAY
+         * generate and include a Session ID in the TLS ClientHello."
+         */
+        int renegotiating = 0;
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+        if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {
+            renegotiating = 1;
+        }
+#endif
+        if (!renegotiating) {
+            if ((session_negotiate->ticket != NULL) &&
+                (session_negotiate->ticket_len != 0)) {
+                session_id_len = 32;
+            }
+        }
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
+        /*
+         * Create a legacy session identifier for the purpose of middlebox
+         * compatibility only if one has not been created already, which is
+         * the case if we are here for the TLS 1.3 second ClientHello.
+         *
+         * Versions of TLS before TLS 1.3 supported a "session resumption"
+         * feature which has been merged with pre-shared keys in TLS 1.3
+         * version. A client which has a cached session ID set by a pre-TLS 1.3
+         * server SHOULD set this field to that value. In compatibility mode,
+         * this field MUST be non-empty, so a client not offering a pre-TLS 1.3
+         * session MUST generate a new 32-byte value. This value need not be
+         * random but SHOULD be unpredictable to avoid implementations fixating
+         * on a specific value (also known as ossification). Otherwise, it MUST
+         * be set as a zero-length vector ( i.e., a zero-valued single byte
+         * length field ).
+         */
+        session_id_len = 32;
+    }
+#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
+
+    if (session_id_len != session_negotiate->id_len) {
+        session_negotiate->id_len = session_id_len;
+        if (session_id_len > 0) {
+            ret = ssl->conf->f_rng(ssl->conf->p_rng,
+                                   session_negotiate->id,
+                                   session_id_len);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "creating session id failed", ret);
+                return ret;
+            }
+        }
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
+    defined(MBEDTLS_SSL_SESSION_TICKETS) && \
+    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3  &&
+        ssl->handshake->resume) {
+        int hostname_mismatch = ssl->hostname != NULL ||
+                                session_negotiate->hostname != NULL;
+        if (ssl->hostname != NULL && session_negotiate->hostname != NULL) {
+            hostname_mismatch = strcmp(
+                ssl->hostname, session_negotiate->hostname) != 0;
+        }
+
+        if (hostname_mismatch) {
+            MBEDTLS_SSL_DEBUG_MSG(
+                1, ("Hostname mismatch the session ticket, "
+                    "disable session resumption."));
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+    } else {
+        return mbedtls_ssl_session_set_hostname(session_negotiate,
+                                                ssl->hostname);
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 &&
+          MBEDTLS_SSL_SESSION_TICKETS &&
+          MBEDTLS_SSL_SERVER_NAME_INDICATION */
+
+    return 0;
+}
+/*
+ * Write ClientHello handshake message.
+ * Handler for MBEDTLS_SSL_CLIENT_HELLO
+ */
+int mbedtls_ssl_write_client_hello(mbedtls_ssl_context *ssl)
+{
+    int ret = 0;
+    unsigned char *buf;
+    size_t buf_len, msg_len, binders_len;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write client hello"));
+
+    MBEDTLS_SSL_PROC_CHK(ssl_prepare_client_hello(ssl));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(
+                             ssl, MBEDTLS_SSL_HS_CLIENT_HELLO,
+                             &buf, &buf_len));
+
+    MBEDTLS_SSL_PROC_CHK(ssl_write_client_hello_body(ssl, buf,
+                                                     buf + buf_len,
+                                                     &msg_len,
+                                                     &binders_len));
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        ssl->out_msglen = msg_len + 4;
+        mbedtls_ssl_send_flight_completed(ssl);
+
+        /*
+         * The two functions below may try to send data on the network and
+         * can return with the MBEDTLS_ERR_SSL_WANT_READ error code when they
+         * fail to do so and the transmission has to be retried later. In that
+         * case as in fatal error cases, we return immediately. But we must have
+         * set the handshake state to the next state at that point to ensure
+         * that we will not write and send again a ClientHello when we
+         * eventually succeed in sending the pending data.
+         */
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO);
+
+        if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret);
+            return ret;
+        }
+
+        if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret);
+            return ret;
+        }
+    } else
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_DTLS */
+    {
+
+        ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl,
+                                                 MBEDTLS_SSL_HS_CLIENT_HELLO,
+                                                 msg_len);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_add_hs_hdr_to_checksum", ret);
+            return ret;
+        }
+        ret = ssl->handshake->update_checksum(ssl, buf, msg_len - binders_len);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret);
+            return ret;
+        }
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+        if (binders_len > 0) {
+            MBEDTLS_SSL_PROC_CHK(
+                mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext(
+                    ssl, buf + msg_len - binders_len, buf + msg_len));
+            ret = ssl->handshake->update_checksum(ssl, buf + msg_len - binders_len,
+                                                  binders_len);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret);
+                return ret;
+            }
+        }
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
+
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl,
+                                                              buf_len,
+                                                              msg_len));
+
+        /*
+         * Set next state. Note that if TLS 1.3 is proposed, this may be
+         * overwritten by mbedtls_ssl_tls13_finalize_client_hello().
+         */
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO);
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        if (ssl->handshake->min_tls_version <=  MBEDTLS_SSL_VERSION_TLS1_3 &&
+            MBEDTLS_SSL_VERSION_TLS1_3 <= ssl->tls_version) {
+            ret = mbedtls_ssl_tls13_finalize_client_hello(ssl);
+        }
+#endif
+    }
+
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write client hello"));
+    return ret;
+}
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 || MBEDTLS_SSL_PROTO_TLS1_2 */
+#endif /* MBEDTLS_SSL_CLI_C */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_client.h b/lib/libmbedtls/mbedtls/library/ssl_client.h
new file mode 100644
index 0000000..f57bea3
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/ssl_client.h
@@ -0,0 +1,34 @@
+/**
+ *  TLS 1.2 and 1.3 client-side functions
+ *
+ *  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_SSL_CLIENT_H
+#define MBEDTLS_SSL_CLIENT_H
+
+#include "common.h"
+
+#if defined(MBEDTLS_SSL_TLS_C)
+#include "ssl_misc.h"
+#endif
+
+#include <stddef.h>
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_write_client_hello(mbedtls_ssl_context *ssl);
+
+#endif /* MBEDTLS_SSL_CLIENT_H */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_cookie.c b/lib/libmbedtls/mbedtls/library/ssl_cookie.c
index 3781796..ef4d188 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_cookie.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_cookie.c
@@ -25,145 +25,191 @@
 
 #if defined(MBEDTLS_SSL_COOKIE_C)
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#define mbedtls_calloc    calloc
-#define mbedtls_free      free
-#endif
 
 #include "mbedtls/ssl_cookie.h"
-#include "mbedtls/ssl_internal.h"
+#include "ssl_misc.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/constant_time.h"
 
+#include "mbedtls/legacy_or_psa.h"
+
 #include <string.h>
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_ssl_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+#endif
+
 /*
- * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is
- * available. Try SHA-256 first, 512 wastes resources since we need to stay
- * with max 32 bytes of cookie for DTLS 1.0
+ * If DTLS is in use, then at least one of SHA-256 or SHA-384 is
+ * available. Try SHA-256 first as 384 wastes resources
  */
-#if defined(MBEDTLS_SHA256_C)
-#define COOKIE_MD           MBEDTLS_MD_SHA224
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA)
+#define COOKIE_MD           MBEDTLS_MD_SHA256
 #define COOKIE_MD_OUTLEN    32
 #define COOKIE_HMAC_LEN     28
-#elif defined(MBEDTLS_SHA512_C)
+#elif defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA)
 #define COOKIE_MD           MBEDTLS_MD_SHA384
 #define COOKIE_MD_OUTLEN    48
 #define COOKIE_HMAC_LEN     28
-#elif defined(MBEDTLS_SHA1_C)
-#define COOKIE_MD           MBEDTLS_MD_SHA1
-#define COOKIE_MD_OUTLEN    20
-#define COOKIE_HMAC_LEN     20
 #else
-#error "DTLS hello verify needs SHA-1 or SHA-2"
+#error "DTLS hello verify needs SHA-256 or SHA-384"
 #endif
 
 /*
  * Cookies are formed of a 4-bytes timestamp (or serial number) and
  * an HMAC of timestamp and client ID.
  */
-#define COOKIE_LEN      ( 4 + COOKIE_HMAC_LEN )
+#define COOKIE_LEN      (4 + COOKIE_HMAC_LEN)
 
-void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx )
+void mbedtls_ssl_cookie_init(mbedtls_ssl_cookie_ctx *ctx)
 {
-    mbedtls_md_init( &ctx->hmac_ctx );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    ctx->psa_hmac_key = MBEDTLS_SVC_KEY_ID_INIT;
+#else
+    mbedtls_md_init(&ctx->hmac_ctx);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 #if !defined(MBEDTLS_HAVE_TIME)
     ctx->serial = 0;
 #endif
     ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT;
 
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_init( &ctx->mutex );
+    mbedtls_mutex_init(&ctx->mutex);
 #endif
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
 }
 
-void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay )
+void mbedtls_ssl_cookie_set_timeout(mbedtls_ssl_cookie_ctx *ctx, unsigned long delay)
 {
     ctx->timeout = delay;
 }
 
-void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx )
+void mbedtls_ssl_cookie_free(mbedtls_ssl_cookie_ctx *ctx)
 {
-    mbedtls_md_free( &ctx->hmac_ctx );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_destroy_key(ctx->psa_hmac_key);
+#else
+    mbedtls_md_free(&ctx->hmac_ctx);
 
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_free( &ctx->mutex );
+    mbedtls_mutex_free(&ctx->mutex);
 #endif
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_cookie_ctx));
 }
 
-int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx,
-                      int (*f_rng)(void *, unsigned char *, size_t),
-                      void *p_rng )
+int mbedtls_ssl_cookie_setup(mbedtls_ssl_cookie_ctx *ctx,
+                             int (*f_rng)(void *, unsigned char *, size_t),
+                             void *p_rng)
 {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_algorithm_t alg;
+
+    (void) f_rng;
+    (void) p_rng;
+
+    alg = mbedtls_hash_info_psa_from_md(COOKIE_MD);
+    if (alg == 0) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    ctx->psa_hmac_alg = PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(alg),
+                                              COOKIE_HMAC_LEN);
+
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_MESSAGE |
+                            PSA_KEY_USAGE_SIGN_MESSAGE);
+    psa_set_key_algorithm(&attributes, ctx->psa_hmac_alg);
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
+    psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(COOKIE_MD_OUTLEN));
+
+    if ((status = psa_generate_key(&attributes,
+                                   &ctx->psa_hmac_key)) != PSA_SUCCESS) {
+        return PSA_TO_MBEDTLS_ERR(status);
+    }
+#else
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char key[COOKIE_MD_OUTLEN];
 
-    if( ( ret = f_rng( p_rng, key, sizeof( key ) ) ) != 0 )
-        return( ret );
+    if ((ret = f_rng(p_rng, key, sizeof(key))) != 0) {
+        return ret;
+    }
 
-    ret = mbedtls_md_setup( &ctx->hmac_ctx, mbedtls_md_info_from_type( COOKIE_MD ), 1 );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_md_setup(&ctx->hmac_ctx, mbedtls_md_info_from_type(COOKIE_MD), 1);
+    if (ret != 0) {
+        return ret;
+    }
 
-    ret = mbedtls_md_hmac_starts( &ctx->hmac_ctx, key, sizeof( key ) );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_md_hmac_starts(&ctx->hmac_ctx, key, sizeof(key));
+    if (ret != 0) {
+        return ret;
+    }
 
-    mbedtls_platform_zeroize( key, sizeof( key ) );
+    mbedtls_platform_zeroize(key, sizeof(key));
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-    return( 0 );
+    return 0;
 }
 
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
 /*
  * Generate the HMAC part of a cookie
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx,
-                            const unsigned char time[4],
-                            unsigned char **p, unsigned char *end,
-                            const unsigned char *cli_id, size_t cli_id_len )
+static int ssl_cookie_hmac(mbedtls_md_context_t *hmac_ctx,
+                           const unsigned char time[4],
+                           unsigned char **p, unsigned char *end,
+                           const unsigned char *cli_id, size_t cli_id_len)
 {
     unsigned char hmac_out[COOKIE_MD_OUTLEN];
 
-    MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_HMAC_LEN );
+    MBEDTLS_SSL_CHK_BUF_PTR(*p, end, COOKIE_HMAC_LEN);
 
-    if( mbedtls_md_hmac_reset(  hmac_ctx ) != 0 ||
-        mbedtls_md_hmac_update( hmac_ctx, time, 4 ) != 0 ||
-        mbedtls_md_hmac_update( hmac_ctx, cli_id, cli_id_len ) != 0 ||
-        mbedtls_md_hmac_finish( hmac_ctx, hmac_out ) != 0 )
-    {
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    if (mbedtls_md_hmac_reset(hmac_ctx) != 0 ||
+        mbedtls_md_hmac_update(hmac_ctx, time, 4) != 0 ||
+        mbedtls_md_hmac_update(hmac_ctx, cli_id, cli_id_len) != 0 ||
+        mbedtls_md_hmac_finish(hmac_ctx, hmac_out) != 0) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    memcpy( *p, hmac_out, COOKIE_HMAC_LEN );
+    memcpy(*p, hmac_out, COOKIE_HMAC_LEN);
     *p += COOKIE_HMAC_LEN;
 
-    return( 0 );
+    return 0;
 }
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
 
 /*
  * Generate cookie for DTLS ClientHello verification
  */
-int mbedtls_ssl_cookie_write( void *p_ctx,
-                      unsigned char **p, unsigned char *end,
-                      const unsigned char *cli_id, size_t cli_id_len )
+int mbedtls_ssl_cookie_write(void *p_ctx,
+                             unsigned char **p, unsigned char *end,
+                             const unsigned char *cli_id, size_t cli_id_len)
 {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t sign_mac_length = 0;
+#endif
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx;
     unsigned long t;
 
-    if( ctx == NULL || cli_id == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ctx == NULL || cli_id == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_LEN );
+    MBEDTLS_SSL_CHK_BUF_PTR(*p, end, COOKIE_LEN);
 
 #if defined(MBEDTLS_HAVE_TIME)
-    t = (unsigned long) mbedtls_time( NULL );
+    t = (unsigned long) mbedtls_time(NULL);
 #else
     t = ctx->serial++;
 #endif
@@ -171,88 +217,174 @@
     MBEDTLS_PUT_UINT32_BE(t, *p, 0);
     *p += 4;
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    status = psa_mac_sign_setup(&operation, ctx->psa_hmac_key,
+                                ctx->psa_hmac_alg);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        goto exit;
+    }
+
+    status = psa_mac_update(&operation, *p - 4, 4);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        goto exit;
+    }
+
+    status = psa_mac_update(&operation, cli_id, cli_id_len);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        goto exit;
+    }
+
+    status = psa_mac_sign_finish(&operation, *p, COOKIE_MD_OUTLEN,
+                                 &sign_mac_length);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        goto exit;
+    }
+
+    *p += COOKIE_HMAC_LEN;
+
+    ret = 0;
+#else
 #if defined(MBEDTLS_THREADING_C)
-    if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret ) );
+    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret);
+    }
 #endif
 
-    ret = ssl_cookie_hmac( &ctx->hmac_ctx, *p - 4,
-                           p, end, cli_id, cli_id_len );
+    ret = ssl_cookie_hmac(&ctx->hmac_ctx, *p - 4,
+                          p, end, cli_id, cli_id_len);
 
 #if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR,
-                MBEDTLS_ERR_THREADING_MUTEX_ERROR ) );
+    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR,
+                                 MBEDTLS_ERR_THREADING_MUTEX_ERROR);
+    }
 #endif
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-    return( ret );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+exit:
+    status = psa_mac_abort(&operation);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    return ret;
 }
 
 /*
  * Check a cookie
  */
-int mbedtls_ssl_cookie_check( void *p_ctx,
-                      const unsigned char *cookie, size_t cookie_len,
-                      const unsigned char *cli_id, size_t cli_id_len )
+int mbedtls_ssl_cookie_check(void *p_ctx,
+                             const unsigned char *cookie, size_t cookie_len,
+                             const unsigned char *cli_id, size_t cli_id_len)
 {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+#else
     unsigned char ref_hmac[COOKIE_HMAC_LEN];
-    int ret = 0;
     unsigned char *p = ref_hmac;
+#endif
+    int ret = 0;
     mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx;
     unsigned long cur_time, cookie_time;
 
-    if( ctx == NULL || cli_id == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ctx == NULL || cli_id == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    if( cookie_len != COOKIE_LEN )
-        return( -1 );
+    if (cookie_len != COOKIE_LEN) {
+        return -1;
+    }
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    status = psa_mac_verify_setup(&operation, ctx->psa_hmac_key,
+                                  ctx->psa_hmac_alg);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        goto exit;
+    }
+
+    status = psa_mac_update(&operation, cookie, 4);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        goto exit;
+    }
+
+    status = psa_mac_update(&operation, cli_id,
+                            cli_id_len);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        goto exit;
+    }
+
+    status = psa_mac_verify_finish(&operation, cookie + 4,
+                                   COOKIE_HMAC_LEN);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        goto exit;
+    }
+
+    ret = 0;
+#else
 #if defined(MBEDTLS_THREADING_C)
-    if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret ) );
-#endif
-
-    if( ssl_cookie_hmac( &ctx->hmac_ctx, cookie,
-                         &p, p + sizeof( ref_hmac ),
-                         cli_id, cli_id_len ) != 0 )
-        ret = -1;
-
-#if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
-    {
-        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR,
-                                 MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret);
     }
 #endif
 
-    if( ret != 0 )
-        goto exit;
+    if (ssl_cookie_hmac(&ctx->hmac_ctx, cookie,
+                        &p, p + sizeof(ref_hmac),
+                        cli_id, cli_id_len) != 0) {
+        ret = -1;
+    }
 
-    if( mbedtls_ct_memcmp( cookie + 4, ref_hmac, sizeof( ref_hmac ) ) != 0 )
-    {
+#if defined(MBEDTLS_THREADING_C)
+    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
+        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR,
+                                MBEDTLS_ERR_THREADING_MUTEX_ERROR);
+    }
+#endif
+
+    if (ret != 0) {
+        goto exit;
+    }
+
+    if (mbedtls_ct_memcmp(cookie + 4, ref_hmac, sizeof(ref_hmac)) != 0) {
         ret = -1;
         goto exit;
     }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #if defined(MBEDTLS_HAVE_TIME)
-    cur_time = (unsigned long) mbedtls_time( NULL );
+    cur_time = (unsigned long) mbedtls_time(NULL);
 #else
     cur_time = ctx->serial;
 #endif
 
-    cookie_time = ( (unsigned long) cookie[0] << 24 ) |
-                  ( (unsigned long) cookie[1] << 16 ) |
-                  ( (unsigned long) cookie[2] <<  8 ) |
-                  ( (unsigned long) cookie[3]       );
+    cookie_time = ((unsigned long) cookie[0] << 24) |
+                  ((unsigned long) cookie[1] << 16) |
+                  ((unsigned long) cookie[2] <<  8) |
+                  ((unsigned long) cookie[3]);
 
-    if( ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout )
-    {
+    if (ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout) {
         ret = -1;
         goto exit;
     }
 
 exit:
-    mbedtls_platform_zeroize( ref_hmac, sizeof( ref_hmac ) );
-    return( ret );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    status = psa_mac_abort(&operation);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+    }
+#else
+    mbedtls_platform_zeroize(ref_hmac, sizeof(ref_hmac));
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    return ret;
 }
 #endif /* MBEDTLS_SSL_COOKIE_C */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_debug_helpers.h b/lib/libmbedtls/mbedtls/library/ssl_debug_helpers.h
new file mode 100644
index 0000000..5c22ed2
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/ssl_debug_helpers.h
@@ -0,0 +1,90 @@
+/**
+ * \file ssl_debug_helpers.h
+ *
+ * \brief Automatically generated helper functions for debugging
+ */
+/*
+ *  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_SSL_DEBUG_HELPERS_H
+#define MBEDTLS_SSL_DEBUG_HELPERS_H
+
+#include "common.h"
+
+#if defined(MBEDTLS_DEBUG_C)
+
+#include "mbedtls/ssl.h"
+#include "ssl_misc.h"
+
+
+const char *mbedtls_ssl_states_str(mbedtls_ssl_states in);
+
+const char *mbedtls_ssl_protocol_version_str(mbedtls_ssl_protocol_version in);
+
+const char *mbedtls_tls_prf_types_str(mbedtls_tls_prf_types in);
+
+const char *mbedtls_ssl_key_export_type_str(mbedtls_ssl_key_export_type in);
+
+const char *mbedtls_ssl_sig_alg_to_str(uint16_t in);
+
+const char *mbedtls_ssl_named_group_to_str(uint16_t in);
+
+const char *mbedtls_ssl_get_extension_name(unsigned int extension_type);
+
+void mbedtls_ssl_print_extensions(const mbedtls_ssl_context *ssl,
+                                  int level, const char *file, int line,
+                                  int hs_msg_type, uint32_t extensions_mask,
+                                  const char *extra);
+
+void mbedtls_ssl_print_extension(const mbedtls_ssl_context *ssl,
+                                 int level, const char *file, int line,
+                                 int hs_msg_type, unsigned int extension_type,
+                                 const char *extra_msg0, const char *extra_msg1);
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)
+void mbedtls_ssl_print_ticket_flags(const mbedtls_ssl_context *ssl,
+                                    int level, const char *file, int line,
+                                    unsigned int flags);
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */
+
+#define MBEDTLS_SSL_PRINT_EXTS(level, hs_msg_type, extensions_mask)            \
+    mbedtls_ssl_print_extensions(ssl, level, __FILE__, __LINE__,       \
+                                 hs_msg_type, extensions_mask, NULL)
+
+#define MBEDTLS_SSL_PRINT_EXT(level, hs_msg_type, extension_type, extra)      \
+    mbedtls_ssl_print_extension(ssl, level, __FILE__, __LINE__,        \
+                                hs_msg_type, extension_type,           \
+                                extra, NULL)
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)
+#define MBEDTLS_SSL_PRINT_TICKET_FLAGS(level, flags)             \
+    mbedtls_ssl_print_ticket_flags(ssl, level, __FILE__, __LINE__, flags)
+#endif
+
+#else
+
+#define MBEDTLS_SSL_PRINT_EXTS(level, hs_msg_type, extension_mask)
+
+#define MBEDTLS_SSL_PRINT_EXT(level, hs_msg_type, extension_type, extra)
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)
+#define MBEDTLS_SSL_PRINT_TICKET_FLAGS(level, flags)
+#endif
+
+#endif /* MBEDTLS_DEBUG_C */
+
+#endif /* MBEDTLS_SSL_DEBUG_HELPERS_H */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_debug_helpers_generated.c b/lib/libmbedtls/mbedtls/library/ssl_debug_helpers_generated.c
new file mode 100644
index 0000000..9add9db
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/ssl_debug_helpers_generated.c
@@ -0,0 +1,225 @@
+/* Automatically generated by generate_ssl_debug_helpers.py. DO NOT EDIT. */
+
+/**
+ * \file ssl_debug_helpers_generated.c
+ *
+ * \brief Automatically generated helper functions for debugging
+ */
+/*
+ *  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.
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_DEBUG_C)
+
+#include "ssl_debug_helpers.h"
+
+
+const char *mbedtls_ssl_named_group_to_str( uint16_t in )
+{
+    switch( in )
+    {
+    case MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1:
+        return "secp192k1";
+    case MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1:
+        return "secp192r1";
+    case MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1:
+        return "secp224k1";
+    case MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1:
+        return "secp224r1";
+    case MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1:
+        return "secp256k1";
+    case MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1:
+        return "secp256r1";
+    case MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1:
+        return "secp384r1";
+    case MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1:
+        return "secp521r1";
+    case MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1:
+        return "bp256r1";
+    case MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1:
+        return "bp384r1";
+    case MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1:
+        return "bp512r1";
+    case MBEDTLS_SSL_IANA_TLS_GROUP_X25519:
+        return "x25519";
+    case MBEDTLS_SSL_IANA_TLS_GROUP_X448:
+        return "x448";
+    case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048:
+        return "ffdhe2048";
+    case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072:
+        return "ffdhe3072";
+    case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096:
+        return "ffdhe4096";
+    case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144:
+        return "ffdhe6144";
+    case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192:
+        return "ffdhe8192";
+    };
+
+    return "UNKOWN";
+}
+const char *mbedtls_ssl_sig_alg_to_str( uint16_t in )
+{
+    switch( in )
+    {
+    case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256:
+        return "rsa_pkcs1_sha256";
+    case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384:
+        return "rsa_pkcs1_sha384";
+    case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512:
+        return "rsa_pkcs1_sha512";
+    case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256:
+        return "ecdsa_secp256r1_sha256";
+    case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384:
+        return "ecdsa_secp384r1_sha384";
+    case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512:
+        return "ecdsa_secp521r1_sha512";
+    case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256:
+        return "rsa_pss_rsae_sha256";
+    case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384:
+        return "rsa_pss_rsae_sha384";
+    case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512:
+        return "rsa_pss_rsae_sha512";
+    case MBEDTLS_TLS1_3_SIG_ED25519:
+        return "ed25519";
+    case MBEDTLS_TLS1_3_SIG_ED448:
+        return "ed448";
+    case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA256:
+        return "rsa_pss_pss_sha256";
+    case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA384:
+        return "rsa_pss_pss_sha384";
+    case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA512:
+        return "rsa_pss_pss_sha512";
+    case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA1:
+        return "rsa_pkcs1_sha1";
+    case MBEDTLS_TLS1_3_SIG_ECDSA_SHA1:
+        return "ecdsa_sha1";
+    case MBEDTLS_TLS1_3_SIG_NONE:
+        return "none";
+    };
+
+    return "UNKNOWN";
+}
+const char *mbedtls_ssl_states_str( mbedtls_ssl_states in )
+{
+    const char * in_to_str[]=
+    {
+        [MBEDTLS_SSL_HELLO_REQUEST] = "MBEDTLS_SSL_HELLO_REQUEST",
+        [MBEDTLS_SSL_CLIENT_HELLO] = "MBEDTLS_SSL_CLIENT_HELLO",
+        [MBEDTLS_SSL_SERVER_HELLO] = "MBEDTLS_SSL_SERVER_HELLO",
+        [MBEDTLS_SSL_SERVER_CERTIFICATE] = "MBEDTLS_SSL_SERVER_CERTIFICATE",
+        [MBEDTLS_SSL_SERVER_KEY_EXCHANGE] = "MBEDTLS_SSL_SERVER_KEY_EXCHANGE",
+        [MBEDTLS_SSL_CERTIFICATE_REQUEST] = "MBEDTLS_SSL_CERTIFICATE_REQUEST",
+        [MBEDTLS_SSL_SERVER_HELLO_DONE] = "MBEDTLS_SSL_SERVER_HELLO_DONE",
+        [MBEDTLS_SSL_CLIENT_CERTIFICATE] = "MBEDTLS_SSL_CLIENT_CERTIFICATE",
+        [MBEDTLS_SSL_CLIENT_KEY_EXCHANGE] = "MBEDTLS_SSL_CLIENT_KEY_EXCHANGE",
+        [MBEDTLS_SSL_CERTIFICATE_VERIFY] = "MBEDTLS_SSL_CERTIFICATE_VERIFY",
+        [MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC] = "MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC",
+        [MBEDTLS_SSL_CLIENT_FINISHED] = "MBEDTLS_SSL_CLIENT_FINISHED",
+        [MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC] = "MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC",
+        [MBEDTLS_SSL_SERVER_FINISHED] = "MBEDTLS_SSL_SERVER_FINISHED",
+        [MBEDTLS_SSL_FLUSH_BUFFERS] = "MBEDTLS_SSL_FLUSH_BUFFERS",
+        [MBEDTLS_SSL_HANDSHAKE_WRAPUP] = "MBEDTLS_SSL_HANDSHAKE_WRAPUP",
+        [MBEDTLS_SSL_NEW_SESSION_TICKET] = "MBEDTLS_SSL_NEW_SESSION_TICKET",
+        [MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT] = "MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT",
+        [MBEDTLS_SSL_HELLO_RETRY_REQUEST] = "MBEDTLS_SSL_HELLO_RETRY_REQUEST",
+        [MBEDTLS_SSL_ENCRYPTED_EXTENSIONS] = "MBEDTLS_SSL_ENCRYPTED_EXTENSIONS",
+        [MBEDTLS_SSL_END_OF_EARLY_DATA] = "MBEDTLS_SSL_END_OF_EARLY_DATA",
+        [MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY] = "MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY",
+        [MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED] = "MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED",
+        [MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO] = "MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO",
+        [MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO] = "MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO",
+        [MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO] = "MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO",
+        [MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST] = "MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST",
+        [MBEDTLS_SSL_HANDSHAKE_OVER] = "MBEDTLS_SSL_HANDSHAKE_OVER",
+        [MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET] = "MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET",
+        [MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH] = "MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH",
+    };
+
+    if( in > ( sizeof( in_to_str )/sizeof( in_to_str[0]) - 1 ) ||
+        in_to_str[ in ] == NULL )
+    {
+        return "UNKNOWN_VALUE";
+    }
+    return in_to_str[ in ];
+}
+
+const char *mbedtls_ssl_protocol_version_str( mbedtls_ssl_protocol_version in )
+{
+    const char * in_to_str[]=
+    {
+        [MBEDTLS_SSL_VERSION_UNKNOWN] = "MBEDTLS_SSL_VERSION_UNKNOWN",
+        [MBEDTLS_SSL_VERSION_TLS1_2] = "MBEDTLS_SSL_VERSION_TLS1_2",
+        [MBEDTLS_SSL_VERSION_TLS1_3] = "MBEDTLS_SSL_VERSION_TLS1_3",
+    };
+
+    if( in > ( sizeof( in_to_str )/sizeof( in_to_str[0]) - 1 ) ||
+        in_to_str[ in ] == NULL )
+    {
+        return "UNKNOWN_VALUE";
+    }
+    return in_to_str[ in ];
+}
+
+const char *mbedtls_tls_prf_types_str( mbedtls_tls_prf_types in )
+{
+    const char * in_to_str[]=
+    {
+        [MBEDTLS_SSL_TLS_PRF_NONE] = "MBEDTLS_SSL_TLS_PRF_NONE",
+        [MBEDTLS_SSL_TLS_PRF_SHA384] = "MBEDTLS_SSL_TLS_PRF_SHA384",
+        [MBEDTLS_SSL_TLS_PRF_SHA256] = "MBEDTLS_SSL_TLS_PRF_SHA256",
+        [MBEDTLS_SSL_HKDF_EXPAND_SHA384] = "MBEDTLS_SSL_HKDF_EXPAND_SHA384",
+        [MBEDTLS_SSL_HKDF_EXPAND_SHA256] = "MBEDTLS_SSL_HKDF_EXPAND_SHA256",
+    };
+
+    if( in > ( sizeof( in_to_str )/sizeof( in_to_str[0]) - 1 ) ||
+        in_to_str[ in ] == NULL )
+    {
+        return "UNKNOWN_VALUE";
+    }
+    return in_to_str[ in ];
+}
+
+const char *mbedtls_ssl_key_export_type_str( mbedtls_ssl_key_export_type in )
+{
+    const char * in_to_str[]=
+    {
+        [MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET",
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET",
+        [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET",
+        [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET",
+        [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET",
+        [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET",
+        [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET",
+#endif
+    };
+
+    if( in > ( sizeof( in_to_str )/sizeof( in_to_str[0]) - 1 ) ||
+        in_to_str[ in ] == NULL )
+    {
+        return "UNKNOWN_VALUE";
+    }
+    return in_to_str[ in ];
+}
+
+
+
+#endif /* MBEDTLS_DEBUG_C */
+/* End of automatically generated file. */
+
diff --git a/lib/libmbedtls/mbedtls/library/ssl_misc.h b/lib/libmbedtls/mbedtls/library/ssl_misc.h
new file mode 100644
index 0000000..6fe0414
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/ssl_misc.h
@@ -0,0 +1,2769 @@
+/**
+ * \file ssl_misc.h
+ *
+ * \brief Internal functions shared by the SSL modules
+ */
+/*
+ *  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_SSL_MISC_H
+#define MBEDTLS_SSL_MISC_H
+
+#include "mbedtls/build_info.h"
+
+#include "mbedtls/ssl.h"
+#include "mbedtls/cipher.h"
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
+#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
+#include "hash_info.h"
+#endif
+#include "mbedtls/legacy_or_psa.h"
+
+#if defined(MBEDTLS_MD5_C)
+#include "mbedtls/md5.h"
+#endif
+
+#if defined(MBEDTLS_SHA1_C)
+#include "mbedtls/sha1.h"
+#endif
+
+#if defined(MBEDTLS_SHA256_C)
+#include "mbedtls/sha256.h"
+#endif
+
+#if defined(MBEDTLS_SHA512_C)
+#include "mbedtls/sha512.h"
+#endif
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
+    !defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "mbedtls/ecjpake.h"
+#endif
+
+#include "mbedtls/pk.h"
+#include "common.h"
+
+/* Shorthand for restartable ECC */
+#if defined(MBEDTLS_ECP_RESTARTABLE) && \
+    defined(MBEDTLS_SSL_CLI_C) && \
+    defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+#define MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED
+#endif
+
+#define MBEDTLS_SSL_INITIAL_HANDSHAKE           0
+#define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS   1   /* In progress */
+#define MBEDTLS_SSL_RENEGOTIATION_DONE          2   /* Done or aborted */
+#define MBEDTLS_SSL_RENEGOTIATION_PENDING       3   /* Requested (server only) */
+
+/* Faked handshake message identity for HelloRetryRequest. */
+#define MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST (-MBEDTLS_SSL_HS_SERVER_HELLO)
+
+/*
+ * Internal identity of handshake extensions
+ */
+#define MBEDTLS_SSL_EXT_ID_UNRECOGNIZED                0
+#define MBEDTLS_SSL_EXT_ID_SERVERNAME                  1
+#define MBEDTLS_SSL_EXT_ID_SERVERNAME_HOSTNAME         1
+#define MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH         2
+#define MBEDTLS_SSL_EXT_ID_STATUS_REQUEST              3
+#define MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS            4
+#define MBEDTLS_SSL_EXT_ID_SUPPORTED_ELLIPTIC_CURVES   4
+#define MBEDTLS_SSL_EXT_ID_SIG_ALG                     5
+#define MBEDTLS_SSL_EXT_ID_USE_SRTP                    6
+#define MBEDTLS_SSL_EXT_ID_HEARTBEAT                   7
+#define MBEDTLS_SSL_EXT_ID_ALPN                        8
+#define MBEDTLS_SSL_EXT_ID_SCT                         9
+#define MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE              10
+#define MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE             11
+#define MBEDTLS_SSL_EXT_ID_PADDING                    12
+#define MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY             13
+#define MBEDTLS_SSL_EXT_ID_EARLY_DATA                 14
+#define MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS         15
+#define MBEDTLS_SSL_EXT_ID_COOKIE                     16
+#define MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES     17
+#define MBEDTLS_SSL_EXT_ID_CERT_AUTH                  18
+#define MBEDTLS_SSL_EXT_ID_OID_FILTERS                19
+#define MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH        20
+#define MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT               21
+#define MBEDTLS_SSL_EXT_ID_KEY_SHARE                  22
+#define MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC             23
+#define MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS    24
+#define MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC           25
+#define MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET     26
+#define MBEDTLS_SSL_EXT_ID_SESSION_TICKET             27
+#define MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT          28
+
+/* Utility for translating IANA extension type. */
+uint32_t mbedtls_ssl_get_extension_id(unsigned int extension_type);
+uint32_t mbedtls_ssl_get_extension_mask(unsigned int extension_type);
+/* Macros used to define mask constants */
+#define MBEDTLS_SSL_EXT_MASK(id)       (1ULL << (MBEDTLS_SSL_EXT_ID_##id))
+/* Reset value of extension mask */
+#define MBEDTLS_SSL_EXT_MASK_NONE                                              0
+
+/* In messages containing extension requests, we should ignore unrecognized
+ * extensions. In messages containing extension responses, unrecognized
+ * extensions should result in handshake abortion. Messages containing
+ * extension requests include ClientHello, CertificateRequest and
+ * NewSessionTicket. Messages containing extension responses include
+ * ServerHello, HelloRetryRequest, EncryptedExtensions and Certificate.
+ *
+ * RFC 8446 section 4.1.3
+ *
+ * The ServerHello MUST only include extensions which are required to establish
+ * the cryptographic context and negotiate the protocol version.
+ *
+ * RFC 8446 section 4.2
+ *
+ * If an implementation receives an extension which it recognizes and which is
+ * not specified for the message in which it appears, it MUST abort the handshake
+ * with an "illegal_parameter" alert.
+ */
+
+/* Extensions that are not recognized by TLS 1.3 */
+#define MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED                               \
+    (MBEDTLS_SSL_EXT_MASK(SUPPORTED_POINT_FORMATS)                | \
+     MBEDTLS_SSL_EXT_MASK(ENCRYPT_THEN_MAC)                       | \
+     MBEDTLS_SSL_EXT_MASK(EXTENDED_MASTER_SECRET)                 | \
+     MBEDTLS_SSL_EXT_MASK(SESSION_TICKET)                         | \
+     MBEDTLS_SSL_EXT_MASK(TRUNCATED_HMAC)                         | \
+     MBEDTLS_SSL_EXT_MASK(UNRECOGNIZED))
+
+/* RFC 8446 section 4.2. Allowed extensions for ClientHello */
+#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH                                  \
+    (MBEDTLS_SSL_EXT_MASK(SERVERNAME)                             | \
+     MBEDTLS_SSL_EXT_MASK(MAX_FRAGMENT_LENGTH)                    | \
+     MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST)                         | \
+     MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS)                       | \
+     MBEDTLS_SSL_EXT_MASK(SIG_ALG)                                | \
+     MBEDTLS_SSL_EXT_MASK(USE_SRTP)                               | \
+     MBEDTLS_SSL_EXT_MASK(HEARTBEAT)                              | \
+     MBEDTLS_SSL_EXT_MASK(ALPN)                                   | \
+     MBEDTLS_SSL_EXT_MASK(SCT)                                    | \
+     MBEDTLS_SSL_EXT_MASK(CLI_CERT_TYPE)                          | \
+     MBEDTLS_SSL_EXT_MASK(SERV_CERT_TYPE)                         | \
+     MBEDTLS_SSL_EXT_MASK(PADDING)                                | \
+     MBEDTLS_SSL_EXT_MASK(KEY_SHARE)                              | \
+     MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)                         | \
+     MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES)                 | \
+     MBEDTLS_SSL_EXT_MASK(EARLY_DATA)                             | \
+     MBEDTLS_SSL_EXT_MASK(COOKIE)                                 | \
+     MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS)                     | \
+     MBEDTLS_SSL_EXT_MASK(CERT_AUTH)                              | \
+     MBEDTLS_SSL_EXT_MASK(POST_HANDSHAKE_AUTH)                    | \
+     MBEDTLS_SSL_EXT_MASK(SIG_ALG_CERT)                           | \
+     MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT)                      | \
+     MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED)
+
+/* RFC 8446 section 4.2. Allowed extensions for EncryptedExtensions */
+#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_EE                                  \
+    (MBEDTLS_SSL_EXT_MASK(SERVERNAME)                             | \
+     MBEDTLS_SSL_EXT_MASK(MAX_FRAGMENT_LENGTH)                    | \
+     MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS)                       | \
+     MBEDTLS_SSL_EXT_MASK(USE_SRTP)                               | \
+     MBEDTLS_SSL_EXT_MASK(HEARTBEAT)                              | \
+     MBEDTLS_SSL_EXT_MASK(ALPN)                                   | \
+     MBEDTLS_SSL_EXT_MASK(CLI_CERT_TYPE)                          | \
+     MBEDTLS_SSL_EXT_MASK(SERV_CERT_TYPE)                         | \
+     MBEDTLS_SSL_EXT_MASK(EARLY_DATA)                             | \
+     MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT))
+
+/* RFC 8446 section 4.2. Allowed extensions for CertificateRequest */
+#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CR                                  \
+    (MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST)                         | \
+     MBEDTLS_SSL_EXT_MASK(SIG_ALG)                                | \
+     MBEDTLS_SSL_EXT_MASK(SCT)                                    | \
+     MBEDTLS_SSL_EXT_MASK(CERT_AUTH)                              | \
+     MBEDTLS_SSL_EXT_MASK(OID_FILTERS)                            | \
+     MBEDTLS_SSL_EXT_MASK(SIG_ALG_CERT)                           | \
+     MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED)
+
+/* RFC 8446 section 4.2. Allowed extensions for Certificate */
+#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CT                                  \
+    (MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST)                         | \
+     MBEDTLS_SSL_EXT_MASK(SCT))
+
+/* RFC 8446 section 4.2. Allowed extensions for ServerHello */
+#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_SH                                  \
+    (MBEDTLS_SSL_EXT_MASK(KEY_SHARE)                              | \
+     MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)                         | \
+     MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS))
+
+/* RFC 8446 section 4.2. Allowed extensions for HelloRetryRequest */
+#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_HRR                                 \
+    (MBEDTLS_SSL_EXT_MASK(KEY_SHARE)                              | \
+     MBEDTLS_SSL_EXT_MASK(COOKIE)                                 | \
+     MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS))
+
+/* RFC 8446 section 4.2. Allowed extensions for NewSessionTicket */
+#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_NST                                 \
+    (MBEDTLS_SSL_EXT_MASK(EARLY_DATA)                             | \
+     MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED)
+
+/*
+ * Helper macros for function call with return check.
+ */
+/*
+ * Exit when return non-zero value
+ */
+#define MBEDTLS_SSL_PROC_CHK(f)                               \
+    do {                                                        \
+        ret = (f);                                            \
+        if (ret != 0)                                          \
+        {                                                       \
+            goto cleanup;                                       \
+        }                                                       \
+    } while (0)
+/*
+ * Exit when return negative value
+ */
+#define MBEDTLS_SSL_PROC_CHK_NEG(f)                           \
+    do {                                                        \
+        ret = (f);                                            \
+        if (ret < 0)                                           \
+        {                                                       \
+            goto cleanup;                                       \
+        }                                                       \
+    } while (0)
+
+/*
+ * DTLS retransmission states, see RFC 6347 4.2.4
+ *
+ * The SENDING state is merged in PREPARING for initial sends,
+ * but is distinct for resends.
+ *
+ * Note: initial state is wrong for server, but is not used anyway.
+ */
+#define MBEDTLS_SSL_RETRANS_PREPARING       0
+#define MBEDTLS_SSL_RETRANS_SENDING         1
+#define MBEDTLS_SSL_RETRANS_WAITING         2
+#define MBEDTLS_SSL_RETRANS_FINISHED        3
+
+/*
+ * Allow extra bytes for record, authentication and encryption overhead:
+ * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256).
+ */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+
+/* This macro determines whether CBC is supported. */
+#if defined(MBEDTLS_CIPHER_MODE_CBC) &&                               \
+    (defined(MBEDTLS_AES_C)      ||                                  \
+    defined(MBEDTLS_CAMELLIA_C) ||                                  \
+    defined(MBEDTLS_ARIA_C)     ||                                  \
+    defined(MBEDTLS_DES_C))
+#define MBEDTLS_SSL_SOME_SUITES_USE_CBC
+#endif
+
+/* This macro determines whether a ciphersuite using a
+ * stream cipher can be used. */
+#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
+#define MBEDTLS_SSL_SOME_SUITES_USE_STREAM
+#endif
+
+/* This macro determines whether the CBC construct used in TLS 1.2 is supported. */
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \
+    defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#define MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC
+#endif
+
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM) || \
+    defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC)
+#define MBEDTLS_SSL_SOME_SUITES_USE_MAC
+#endif
+
+/* This macro determines whether a ciphersuite uses Encrypt-then-MAC with CBC */
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \
+    defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+#define MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM
+#endif
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
+/* Ciphersuites using HMAC */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#define MBEDTLS_SSL_MAC_ADD                 48  /* SHA-384 used for HMAC */
+#elif defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#define MBEDTLS_SSL_MAC_ADD                 32  /* SHA-256 used for HMAC */
+#else
+#define MBEDTLS_SSL_MAC_ADD                 20  /* SHA-1   used for HMAC */
+#endif
+#else /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
+/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */
+#define MBEDTLS_SSL_MAC_ADD                 16
+#endif
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#define MBEDTLS_SSL_PADDING_ADD            256
+#else
+#define MBEDTLS_SSL_PADDING_ADD              0
+#endif
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+#define MBEDTLS_SSL_MAX_CID_EXPANSION      MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY
+#else
+#define MBEDTLS_SSL_MAX_CID_EXPANSION        0
+#endif
+
+#define MBEDTLS_SSL_PAYLOAD_OVERHEAD (MBEDTLS_MAX_IV_LENGTH +          \
+                                      MBEDTLS_SSL_MAC_ADD +            \
+                                      MBEDTLS_SSL_PADDING_ADD +        \
+                                      MBEDTLS_SSL_MAX_CID_EXPANSION    \
+                                      )
+
+#define MBEDTLS_SSL_IN_PAYLOAD_LEN (MBEDTLS_SSL_PAYLOAD_OVERHEAD + \
+                                    (MBEDTLS_SSL_IN_CONTENT_LEN))
+
+#define MBEDTLS_SSL_OUT_PAYLOAD_LEN (MBEDTLS_SSL_PAYLOAD_OVERHEAD + \
+                                     (MBEDTLS_SSL_OUT_CONTENT_LEN))
+
+/* The maximum number of buffered handshake messages. */
+#define MBEDTLS_SSL_MAX_BUFFERED_HS 4
+
+/* Maximum length we can advertise as our max content length for
+   RFC 6066 max_fragment_length extension negotiation purposes
+   (the lesser of both sizes, if they are unequal.)
+ */
+#define MBEDTLS_TLS_EXT_ADV_CONTENT_LEN (                            \
+        (MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN)   \
+        ? (MBEDTLS_SSL_OUT_CONTENT_LEN)                            \
+        : (MBEDTLS_SSL_IN_CONTENT_LEN)                             \
+        )
+
+/* Maximum size in bytes of list in signature algorithms ext., RFC 5246/8446 */
+#define MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN       65534
+
+/* Minimum size in bytes of list in signature algorithms ext., RFC 5246/8446 */
+#define MBEDTLS_SSL_MIN_SIG_ALG_LIST_LEN       2
+
+/* Maximum size in bytes of list in supported elliptic curve ext., RFC 4492 */
+#define MBEDTLS_SSL_MAX_CURVE_LIST_LEN         65535
+
+#define MBEDTLS_RECEIVED_SIG_ALGS_SIZE         20
+
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+
+#define MBEDTLS_TLS_SIG_NONE MBEDTLS_TLS1_3_SIG_NONE
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#define MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(sig, hash) ((hash << 8) | sig)
+#define MBEDTLS_SSL_TLS12_SIG_ALG_FROM_SIG_AND_HASH_ALG(alg) (alg & 0xFF)
+#define MBEDTLS_SSL_TLS12_HASH_ALG_FROM_SIG_AND_HASH_ALG(alg) (alg >> 8)
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
+
+/*
+ * Check that we obey the standard's message size bounds
+ */
+
+#if MBEDTLS_SSL_IN_CONTENT_LEN > 16384
+#error "Bad configuration - incoming record content too large."
+#endif
+
+#if MBEDTLS_SSL_OUT_CONTENT_LEN > 16384
+#error "Bad configuration - outgoing record content too large."
+#endif
+
+#if MBEDTLS_SSL_IN_PAYLOAD_LEN > MBEDTLS_SSL_IN_CONTENT_LEN + 2048
+#error "Bad configuration - incoming protected record payload too large."
+#endif
+
+#if MBEDTLS_SSL_OUT_PAYLOAD_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN + 2048
+#error "Bad configuration - outgoing protected record payload too large."
+#endif
+
+/* Calculate buffer sizes */
+
+/* Note: Even though the TLS record header is only 5 bytes
+   long, we're internally using 8 bytes to store the
+   implicit sequence number. */
+#define MBEDTLS_SSL_HEADER_LEN 13
+
+#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+#define MBEDTLS_SSL_IN_BUFFER_LEN  \
+    ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_IN_PAYLOAD_LEN))
+#else
+#define MBEDTLS_SSL_IN_BUFFER_LEN  \
+    ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_IN_PAYLOAD_LEN) \
+     + (MBEDTLS_SSL_CID_IN_LEN_MAX))
+#endif
+
+#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+#define MBEDTLS_SSL_OUT_BUFFER_LEN  \
+    ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_OUT_PAYLOAD_LEN))
+#else
+#define MBEDTLS_SSL_OUT_BUFFER_LEN                               \
+    ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_OUT_PAYLOAD_LEN)    \
+     + (MBEDTLS_SSL_CID_OUT_LEN_MAX))
+#endif
+
+#define MBEDTLS_CLIENT_HELLO_RANDOM_LEN 32
+#define MBEDTLS_SERVER_HELLO_RANDOM_LEN 32
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+/**
+ * \brief          Return the maximum fragment length (payload, in bytes) for
+ *                 the output buffer. For the client, this is the configured
+ *                 value. For the server, it is the minimum of two - the
+ *                 configured value and the negotiated one.
+ *
+ * \sa             mbedtls_ssl_conf_max_frag_len()
+ * \sa             mbedtls_ssl_get_max_out_record_payload()
+ *
+ * \param ssl      SSL context
+ *
+ * \return         Current maximum fragment length for the output buffer.
+ */
+size_t mbedtls_ssl_get_output_max_frag_len(const mbedtls_ssl_context *ssl);
+
+/**
+ * \brief          Return the maximum fragment length (payload, in bytes) for
+ *                 the input buffer. This is the negotiated maximum fragment
+ *                 length, or, if there is none, MBEDTLS_SSL_IN_CONTENT_LEN.
+ *                 If it is not defined either, the value is 2^14. This function
+ *                 works as its predecessor, \c mbedtls_ssl_get_max_frag_len().
+ *
+ * \sa             mbedtls_ssl_conf_max_frag_len()
+ * \sa             mbedtls_ssl_get_max_in_record_payload()
+ *
+ * \param ssl      SSL context
+ *
+ * \return         Current maximum fragment length for the output buffer.
+ */
+size_t mbedtls_ssl_get_input_max_frag_len(const mbedtls_ssl_context *ssl);
+#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+static inline size_t mbedtls_ssl_get_output_buflen(const mbedtls_ssl_context *ctx)
+{
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    return mbedtls_ssl_get_output_max_frag_len(ctx)
+           + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD
+           + MBEDTLS_SSL_CID_OUT_LEN_MAX;
+#else
+    return mbedtls_ssl_get_output_max_frag_len(ctx)
+           + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD;
+#endif
+}
+
+static inline size_t mbedtls_ssl_get_input_buflen(const mbedtls_ssl_context *ctx)
+{
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    return mbedtls_ssl_get_input_max_frag_len(ctx)
+           + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD
+           + MBEDTLS_SSL_CID_IN_LEN_MAX;
+#else
+    return mbedtls_ssl_get_input_max_frag_len(ctx)
+           + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD;
+#endif
+}
+#endif
+
+/*
+ * TLS extension flags (for extensions with outgoing ServerHello content
+ * that need it (e.g. for RENEGOTIATION_INFO the server already knows because
+ * of state of the renegotiation flag, so no indicator is required)
+ */
+#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0)
+#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK                 (1 << 1)
+
+/**
+ * \brief        This function checks if the remaining size in a buffer is
+ *               greater or equal than a needed space.
+ *
+ * \param cur    Pointer to the current position in the buffer.
+ * \param end    Pointer to one past the end of the buffer.
+ * \param need   Needed space in bytes.
+ *
+ * \return       Zero if the needed space is available in the buffer, non-zero
+ *               otherwise.
+ */
+#if !defined(MBEDTLS_TEST_HOOKS)
+static inline int mbedtls_ssl_chk_buf_ptr(const uint8_t *cur,
+                                          const uint8_t *end, size_t need)
+{
+    return (cur > end) || (need > (size_t) (end - cur));
+}
+#else
+typedef struct {
+    const uint8_t *cur;
+    const uint8_t *end;
+    size_t need;
+} mbedtls_ssl_chk_buf_ptr_args;
+
+void mbedtls_ssl_set_chk_buf_ptr_fail_args(
+    const uint8_t *cur, const uint8_t *end, size_t need);
+void mbedtls_ssl_reset_chk_buf_ptr_fail_args(void);
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_cmp_chk_buf_ptr_fail_args(mbedtls_ssl_chk_buf_ptr_args *args);
+
+static inline int mbedtls_ssl_chk_buf_ptr(const uint8_t *cur,
+                                          const uint8_t *end, size_t need)
+{
+    if ((cur > end) || (need > (size_t) (end - cur))) {
+        mbedtls_ssl_set_chk_buf_ptr_fail_args(cur, end, need);
+        return 1;
+    }
+    return 0;
+}
+#endif /* MBEDTLS_TEST_HOOKS */
+
+/**
+ * \brief        This macro checks if the remaining size in a buffer is
+ *               greater or equal than a needed space. If it is not the case,
+ *               it returns an SSL_BUFFER_TOO_SMALL error.
+ *
+ * \param cur    Pointer to the current position in the buffer.
+ * \param end    Pointer to one past the end of the buffer.
+ * \param need   Needed space in bytes.
+ *
+ */
+#define MBEDTLS_SSL_CHK_BUF_PTR(cur, end, need)                        \
+    do {                                                                 \
+        if (mbedtls_ssl_chk_buf_ptr((cur), (end), (need)) != 0) \
+        {                                                                \
+            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;                  \
+        }                                                                \
+    } while (0)
+
+/**
+ * \brief        This macro checks if the remaining length in an input buffer is
+ *               greater or equal than a needed length. If it is not the case, it
+ *               returns #MBEDTLS_ERR_SSL_DECODE_ERROR error and pends a
+ *               #MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR alert message.
+ *
+ *               This is a function-like macro. It is guaranteed to evaluate each
+ *               argument exactly once.
+ *
+ * \param cur    Pointer to the current position in the buffer.
+ * \param end    Pointer to one past the end of the buffer.
+ * \param need   Needed length in bytes.
+ *
+ */
+#define MBEDTLS_SSL_CHK_BUF_READ_PTR(cur, end, need)                          \
+    do {                                                                        \
+        if (mbedtls_ssl_chk_buf_ptr((cur), (end), (need)) != 0)        \
+        {                                                                       \
+            MBEDTLS_SSL_DEBUG_MSG(1,                                           \
+                                  ("missing input data in %s", __func__));  \
+            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,   \
+                                         MBEDTLS_ERR_SSL_DECODE_ERROR);       \
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;                             \
+        }                                                                       \
+    } while (0)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int  mbedtls_ssl_tls_prf_cb(const unsigned char *secret, size_t slen,
+                                    const char *label,
+                                    const unsigned char *random, size_t rlen,
+                                    unsigned char *dstbuf, size_t dlen);
+
+/* cipher.h exports the maximum IV, key and block length from
+ * all ciphers enabled in the config, regardless of whether those
+ * ciphers are actually usable in SSL/TLS. Notably, XTS is enabled
+ * in the default configuration and uses 64 Byte keys, but it is
+ * not used for record protection in SSL/TLS.
+ *
+ * In order to prevent unnecessary inflation of key structures,
+ * we introduce SSL-specific variants of the max-{key,block,IV}
+ * macros here which are meant to only take those ciphers into
+ * account which can be negotiated in SSL/TLS.
+ *
+ * Since the current definitions of MBEDTLS_MAX_{KEY|BLOCK|IV}_LENGTH
+ * in cipher.h are rough overapproximations of the real maxima, here
+ * we content ourselves with replicating those overapproximations
+ * for the maximum block and IV length, and excluding XTS from the
+ * computation of the maximum key length. */
+#define MBEDTLS_SSL_MAX_BLOCK_LENGTH 16
+#define MBEDTLS_SSL_MAX_IV_LENGTH    16
+#define MBEDTLS_SSL_MAX_KEY_LENGTH   32
+
+/**
+ * \brief   The data structure holding the cryptographic material (key and IV)
+ *          used for record protection in TLS 1.3.
+ */
+struct mbedtls_ssl_key_set {
+    /*! The key for client->server records. */
+    unsigned char client_write_key[MBEDTLS_SSL_MAX_KEY_LENGTH];
+    /*! The key for server->client records. */
+    unsigned char server_write_key[MBEDTLS_SSL_MAX_KEY_LENGTH];
+    /*! The IV  for client->server records. */
+    unsigned char client_write_iv[MBEDTLS_SSL_MAX_IV_LENGTH];
+    /*! The IV  for server->client records. */
+    unsigned char server_write_iv[MBEDTLS_SSL_MAX_IV_LENGTH];
+
+    size_t key_len; /*!< The length of client_write_key and
+                     *   server_write_key, in Bytes. */
+    size_t iv_len;  /*!< The length of client_write_iv and
+                     *   server_write_iv, in Bytes. */
+};
+typedef struct mbedtls_ssl_key_set mbedtls_ssl_key_set;
+
+typedef struct {
+    unsigned char binder_key[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+    unsigned char client_early_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+    unsigned char early_exporter_master_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+} mbedtls_ssl_tls13_early_secrets;
+
+typedef struct {
+    unsigned char client_handshake_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+    unsigned char server_handshake_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+} mbedtls_ssl_tls13_handshake_secrets;
+
+/*
+ * This structure contains the parameters only needed during handshake.
+ */
+struct mbedtls_ssl_handshake_params {
+    /* Frequently-used boolean or byte fields (placed early to take
+     * advantage of smaller code size for indirect access on Arm Thumb) */
+    uint8_t resume;                     /*!<  session resume indicator*/
+    uint8_t cli_exts;                   /*!< client extension presence*/
+
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    uint8_t sni_authmode;               /*!< authmode from SNI callback     */
+#endif
+
+#if defined(MBEDTLS_SSL_SRV_C)
+    /* Flag indicating if a CertificateRequest message has been sent
+     * to the client or not. */
+    uint8_t certificate_request_sent;
+#endif /* MBEDTLS_SSL_SRV_C */
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    uint8_t new_session_ticket;         /*!< use NewSessionTicket?    */
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+#if defined(MBEDTLS_SSL_CLI_C)
+    /** Minimum TLS version to be negotiated.
+     *
+     *  It is set up in the ClientHello writing preparation stage and used
+     *  throughout the ClientHello writing. Not relevant anymore as soon as
+     *  the protocol version has been negotiated thus as soon as the
+     *  ServerHello is received.
+     *  For a fresh handshake not linked to any previous handshake, it is
+     *  equal to the configured minimum minor version to be negotiated. When
+     *  renegotiating or resuming a session, it is equal to the previously
+     *  negotiated minor version.
+     *
+     *  There is no maximum TLS version field in this handshake context.
+     *  From the start of the handshake, we need to define a current protocol
+     *  version for the record layer which we define as the maximum TLS
+     *  version to be negotiated. The `tls_version` field of the SSL context is
+     *  used to store this maximum value until it contains the actual
+     *  negotiated value.
+     */
+    mbedtls_ssl_protocol_version min_tls_version;
+#endif
+
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+    uint8_t extended_ms;                /*!< use Extended Master Secret? */
+#endif
+
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+    uint8_t async_in_progress; /*!< an asynchronous operation is in progress */
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    unsigned char retransmit_state;     /*!<  Retransmission state           */
+#endif
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+    unsigned char group_list_heap_allocated;
+    unsigned char sig_algs_heap_allocated;
+#endif
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    uint8_t ecrs_enabled;               /*!< Handshake supports EC restart? */
+    enum { /* this complements ssl->state with info on intra-state operations */
+        ssl_ecrs_none = 0,              /*!< nothing going on (yet)         */
+        ssl_ecrs_crt_verify,            /*!< Certificate: crt_verify()      */
+        ssl_ecrs_ske_start_processing,  /*!< ServerKeyExchange: pk_verify() */
+        ssl_ecrs_cke_ecdh_calc_secret,  /*!< ClientKeyExchange: ECDH step 2 */
+        ssl_ecrs_crt_vrfy_sign,         /*!< CertificateVerify: pk_sign()   */
+    } ecrs_state;                       /*!< current (or last) operation    */
+    mbedtls_x509_crt *ecrs_peer_cert;   /*!< The peer's CRT chain.          */
+    size_t ecrs_n;                      /*!< place for saving a length      */
+#endif
+
+    mbedtls_ssl_ciphersuite_t const *ciphersuite_info;
+
+    MBEDTLS_CHECK_RETURN_CRITICAL
+    int (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t);
+    MBEDTLS_CHECK_RETURN_CRITICAL
+    int (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *);
+    MBEDTLS_CHECK_RETURN_CRITICAL
+    int (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int);
+    mbedtls_ssl_tls_prf_cb *tls_prf;
+
+    /*
+     * Handshake specific crypto variables
+     */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    uint8_t key_exchange_mode; /*!< Selected key exchange mode */
+
+    /** Number of HelloRetryRequest messages received/sent from/to the server. */
+    int hello_retry_request_count;
+
+#if defined(MBEDTLS_SSL_SRV_C)
+    /** selected_group of key_share extension in HelloRetryRequest message. */
+    uint16_t hrr_selected_group;
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    uint8_t tls13_kex_modes; /*!< Key exchange modes supported by the client */
+#endif
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    uint16_t new_session_tickets_count;         /*!< number of session tickets */
+#endif
+#endif /* MBEDTLS_SSL_SRV_C */
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+    uint16_t received_sig_algs[MBEDTLS_RECEIVED_SIG_ALGS_SIZE];
+#endif
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+    const uint16_t *group_list;
+    const uint16_t *sig_algs;
+#endif
+
+#if defined(MBEDTLS_DHM_C)
+    mbedtls_dhm_context dhm_ctx;                /*!<  DHM key exchange        */
+#endif
+
+/* Adding guard for MBEDTLS_ECDSA_C to ensure no compile errors due
+ * to guards in client and server code. There is a gap in functionality that
+ * access to ecdh_ctx structure is needed for MBEDTLS_ECDSA_C which does not
+ * seem correct.
+ */
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
+    mbedtls_ecdh_context ecdh_ctx;              /*!<  ECDH key exchange       */
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    psa_key_type_t ecdh_psa_type;
+    size_t ecdh_bits;
+    mbedtls_svc_key_id_t ecdh_psa_privkey;
+    uint8_t ecdh_psa_privkey_is_external;
+    unsigned char ecdh_psa_peerkey[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
+    size_t ecdh_psa_peerkey_len;
+#endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */
+#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_pake_operation_t psa_pake_ctx;        /*!< EC J-PAKE key exchange */
+    mbedtls_svc_key_id_t psa_pake_password;
+    uint8_t psa_pake_ctx_is_ok;
+#else
+    mbedtls_ecjpake_context ecjpake_ctx;        /*!< EC J-PAKE key exchange */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#if defined(MBEDTLS_SSL_CLI_C)
+    unsigned char *ecjpake_cache;               /*!< Cache for ClientHello ext */
+    size_t ecjpake_cache_len;                   /*!< Length of cached data */
+#endif
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) ||      \
+    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+    uint16_t *curves_tls_id;      /*!<  List of TLS IDs of supported elliptic curves */
+#endif
+
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    mbedtls_svc_key_id_t psk_opaque;            /*!< Opaque PSK from the callback   */
+    uint8_t psk_opaque_is_internal;
+#else
+    unsigned char *psk;                 /*!<  PSK from the callback         */
+    size_t psk_len;                     /*!<  Length of PSK from callback   */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    uint16_t    selected_identity;
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    mbedtls_x509_crt_restart_ctx ecrs_ctx;  /*!< restart context            */
+#endif
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    mbedtls_ssl_key_cert *key_cert;     /*!< chosen key/cert pair (server)  */
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI         */
+    mbedtls_x509_crt *sni_ca_chain;     /*!< trusted CAs from SNI callback  */
+    mbedtls_x509_crl *sni_ca_crl;       /*!< trusted CAs CRLs from SNI      */
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C) &&        \
+    !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    mbedtls_pk_context peer_pubkey;     /*!< The public key from the peer.  */
+#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
+    struct {
+        size_t total_bytes_buffered; /*!< Cumulative size of heap allocated
+                                      *   buffers used for message buffering. */
+
+        uint8_t seen_ccs;               /*!< Indicates if a CCS message has
+                                         *   been seen in the current flight. */
+
+        struct mbedtls_ssl_hs_buffer {
+            unsigned is_valid      : 1;
+            unsigned is_fragmented : 1;
+            unsigned is_complete   : 1;
+            unsigned char *data;
+            size_t data_len;
+        } hs[MBEDTLS_SSL_MAX_BUFFERED_HS];
+
+        struct {
+            unsigned char *data;
+            size_t len;
+            unsigned epoch;
+        } future_record;
+
+    } 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 */
+#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_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 */
+    unsigned int in_msg_seq;            /*!<  Incoming handshake sequence number */
+
+    uint32_t retransmit_timeout;        /*!<  Current value of timeout       */
+    mbedtls_ssl_flight_item *flight;    /*!<  Current outgoing flight        */
+    mbedtls_ssl_flight_item *cur_msg;   /*!<  Current message in flight      */
+    unsigned char *cur_msg_p;           /*!<  Position in current message    */
+    unsigned int in_flight_start_seq;   /*!<  Minimum message sequence in the
+                                              flight being received          */
+    mbedtls_ssl_transform *alt_transform_out;   /*!<  Alternative transform for
+                                                   resending messages             */
+    unsigned char alt_out_ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!<  Alternative record epoch/counter
+                                                                      for resending messages         */
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    /* The state of CID configuration in this handshake. */
+
+    uint8_t cid_in_use; /*!< This indicates whether the use of the CID extension
+                         *   has been negotiated. Possible values are
+                         *   #MBEDTLS_SSL_CID_ENABLED and
+                         *   #MBEDTLS_SSL_CID_DISABLED. */
+    unsigned char peer_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX];   /*! The peer's CID */
+    uint8_t peer_cid_len;                                  /*!< The length of
+                                                            *   \c peer_cid.  */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+    uint16_t mtu;                       /*!<  Handshake mtu, used to fragment outgoing messages */
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+    /*
+     * Checksum contexts
+     */
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_hash_operation_t fin_sha256_psa;
+#else
+    mbedtls_md_context_t fin_sha256;
+#endif
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_hash_operation_t fin_sha384_psa;
+#else
+    mbedtls_md_context_t fin_sha384;
+#endif
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    uint16_t offered_group_id; /* The NamedGroup value for the group
+                                * that is being used for ephemeral
+                                * key exchange.
+                                *
+                                * On the client: Defaults to the first
+                                * entry in the client's group list,
+                                * but can be overwritten by the HRR. */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+#if defined(MBEDTLS_SSL_CLI_C)
+    uint8_t client_auth;       /*!< used to check if CertificateRequest has been
+                                    received from server side. If CertificateRequest
+                                    has been received, Certificate and CertificateVerify
+                                    should be sent to server */
+#endif /* MBEDTLS_SSL_CLI_C */
+    /*
+     * State-local variables used during the processing
+     * of a specific handshake state.
+     */
+    union {
+        /* Outgoing Finished message */
+        struct {
+            uint8_t preparation_done;
+
+            /* Buffer holding digest of the handshake up to
+             * but excluding the outgoing finished message. */
+            unsigned char digest[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+            size_t digest_len;
+        } finished_out;
+
+        /* Incoming Finished message */
+        struct {
+            uint8_t preparation_done;
+
+            /* Buffer holding digest of the handshake up to but
+             * excluding the peer's incoming finished message. */
+            unsigned char digest[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+            size_t digest_len;
+        } finished_in;
+
+    } state_local;
+
+    /* End of state-local variables. */
+
+    unsigned char randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN +
+                            MBEDTLS_SERVER_HELLO_RANDOM_LEN];
+    /*!<  random bytes            */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    unsigned char premaster[MBEDTLS_PREMASTER_SIZE];
+    /*!<  premaster secret        */
+    size_t pmslen;                      /*!<  premaster length        */
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    uint32_t sent_extensions;       /*!< extensions sent by endpoint */
+    uint32_t received_extensions;   /*!< extensions received by endpoint */
+
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+    unsigned char certificate_request_context_len;
+    unsigned char *certificate_request_context;
+#endif
+
+    /** TLS 1.3 transform for encrypted handshake messages. */
+    mbedtls_ssl_transform *transform_handshake;
+    union {
+        unsigned char early[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+        unsigned char handshake[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+        unsigned char app[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+    } tls13_master_secrets;
+
+    mbedtls_ssl_tls13_handshake_secrets tls13_hs_secrets;
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    /** TLS 1.3 transform for early data and handshake messages. */
+    mbedtls_ssl_transform *transform_earlydata;
+#endif
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+    /** Asynchronous operation context. This field is meant for use by the
+     * asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start,
+     * mbedtls_ssl_config::f_async_decrypt_start,
+     * mbedtls_ssl_config::f_async_resume, mbedtls_ssl_config::f_async_cancel).
+     * The library does not use it internally. */
+    void *user_async_ctx;
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    const unsigned char *sni_name;      /*!< raw SNI                        */
+    size_t sni_name_len;                /*!< raw SNI len                    */
+#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+    const mbedtls_x509_crt *dn_hints;   /*!< acceptable client cert issuers */
+#endif
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+};
+
+typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer;
+
+/*
+ * Representation of decryption/encryption transformations on records
+ *
+ * There are the following general types of record transformations:
+ * - Stream transformations (TLS versions == 1.2 only)
+ *   Transformation adding a MAC and applying a stream-cipher
+ *   to the authenticated message.
+ * - CBC block cipher transformations ([D]TLS versions == 1.2 only)
+ *   For TLS 1.2, no IV is generated at key extraction time, but every
+ *   encrypted record is explicitly prefixed by the IV with which it was
+ *   encrypted.
+ * - AEAD transformations ([D]TLS versions == 1.2 only)
+ *   These come in two fundamentally different versions, the first one
+ *   used in TLS 1.2, excluding ChaChaPoly ciphersuites, and the second
+ *   one used for ChaChaPoly ciphersuites in TLS 1.2 as well as for TLS 1.3.
+ *   In the first transformation, the IV to be used for a record is obtained
+ *   as the concatenation of an explicit, static 4-byte IV and the 8-byte
+ *   record sequence number, and explicitly prepending this sequence number
+ *   to the encrypted record. In contrast, in the second transformation
+ *   the IV is obtained by XOR'ing a static IV obtained at key extraction
+ *   time with the 8-byte record sequence number, without prepending the
+ *   latter to the encrypted record.
+ *
+ * Additionally, DTLS 1.2 + CID as well as TLS 1.3 use an inner plaintext
+ * which allows to add flexible length padding and to hide a record's true
+ * content type.
+ *
+ * In addition to type and version, the following parameters are relevant:
+ * - The symmetric cipher algorithm to be used.
+ * - The (static) encryption/decryption keys for the cipher.
+ * - For stream/CBC, the type of message digest to be used.
+ * - For stream/CBC, (static) encryption/decryption keys for the digest.
+ * - For AEAD transformations, the size (potentially 0) of an explicit,
+ *   random initialization vector placed in encrypted records.
+ * - For some transformations (currently AEAD) an implicit IV. It is static
+ *   and (if present) is combined with the explicit IV in a transformation-
+ *   -dependent way (e.g. appending in TLS 1.2 and XOR'ing in TLS 1.3).
+ * - For stream/CBC, a flag determining the order of encryption and MAC.
+ * - The details of the transformation depend on the SSL/TLS version.
+ * - The length of the authentication tag.
+ *
+ * The struct below refines this abstract view as follows:
+ * - The cipher underlying the transformation is managed in
+ *   cipher contexts cipher_ctx_{enc/dec}, which must have the
+ *   same cipher type. The mode of these cipher contexts determines
+ *   the type of the transformation in the sense above: e.g., if
+ *   the type is MBEDTLS_CIPHER_AES_256_CBC resp. MBEDTLS_CIPHER_AES_192_GCM
+ *   then the transformation has type CBC resp. AEAD.
+ * - The cipher keys are never stored explicitly but
+ *   are maintained within cipher_ctx_{enc/dec}.
+ * - For stream/CBC transformations, the message digest contexts
+ *   used for the MAC's are stored in md_ctx_{enc/dec}. These contexts
+ *   are unused for AEAD transformations.
+ * - For stream/CBC transformations, the MAC keys are not stored explicitly
+ *   but maintained within md_ctx_{enc/dec}.
+ * - The mac_enc and mac_dec fields are unused for EAD transformations.
+ * - For transformations using an implicit IV maintained within
+ *   the transformation context, its contents are stored within
+ *   iv_{enc/dec}.
+ * - The value of ivlen indicates the length of the IV.
+ *   This is redundant in case of stream/CBC transformations
+ *   which always use 0 resp. the cipher's block length as the
+ *   IV length, but is needed for AEAD ciphers and may be
+ *   different from the underlying cipher's block length
+ *   in this case.
+ * - The field fixed_ivlen is nonzero for AEAD transformations only
+ *   and indicates the length of the static part of the IV which is
+ *   constant throughout the communication, and which is stored in
+ *   the first fixed_ivlen bytes of the iv_{enc/dec} arrays.
+ * - tls_version denotes the 2-byte TLS version
+ * - For stream/CBC transformations, maclen denotes the length of the
+ *   authentication tag, while taglen is unused and 0.
+ * - For AEAD transformations, taglen denotes the length of the
+ *   authentication tag, while maclen is unused and 0.
+ * - For CBC transformations, encrypt_then_mac determines the
+ *   order of encryption and authentication. This field is unused
+ *   in other transformations.
+ *
+ */
+struct mbedtls_ssl_transform {
+    /*
+     * Session specific crypto layer
+     */
+    size_t minlen;                      /*!<  min. ciphertext length  */
+    size_t ivlen;                       /*!<  IV length               */
+    size_t fixed_ivlen;                 /*!<  Fixed part of IV (AEAD) */
+    size_t maclen;                      /*!<  MAC(CBC) len            */
+    size_t taglen;                      /*!<  TAG(AEAD) len           */
+
+    unsigned char iv_enc[16];           /*!<  IV (encryption)         */
+    unsigned char iv_dec[16];           /*!<  IV (decryption)         */
+
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    mbedtls_svc_key_id_t psa_mac_enc;           /*!<  MAC (encryption)        */
+    mbedtls_svc_key_id_t psa_mac_dec;           /*!<  MAC (decryption)        */
+    psa_algorithm_t psa_mac_alg;                /*!<  psa MAC algorithm       */
+#else
+    mbedtls_md_context_t md_ctx_enc;            /*!<  MAC (encryption)        */
+    mbedtls_md_context_t md_ctx_dec;            /*!<  MAC (decryption)        */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+    int encrypt_then_mac;       /*!< flag for EtM activation                */
+#endif
+
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
+
+    mbedtls_ssl_protocol_version tls_version;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    mbedtls_svc_key_id_t psa_key_enc;           /*!<  psa encryption key      */
+    mbedtls_svc_key_id_t psa_key_dec;           /*!<  psa decryption key      */
+    psa_algorithm_t psa_alg;                    /*!<  psa algorithm           */
+#else
+    mbedtls_cipher_context_t cipher_ctx_enc;    /*!<  encryption context      */
+    mbedtls_cipher_context_t cipher_ctx_dec;    /*!<  decryption context      */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    uint8_t in_cid_len;
+    uint8_t out_cid_len;
+    unsigned char in_cid[MBEDTLS_SSL_CID_IN_LEN_MAX];
+    unsigned char out_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX];
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+    /* We need the Hello random bytes in order to re-derive keys from the
+     * Master Secret and other session info,
+     * see ssl_tls12_populate_transform() */
+    unsigned char randbytes[MBEDTLS_SERVER_HELLO_RANDOM_LEN +
+                            MBEDTLS_CLIENT_HELLO_RANDOM_LEN];
+    /*!< ServerHello.random+ClientHello.random */
+#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
+};
+
+/*
+ * Return 1 if the transform uses an AEAD cipher, 0 otherwise.
+ * Equivalently, return 0 if a separate MAC is used, 1 otherwise.
+ */
+static inline int mbedtls_ssl_transform_uses_aead(
+    const mbedtls_ssl_transform *transform)
+{
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
+    return transform->maclen == 0 && transform->taglen != 0;
+#else
+    (void) transform;
+    return 1;
+#endif
+}
+
+/*
+ * Internal representation of record frames
+ *
+ * Instances come in two flavors:
+ * (1) Encrypted
+ *     These always have data_offset = 0
+ * (2) Unencrypted
+ *     These have data_offset set to the amount of
+ *     pre-expansion during record protection. Concretely,
+ *     this is the length of the fixed part of the explicit IV
+ *     used for encryption, or 0 if no explicit IV is used
+ *     (e.g. for stream ciphers).
+ *
+ * The reason for the data_offset in the unencrypted case
+ * is to allow for in-place conversion of an unencrypted to
+ * an encrypted record. If the offset wasn't included, the
+ * encrypted content would need to be shifted afterwards to
+ * make space for the fixed IV.
+ *
+ */
+#if MBEDTLS_SSL_CID_OUT_LEN_MAX > MBEDTLS_SSL_CID_IN_LEN_MAX
+#define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_OUT_LEN_MAX
+#else
+#define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_IN_LEN_MAX
+#endif
+
+typedef struct {
+    uint8_t ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN];  /* In TLS:  The implicit record sequence number.
+                                                    * In DTLS: The 2-byte epoch followed by
+                                                    *          the 6-byte sequence number.
+                                                    * This is stored as a raw big endian byte array
+                                                    * as opposed to a uint64_t because we rarely
+                                                    * need to perform arithmetic on this, but do
+                                                    * need it as a Byte array for the purpose of
+                                                    * MAC computations.                             */
+    uint8_t type;           /* The record content type.                      */
+    uint8_t ver[2];         /* SSL/TLS version as present on the wire.
+                             * Convert to internal presentation of versions
+                             * using mbedtls_ssl_read_version() and
+                             * mbedtls_ssl_write_version().
+                             * Keep wire-format for MAC computations.        */
+
+    unsigned char *buf;     /* Memory buffer enclosing the record content    */
+    size_t buf_len;         /* Buffer length                                 */
+    size_t data_offset;     /* Offset of record content                      */
+    size_t data_len;        /* Length of record content                      */
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    uint8_t cid_len;        /* Length of the CID (0 if not present)          */
+    unsigned char cid[MBEDTLS_SSL_CID_LEN_MAX];   /* The CID                 */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+} mbedtls_record;
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+/*
+ * List of certificate + private key pairs
+ */
+struct mbedtls_ssl_key_cert {
+    mbedtls_x509_crt *cert;                 /*!< cert                       */
+    mbedtls_pk_context *key;                /*!< private key                */
+    mbedtls_ssl_key_cert *next;             /*!< next key/cert pair         */
+};
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+/*
+ * List of handshake messages kept around for resending
+ */
+struct mbedtls_ssl_flight_item {
+    unsigned char *p;       /*!< message, including handshake headers   */
+    size_t len;             /*!< length of p                            */
+    unsigned char type;     /*!< type of the message: handshake or CCS  */
+    mbedtls_ssl_flight_item *next;  /*!< next handshake message(s)              */
+};
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+/**
+ * \brief Given an SSL context and its associated configuration, write the TLS
+ *        1.2 specific extensions of the ClientHello message.
+ *
+ * \param[in]   ssl     SSL context
+ * \param[in]   buf     Base address of the buffer where to write the extensions
+ * \param[in]   end     End address of the buffer where to write the extensions
+ * \param       uses_ec Whether one proposed ciphersuite uses an elliptic curve
+ *                      (<> 0) or not ( 0 ).
+ * \param[out]  out_len Length of the data written into the buffer \p buf
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls12_write_client_hello_exts(mbedtls_ssl_context *ssl,
+                                              unsigned char *buf,
+                                              const unsigned char *end,
+                                              int uses_ec,
+                                              size_t *out_len);
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
+    defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+
+/**
+ * \brief Find the preferred hash for a given signature algorithm.
+ *
+ * \param[in]   ssl     SSL context
+ * \param[in]   sig_alg A signature algorithm identifier as defined in the
+ *                      TLS 1.2 SignatureAlgorithm enumeration.
+ *
+ * \return  The preferred hash algorithm for \p sig_alg. It is a hash algorithm
+ *          identifier as defined in the TLS 1.2 HashAlgorithm enumeration.
+ */
+unsigned int mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg(
+    mbedtls_ssl_context *ssl,
+    unsigned int sig_alg);
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
+          MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
+/**
+ * \brief           Free referenced items in an SSL transform context and clear
+ *                  memory
+ *
+ * \param transform SSL transform context
+ */
+void mbedtls_ssl_transform_free(mbedtls_ssl_transform *transform);
+
+/**
+ * \brief           Free referenced items in an SSL handshake context and clear
+ *                  memory
+ *
+ * \param ssl       SSL context
+ */
+void mbedtls_ssl_handshake_free(mbedtls_ssl_context *ssl);
+
+/* set inbound transform of ssl context */
+void mbedtls_ssl_set_inbound_transform(mbedtls_ssl_context *ssl,
+                                       mbedtls_ssl_transform *transform);
+
+/* set outbound transform of ssl context */
+void mbedtls_ssl_set_outbound_transform(mbedtls_ssl_context *ssl,
+                                        mbedtls_ssl_transform *transform);
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl);
+void mbedtls_ssl_handshake_wrapup(mbedtls_ssl_context *ssl);
+static inline void mbedtls_ssl_handshake_set_state(mbedtls_ssl_context *ssl,
+                                                   mbedtls_ssl_states state)
+{
+    ssl->state = (int) state;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_send_fatal_handshake_failure(mbedtls_ssl_context *ssl);
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl);
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_derive_keys(mbedtls_ssl_context *ssl);
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2  */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl);
+
+/**
+ * \brief       Update record layer
+ *
+ *              This function roughly separates the implementation
+ *              of the logic of (D)TLS from the implementation
+ *              of the secure transport.
+ *
+ * \param  ssl              The SSL context to use.
+ * \param  update_hs_digest This indicates if the handshake digest
+ *                          should be automatically updated in case
+ *                          a handshake message is found.
+ *
+ * \return      0 or non-zero error code.
+ *
+ * \note        A clarification on what is called 'record layer' here
+ *              is in order, as many sensible definitions are possible:
+ *
+ *              The record layer takes as input an untrusted underlying
+ *              transport (stream or datagram) and transforms it into
+ *              a serially multiplexed, secure transport, which
+ *              conceptually provides the following:
+ *
+ *              (1) Three datagram based, content-agnostic transports
+ *                  for handshake, alert and CCS messages.
+ *              (2) One stream- or datagram-based transport
+ *                  for application data.
+ *              (3) Functionality for changing the underlying transform
+ *                  securing the contents.
+ *
+ *              The interface to this functionality is given as follows:
+ *
+ *              a Updating
+ *                [Currently implemented by mbedtls_ssl_read_record]
+ *
+ *                Check if and on which of the four 'ports' data is pending:
+ *                Nothing, a controlling datagram of type (1), or application
+ *                data (2). In any case data is present, internal buffers
+ *                provide access to the data for the user to process it.
+ *                Consumption of type (1) datagrams is done automatically
+ *                on the next update, invalidating that the internal buffers
+ *                for previous datagrams, while consumption of application
+ *                data (2) is user-controlled.
+ *
+ *              b Reading of application data
+ *                [Currently manual adaption of ssl->in_offt pointer]
+ *
+ *                As mentioned in the last paragraph, consumption of data
+ *                is different from the automatic consumption of control
+ *                datagrams (1) because application data is treated as a stream.
+ *
+ *              c Tracking availability of application data
+ *                [Currently manually through decreasing ssl->in_msglen]
+ *
+ *                For efficiency and to retain datagram semantics for
+ *                application data in case of DTLS, the record layer
+ *                provides functionality for checking how much application
+ *                data is still available in the internal buffer.
+ *
+ *              d Changing the transformation securing the communication.
+ *
+ *              Given an opaque implementation of the record layer in the
+ *              above sense, it should be possible to implement the logic
+ *              of (D)TLS on top of it without the need to know anything
+ *              about the record layer's internals. This is done e.g.
+ *              in all the handshake handling functions, and in the
+ *              application data reading function mbedtls_ssl_read.
+ *
+ * \note        The above tries to give a conceptual picture of the
+ *              record layer, but the current implementation deviates
+ *              from it in some places. For example, our implementation of
+ *              the update functionality through mbedtls_ssl_read_record
+ *              discards datagrams depending on the current state, which
+ *              wouldn't fall under the record layer's responsibility
+ *              following the above definition.
+ *
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_read_record(mbedtls_ssl_context *ssl,
+                            unsigned update_hs_digest);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want);
+
+/*
+ * Write handshake message header
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned hs_type,
+                                    unsigned char **buf, size_t *buf_len);
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_write_handshake_msg_ext(mbedtls_ssl_context *ssl,
+                                        int update_checksum,
+                                        int force_flush);
+static inline int mbedtls_ssl_write_handshake_msg(mbedtls_ssl_context *ssl)
+{
+    return mbedtls_ssl_write_handshake_msg_ext(ssl, 1 /* update checksum */, 1 /* force flush */);
+}
+
+/*
+ * Write handshake message tail
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_finish_handshake_msg(mbedtls_ssl_context *ssl,
+                                     size_t buf_len, size_t msg_len);
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, int force_flush);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_flush_output(mbedtls_ssl_context *ssl);
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl);
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_parse_change_cipher_spec(mbedtls_ssl_context *ssl);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_write_change_cipher_spec(mbedtls_ssl_context *ssl);
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_parse_finished(mbedtls_ssl_context *ssl);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_write_finished(mbedtls_ssl_context *ssl);
+
+void mbedtls_ssl_optimize_checksum(mbedtls_ssl_context *ssl,
+                                   const mbedtls_ssl_ciphersuite_t *ciphersuite_info);
+
+/*
+ * Update checksum of handshake messages.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_add_hs_msg_to_checksum(mbedtls_ssl_context *ssl,
+                                       unsigned hs_type,
+                                       unsigned char const *msg,
+                                       size_t msg_len);
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_add_hs_hdr_to_checksum(mbedtls_ssl_context *ssl,
+                                       unsigned hs_type,
+                                       size_t total_hs_len);
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl,
+                                     mbedtls_key_exchange_type_t key_ex);
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
+#if defined(MBEDTLS_SSL_CLI_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_conf_has_static_psk(mbedtls_ssl_config const *conf);
+#endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+/**
+ * Get the first defined opaque PSK by order of precedence:
+ * 1. handshake PSK set by \c mbedtls_ssl_set_hs_psk_opaque() in the PSK
+ *    callback
+ * 2. static PSK configured by \c mbedtls_ssl_conf_psk_opaque()
+ * Return an opaque PSK
+ */
+static inline mbedtls_svc_key_id_t mbedtls_ssl_get_opaque_psk(
+    const mbedtls_ssl_context *ssl)
+{
+    if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) {
+        return ssl->handshake->psk_opaque;
+    }
+
+    if (!mbedtls_svc_key_id_is_null(ssl->conf->psk_opaque)) {
+        return ssl->conf->psk_opaque;
+    }
+
+    return MBEDTLS_SVC_KEY_ID_INIT;
+}
+#else
+/**
+ * Get the first defined PSK by order of precedence:
+ * 1. handshake PSK set by \c mbedtls_ssl_set_hs_psk() in the PSK callback
+ * 2. static PSK configured by \c mbedtls_ssl_conf_psk()
+ * Return a code and update the pair (PSK, PSK length) passed to this function
+ */
+static inline int mbedtls_ssl_get_psk(const mbedtls_ssl_context *ssl,
+                                      const unsigned char **psk, size_t *psk_len)
+{
+    if (ssl->handshake->psk != NULL && ssl->handshake->psk_len > 0) {
+        *psk = ssl->handshake->psk;
+        *psk_len = ssl->handshake->psk_len;
+    } else if (ssl->conf->psk != NULL && ssl->conf->psk_len > 0) {
+        *psk = ssl->conf->psk;
+        *psk_len = ssl->conf->psk_len;
+    } else {
+        *psk = NULL;
+        *psk_len = 0;
+        return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED;
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
+
+#if defined(MBEDTLS_PK_C)
+unsigned char mbedtls_ssl_sig_from_pk(mbedtls_pk_context *pk);
+unsigned char mbedtls_ssl_sig_from_pk_alg(mbedtls_pk_type_t type);
+mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig(unsigned char sig);
+#endif
+
+mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash(unsigned char hash);
+unsigned char mbedtls_ssl_hash_from_md_alg(int md);
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md);
+#endif
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_check_curve_tls_id(const mbedtls_ssl_context *ssl, uint16_t tls_id);
+#if defined(MBEDTLS_ECP_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id);
+#endif
+
+/**
+ * \brief Return PSA EC info for the specified TLS ID.
+ *
+ * \param tls_id    The TLS ID to look for
+ * \param family    If the TLD ID is supported, then proper \c psa_ecc_family_t
+ *                  value is returned here. Can be NULL.
+ * \param bits      If the TLD ID is supported, then proper bit size is returned
+ *                  here. Can be NULL.
+ * \return          PSA_SUCCESS if the TLS ID is supported,
+ *                  PSA_ERROR_NOT_SUPPORTED otherwise
+ *
+ * \note            If either \c family or \c bits parameters are NULL, then
+ *                  the corresponding value is not returned.
+ *                  The function can be called with both parameters as NULL
+ *                  simply to check if a specific TLS ID is supported.
+ */
+int mbedtls_ssl_get_psa_curve_info_from_tls_id(uint16_t tls_id,
+                                               psa_ecc_family_t *family,
+                                               size_t *bits);
+
+/**
+ * \brief Return \c mbedtls_ecp_group_id for the specified TLS ID.
+ *
+ * \param tls_id    The TLS ID to look for
+ * \return          Proper \c mbedtls_ecp_group_id if the TLS ID is supported,
+ *                  or MBEDTLS_ECP_DP_NONE otherwise
+ */
+mbedtls_ecp_group_id mbedtls_ssl_get_ecp_group_id_from_tls_id(uint16_t tls_id);
+
+/**
+ * \brief Return TLS ID for the specified \c mbedtls_ecp_group_id.
+ *
+ * \param grp_id    The \c mbedtls_ecp_group_id ID to look for
+ * \return          Proper TLS ID if the \c mbedtls_ecp_group_id is supported,
+ *                  or 0 otherwise
+ */
+uint16_t mbedtls_ssl_get_tls_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id);
+
+#if defined(MBEDTLS_DEBUG_C)
+/**
+ * \brief Return EC's name for the specified TLS ID.
+ *
+ * \param tls_id    The TLS ID to look for
+ * \return          A pointer to a const string with the proper name. If TLS
+ *                  ID is not supported, a NULL pointer is returned instead.
+ */
+const char *mbedtls_ssl_get_curve_name_from_tls_id(uint16_t tls_id);
+#endif
+
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+static inline mbedtls_ssl_srtp_profile mbedtls_ssl_check_srtp_profile_value
+    (const uint16_t srtp_profile_value)
+{
+    switch (srtp_profile_value) {
+        case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80:
+        case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32:
+        case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80:
+        case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32:
+            return srtp_profile_value;
+        default: break;
+    }
+    return MBEDTLS_TLS_SRTP_UNSET;
+}
+#endif
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+static inline mbedtls_pk_context *mbedtls_ssl_own_key(mbedtls_ssl_context *ssl)
+{
+    mbedtls_ssl_key_cert *key_cert;
+
+    if (ssl->handshake != NULL && ssl->handshake->key_cert != NULL) {
+        key_cert = ssl->handshake->key_cert;
+    } else {
+        key_cert = ssl->conf->key_cert;
+    }
+
+    return key_cert == NULL ? NULL : key_cert->key;
+}
+
+static inline mbedtls_x509_crt *mbedtls_ssl_own_cert(mbedtls_ssl_context *ssl)
+{
+    mbedtls_ssl_key_cert *key_cert;
+
+    if (ssl->handshake != NULL && ssl->handshake->key_cert != NULL) {
+        key_cert = ssl->handshake->key_cert;
+    } else {
+        key_cert = ssl->conf->key_cert;
+    }
+
+    return key_cert == NULL ? NULL : key_cert->cert;
+}
+
+/*
+ * Check usage of a certificate wrt extensions:
+ * keyUsage, extendedKeyUsage (later), and nSCertType (later).
+ *
+ * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we
+ * check a cert we received from them)!
+ *
+ * Return 0 if everything is OK, -1 if not.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert,
+                                 const mbedtls_ssl_ciphersuite_t *ciphersuite,
+                                 int cert_endpoint,
+                                 uint32_t *flags);
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+void mbedtls_ssl_write_version(unsigned char version[2], int transport,
+                               mbedtls_ssl_protocol_version tls_version);
+uint16_t mbedtls_ssl_read_version(const unsigned char version[2],
+                                  int transport);
+
+static inline size_t mbedtls_ssl_in_hdr_len(const mbedtls_ssl_context *ssl)
+{
+#if !defined(MBEDTLS_SSL_PROTO_DTLS)
+    ((void) ssl);
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        return 13;
+    } else
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+    {
+        return 5;
+    }
+}
+
+static inline size_t mbedtls_ssl_out_hdr_len(const mbedtls_ssl_context *ssl)
+{
+    return (size_t) (ssl->out_iv - ssl->out_hdr);
+}
+
+static inline size_t mbedtls_ssl_hs_hdr_len(const mbedtls_ssl_context *ssl)
+{
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        return 12;
+    }
+#else
+    ((void) ssl);
+#endif
+    return 4;
+}
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+void mbedtls_ssl_send_flight_completed(mbedtls_ssl_context *ssl);
+void mbedtls_ssl_recv_flight_completed(mbedtls_ssl_context *ssl);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_resend(mbedtls_ssl_context *ssl);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_flight_transmit(mbedtls_ssl_context *ssl);
+#endif
+
+/* Visible for testing purposes only */
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_dtls_replay_check(mbedtls_ssl_context const *ssl);
+void mbedtls_ssl_dtls_replay_update(mbedtls_ssl_context *ssl);
+#endif
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_session_copy(mbedtls_ssl_session *dst,
+                             const mbedtls_ssl_session *src);
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+/* The hash buffer must have at least MBEDTLS_MD_MAX_SIZE bytes of length. */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl,
+                                           unsigned char *hash, size_t *hashlen,
+                                           unsigned char *data, size_t data_len,
+                                           mbedtls_md_type_t md_alg);
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+#ifdef __cplusplus
+}
+#endif
+
+void mbedtls_ssl_transform_init(mbedtls_ssl_transform *transform);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl,
+                            mbedtls_ssl_transform *transform,
+                            mbedtls_record *rec,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl,
+                            mbedtls_ssl_transform *transform,
+                            mbedtls_record *rec);
+
+/* Length of the "epoch" field in the record header */
+static inline size_t mbedtls_ssl_ep_len(const mbedtls_ssl_context *ssl)
+{
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        return 2;
+    }
+#else
+    ((void) ssl);
+#endif
+    return 0;
+}
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_resend_hello_request(mbedtls_ssl_context *ssl);
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+void mbedtls_ssl_set_timer(mbedtls_ssl_context *ssl, uint32_t millisecs);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_check_timer(mbedtls_ssl_context *ssl);
+
+void mbedtls_ssl_reset_in_out_pointers(mbedtls_ssl_context *ssl);
+void mbedtls_ssl_update_out_pointers(mbedtls_ssl_context *ssl,
+                                     mbedtls_ssl_transform *transform);
+void mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl);
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial);
+void mbedtls_ssl_session_reset_msg_layer(mbedtls_ssl_context *ssl,
+                                         int partial);
+
+/*
+ * Send pending alert
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_handle_pending_alert(mbedtls_ssl_context *ssl);
+
+/*
+ * Set pending fatal alert flag.
+ */
+void mbedtls_ssl_pend_fatal_alert(mbedtls_ssl_context *ssl,
+                                  unsigned char alert_type,
+                                  int alert_reason);
+
+/* Alias of mbedtls_ssl_pend_fatal_alert */
+#define MBEDTLS_SSL_PEND_FATAL_ALERT(type, user_return_value)         \
+    mbedtls_ssl_pend_fatal_alert(ssl, type, user_return_value)
+
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+void mbedtls_ssl_dtls_replay_reset(mbedtls_ssl_context *ssl);
+#endif
+
+void mbedtls_ssl_handshake_wrapup_free_hs_transform(mbedtls_ssl_context *ssl);
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_start_renegotiation(mbedtls_ssl_context *ssl);
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+size_t mbedtls_ssl_get_current_mtu(const mbedtls_ssl_context *ssl);
+void mbedtls_ssl_buffering_free(mbedtls_ssl_context *ssl);
+void mbedtls_ssl_flight_free(mbedtls_ssl_flight_item *flight);
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+/**
+ * ssl utils functions for checking configuration.
+ */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+static inline int mbedtls_ssl_conf_is_tls13_only(const mbedtls_ssl_config *conf)
+{
+    return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 &&
+           conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3;
+}
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+static inline int mbedtls_ssl_conf_is_tls12_only(const mbedtls_ssl_config *conf)
+{
+    return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_2 &&
+           conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_2;
+}
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+static inline int mbedtls_ssl_conf_is_tls13_enabled(const mbedtls_ssl_config *conf)
+{
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    return conf->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_3 &&
+           conf->max_tls_version >= MBEDTLS_SSL_VERSION_TLS1_3;
+#else
+    ((void) conf);
+    return 0;
+#endif
+}
+
+static inline int mbedtls_ssl_conf_is_tls12_enabled(const mbedtls_ssl_config *conf)
+{
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    return conf->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2 &&
+           conf->max_tls_version >= MBEDTLS_SSL_VERSION_TLS1_2;
+#else
+    ((void) conf);
+    return 0;
+#endif
+}
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
+static inline int mbedtls_ssl_conf_is_hybrid_tls12_tls13(const mbedtls_ssl_config *conf)
+{
+    return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_2 &&
+           conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3;
+}
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_TLS1_3 */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+extern const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[
+    MBEDTLS_SERVER_HELLO_RANDOM_LEN];
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_process_finished_message(mbedtls_ssl_context *ssl);
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_write_finished_message(mbedtls_ssl_context *ssl);
+void mbedtls_ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl);
+
+/**
+ * \brief Given an SSL context and its associated configuration, write the TLS
+ *        1.3 specific extensions of the ClientHello message.
+ *
+ * \param[in]   ssl     SSL context
+ * \param[in]   buf     Base address of the buffer where to write the extensions
+ * \param[in]   end     End address of the buffer where to write the extensions
+ * \param[out]  out_len Length of the data written into the buffer \p buf
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl,
+                                              unsigned char *buf,
+                                              unsigned char *end,
+                                              size_t *out_len);
+
+/**
+ * \brief           TLS 1.3 client side state machine entry
+ *
+ * \param ssl       SSL context
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl);
+
+/**
+ * \brief           TLS 1.3 server side state machine entry
+ *
+ * \param ssl       SSL context
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl);
+
+
+/*
+ * Helper functions around key exchange modes.
+ */
+static inline unsigned mbedtls_ssl_conf_tls13_check_kex_modes(mbedtls_ssl_context *ssl,
+                                                              int kex_mode_mask)
+{
+    return (ssl->conf->tls13_kex_modes & kex_mode_mask) != 0;
+}
+
+static inline int mbedtls_ssl_conf_tls13_psk_enabled(mbedtls_ssl_context *ssl)
+{
+    return mbedtls_ssl_conf_tls13_check_kex_modes(ssl,
+                                                  MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK);
+}
+
+static inline int mbedtls_ssl_conf_tls13_psk_ephemeral_enabled(mbedtls_ssl_context *ssl)
+{
+    return mbedtls_ssl_conf_tls13_check_kex_modes(ssl,
+                                                  MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL);
+}
+
+static inline int mbedtls_ssl_conf_tls13_ephemeral_enabled(mbedtls_ssl_context *ssl)
+{
+    return mbedtls_ssl_conf_tls13_check_kex_modes(ssl,
+                                                  MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL);
+}
+
+static inline int mbedtls_ssl_conf_tls13_some_ephemeral_enabled(mbedtls_ssl_context *ssl)
+{
+    return mbedtls_ssl_conf_tls13_check_kex_modes(ssl,
+                                                  MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL);
+}
+
+static inline int mbedtls_ssl_conf_tls13_some_psk_enabled(mbedtls_ssl_context *ssl)
+{
+    return mbedtls_ssl_conf_tls13_check_kex_modes(ssl,
+                                                  MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL);
+}
+
+#if defined(MBEDTLS_SSL_SRV_C) && \
+    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+/**
+ * Given a list of key exchange modes, check if at least one of them is
+ * supported.
+ *
+ * \param[in] ssl  SSL context
+ * \param kex_modes_mask  Mask of the key exchange modes to check
+ *
+ * \return 0 if at least one of the key exchange modes is supported,
+ *         !=0 otherwise.
+ */
+static inline unsigned mbedtls_ssl_tls13_check_kex_modes(mbedtls_ssl_context *ssl,
+                                                         int kex_modes_mask)
+{
+    return (ssl->handshake->tls13_kex_modes & kex_modes_mask) == 0;
+}
+
+static inline int mbedtls_ssl_tls13_psk_enabled(mbedtls_ssl_context *ssl)
+{
+    return !mbedtls_ssl_tls13_check_kex_modes(ssl,
+                                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK);
+}
+
+static inline int mbedtls_ssl_tls13_psk_ephemeral_enabled(
+    mbedtls_ssl_context *ssl)
+{
+    return !mbedtls_ssl_tls13_check_kex_modes(ssl,
+                                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL);
+}
+
+static inline int mbedtls_ssl_tls13_ephemeral_enabled(mbedtls_ssl_context *ssl)
+{
+    return !mbedtls_ssl_tls13_check_kex_modes(ssl,
+                                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL);
+}
+
+static inline int mbedtls_ssl_tls13_some_ephemeral_enabled(mbedtls_ssl_context *ssl)
+{
+    return !mbedtls_ssl_tls13_check_kex_modes(ssl,
+                                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL);
+}
+
+static inline int mbedtls_ssl_tls13_some_psk_enabled(mbedtls_ssl_context *ssl)
+{
+    return !mbedtls_ssl_tls13_check_kex_modes(ssl,
+                                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL);
+}
+#endif /* MBEDTLS_SSL_SRV_C &&
+          MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
+
+/*
+ * Helper functions for extensions checking.
+ */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_check_received_extension(
+    mbedtls_ssl_context *ssl,
+    int hs_msg_type,
+    unsigned int received_extension_type,
+    uint32_t hs_msg_allowed_extensions_mask);
+
+static inline void mbedtls_ssl_tls13_set_hs_sent_ext_mask(
+    mbedtls_ssl_context *ssl, unsigned int extension_type)
+{
+    ssl->handshake->sent_extensions |=
+        mbedtls_ssl_get_extension_mask(extension_type);
+}
+
+/*
+ * Helper functions to check the selected key exchange mode.
+ */
+static inline int mbedtls_ssl_tls13_key_exchange_mode_check(
+    mbedtls_ssl_context *ssl, int kex_mask)
+{
+    return (ssl->handshake->key_exchange_mode & kex_mask) != 0;
+}
+
+static inline int mbedtls_ssl_tls13_key_exchange_mode_with_psk(
+    mbedtls_ssl_context *ssl)
+{
+    return mbedtls_ssl_tls13_key_exchange_mode_check(ssl,
+                                                     MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL);
+}
+
+static inline int mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(
+    mbedtls_ssl_context *ssl)
+{
+    return mbedtls_ssl_tls13_key_exchange_mode_check(ssl,
+                                                     MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL);
+}
+
+/*
+ * Fetch TLS 1.3 handshake message header
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl,
+                                          unsigned hs_type,
+                                          unsigned char **buf,
+                                          size_t *buf_len);
+
+/*
+ * Handler of TLS 1.3 server certificate message
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_process_certificate(mbedtls_ssl_context *ssl);
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+/*
+ * Handler of TLS 1.3 write Certificate message
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_write_certificate(mbedtls_ssl_context *ssl);
+
+/*
+ * Handler of TLS 1.3 write Certificate Verify message
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl);
+
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+
+/*
+ * Generic handler of Certificate Verify
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl);
+
+/*
+ * Write of dummy-CCS's for middlebox compatibility
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl);
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_reset_transcript_for_hrr(mbedtls_ssl_context *ssl);
+
+#if defined(MBEDTLS_ECDH_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange(
+    mbedtls_ssl_context *ssl,
+    uint16_t named_group,
+    unsigned char *buf,
+    unsigned char *end,
+    size_t *out_len);
+#endif /* MBEDTLS_ECDH_C */
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl,
+                                           unsigned char *buf,
+                                           const unsigned char *end,
+                                           size_t *out_len);
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+/*
+ * Write Signature Algorithm extension
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_write_sig_alg_ext(mbedtls_ssl_context *ssl, unsigned char *buf,
+                                  const unsigned char *end, size_t *out_len);
+/*
+ * Parse TLS Signature Algorithm extension
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_parse_sig_alg_ext(mbedtls_ssl_context *ssl,
+                                  const unsigned char *buf,
+                                  const unsigned char *end);
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
+
+/* Get handshake transcript */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl,
+                                         const mbedtls_md_type_t md,
+                                         unsigned char *dst,
+                                         size_t dst_len,
+                                         size_t *olen);
+
+/*
+ * Return supported groups.
+ *
+ * In future, invocations can be changed to ssl->conf->group_list
+ * when mbedtls_ssl_conf_curves() is deleted.
+ *
+ * ssl->handshake->group_list is either a translation of curve_list to IANA TLS group
+ * identifiers when mbedtls_ssl_conf_curves() has been used, or a pointer to
+ * ssl->conf->group_list when mbedtls_ssl_conf_groups() has been more recently invoked.
+ *
+ */
+static inline const void *mbedtls_ssl_get_groups(const mbedtls_ssl_context *ssl)
+{
+    #if defined(MBEDTLS_DEPRECATED_REMOVED) || !defined(MBEDTLS_ECP_C)
+    return ssl->conf->group_list;
+    #else
+    if ((ssl->handshake != NULL) && (ssl->handshake->group_list != NULL)) {
+        return ssl->handshake->group_list;
+    } else {
+        return ssl->conf->group_list;
+    }
+    #endif
+}
+
+/*
+ * Helper functions for NamedGroup.
+ */
+static inline int mbedtls_ssl_tls12_named_group_is_ecdhe(uint16_t named_group)
+{
+    /*
+     * RFC 8422 section 5.1.1
+     */
+    return named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X25519    ||
+           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1   ||
+           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1   ||
+           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1   ||
+           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X448      ||
+           /* Below deprecated curves should be removed with notice to users */
+           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1 ||
+           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1 ||
+           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1 ||
+           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1 ||
+           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1 ||
+           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 ||
+           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 ||
+           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1;
+}
+
+static inline int mbedtls_ssl_tls13_named_group_is_ecdhe(uint16_t named_group)
+{
+    return named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X25519    ||
+           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 ||
+           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 ||
+           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1 ||
+           named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X448;
+}
+
+static inline int mbedtls_ssl_tls13_named_group_is_dhe(uint16_t named_group)
+{
+    return named_group >= MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048 &&
+           named_group <= MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192;
+}
+
+static inline int mbedtls_ssl_named_group_is_offered(
+    const mbedtls_ssl_context *ssl, uint16_t named_group)
+{
+    const uint16_t *group_list = mbedtls_ssl_get_groups(ssl);
+
+    if (group_list == NULL) {
+        return 0;
+    }
+
+    for (; *group_list != 0; group_list++) {
+        if (*group_list == named_group) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+static inline int mbedtls_ssl_named_group_is_supported(uint16_t named_group)
+{
+#if defined(MBEDTLS_ECDH_C)
+    if (mbedtls_ssl_tls13_named_group_is_ecdhe(named_group)) {
+        if (mbedtls_ssl_get_ecp_group_id_from_tls_id(named_group) !=
+            MBEDTLS_ECP_DP_NONE) {
+            return 1;
+        }
+    }
+#else
+    ((void) named_group);
+#endif /* MBEDTLS_ECDH_C */
+    return 0;
+}
+
+/*
+ * Return supported signature algorithms.
+ *
+ * In future, invocations can be changed to ssl->conf->sig_algs when
+ * mbedtls_ssl_conf_sig_hashes() is deleted.
+ *
+ * ssl->handshake->sig_algs is either a translation of sig_hashes to IANA TLS
+ * signature algorithm identifiers when mbedtls_ssl_conf_sig_hashes() has been
+ * used, or a pointer to ssl->conf->sig_algs when mbedtls_ssl_conf_sig_algs() has
+ * been more recently invoked.
+ *
+ */
+static inline const void *mbedtls_ssl_get_sig_algs(
+    const mbedtls_ssl_context *ssl)
+{
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+    if (ssl->handshake != NULL &&
+        ssl->handshake->sig_algs_heap_allocated == 1 &&
+        ssl->handshake->sig_algs != NULL) {
+        return ssl->handshake->sig_algs;
+    }
+#endif
+    return ssl->conf->sig_algs;
+
+#else /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
+
+    ((void) ssl);
+    return NULL;
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
+}
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+static inline int mbedtls_ssl_sig_alg_is_received(const mbedtls_ssl_context *ssl,
+                                                  uint16_t own_sig_alg)
+{
+    const uint16_t *sig_alg = ssl->handshake->received_sig_algs;
+    if (sig_alg == NULL) {
+        return 0;
+    }
+
+    for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) {
+        if (*sig_alg == own_sig_alg) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static inline int mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(
+    const uint16_t sig_alg)
+{
+    switch (sig_alg) {
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
+#if defined(PSA_WANT_ALG_SHA_256) && defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+        case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256:
+            break;
+#endif /* PSA_WANT_ALG_SHA_256 && MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+#if defined(PSA_WANT_ALG_SHA_384) && defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+        case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384:
+            break;
+#endif /* PSA_WANT_ALG_SHA_384 && MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+#if defined(PSA_WANT_ALG_SHA_512) && defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+        case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512:
+            break;
+#endif /* PSA_WANT_ALG_SHA_512 && MBEDTLS_ECP_DP_SECP521R1_ENABLED */
+#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */
+
+#if defined(MBEDTLS_PKCS1_V21)
+#if defined(PSA_WANT_ALG_SHA_256)
+        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256:
+            break;
+#endif /* PSA_WANT_ALG_SHA_256  */
+#if defined(PSA_WANT_ALG_SHA_384)
+        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384:
+            break;
+#endif /* PSA_WANT_ALG_SHA_384 */
+#if defined(PSA_WANT_ALG_SHA_512)
+        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512:
+            break;
+#endif /* PSA_WANT_ALG_SHA_512 */
+#endif /* MBEDTLS_PKCS1_V21 */
+        default:
+            return 0;
+    }
+    return 1;
+
+}
+
+static inline int mbedtls_ssl_tls13_sig_alg_is_supported(
+    const uint16_t sig_alg)
+{
+    switch (sig_alg) {
+#if defined(MBEDTLS_PKCS1_V15)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256:
+            break;
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384:
+            break;
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512:
+            break;
+#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_PKCS1_V15 */
+        default:
+            return mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(
+                sig_alg);
+    }
+    return 1;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_check_sig_alg_cert_key_match(uint16_t sig_alg,
+                                                   mbedtls_pk_context *key);
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+static inline int mbedtls_ssl_sig_alg_is_offered(const mbedtls_ssl_context *ssl,
+                                                 uint16_t proposed_sig_alg)
+{
+    const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl);
+    if (sig_alg == NULL) {
+        return 0;
+    }
+
+    for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) {
+        if (*sig_alg == proposed_sig_alg) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static inline int mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg(
+    uint16_t sig_alg, mbedtls_pk_type_t *pk_type, mbedtls_md_type_t *md_alg)
+{
+    *pk_type = mbedtls_ssl_pk_alg_from_sig(sig_alg & 0xff);
+    *md_alg = mbedtls_ssl_md_alg_from_hash((sig_alg >> 8) & 0xff);
+
+    if (*pk_type != MBEDTLS_PK_NONE && *md_alg != MBEDTLS_MD_NONE) {
+        return 0;
+    }
+
+    switch (sig_alg) {
+#if defined(MBEDTLS_PKCS1_V21)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256:
+            *md_alg = MBEDTLS_MD_SHA256;
+            *pk_type = MBEDTLS_PK_RSASSA_PSS;
+            break;
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA  */
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384:
+            *md_alg = MBEDTLS_MD_SHA384;
+            *pk_type = MBEDTLS_PK_RSASSA_PSS;
+            break;
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512:
+            *md_alg = MBEDTLS_MD_SHA512;
+            *pk_type = MBEDTLS_PK_RSASSA_PSS;
+            break;
+#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_PKCS1_V21 */
+        default:
+            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    }
+    return 0;
+}
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+static inline int mbedtls_ssl_tls12_sig_alg_is_supported(
+    const uint16_t sig_alg)
+{
+    /* High byte is hash */
+    unsigned char hash = MBEDTLS_BYTE_1(sig_alg);
+    unsigned char sig = MBEDTLS_BYTE_0(sig_alg);
+
+    switch (hash) {
+#if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_SSL_HASH_MD5:
+            break;
+#endif
+
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_SSL_HASH_SHA1:
+            break;
+#endif
+
+#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_SSL_HASH_SHA224:
+            break;
+#endif
+
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_SSL_HASH_SHA256:
+            break;
+#endif
+
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_SSL_HASH_SHA384:
+            break;
+#endif
+
+#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_SSL_HASH_SHA512:
+            break;
+#endif
+
+        default:
+            return 0;
+    }
+
+    switch (sig) {
+#if defined(MBEDTLS_RSA_C)
+        case MBEDTLS_SSL_SIG_RSA:
+            break;
+#endif
+
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
+        case MBEDTLS_SSL_SIG_ECDSA:
+            break;
+#endif
+
+        default:
+            return 0;
+    }
+
+    return 1;
+}
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+static inline int mbedtls_ssl_sig_alg_is_supported(
+    const mbedtls_ssl_context *ssl,
+    const uint16_t sig_alg)
+{
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {
+        return mbedtls_ssl_tls12_sig_alg_is_supported(sig_alg);
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
+        return mbedtls_ssl_tls13_sig_alg_is_supported(sig_alg);
+    }
+#endif
+    ((void) ssl);
+    ((void) sig_alg);
+    return 0;
+}
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
+/* Corresponding PSA algorithm for MBEDTLS_CIPHER_NULL.
+ * Same value is used for PSA_ALG_CATEGORY_CIPHER, hence it is
+ * guaranteed to not be a valid PSA algorithm identifier.
+ */
+#define MBEDTLS_SSL_NULL_CIPHER 0x04000000
+
+/**
+ * \brief       Translate mbedtls cipher type/taglen pair to psa:
+ *              algorithm, key type and key size.
+ *
+ * \param  mbedtls_cipher_type [in] given mbedtls cipher type
+ * \param  taglen              [in] given tag length
+ *                                  0 - default tag length
+ * \param  alg                 [out] corresponding PSA alg
+ *                                   There is no corresponding PSA
+ *                                   alg for MBEDTLS_CIPHER_NULL, so
+ *                                   in this case MBEDTLS_SSL_NULL_CIPHER
+ *                                   is returned via this parameter
+ * \param  key_type            [out] corresponding PSA key type
+ * \param  key_size            [out] corresponding PSA key size
+ *
+ * \return                     PSA_SUCCESS on success or PSA_ERROR_NOT_SUPPORTED if
+ *                             conversion is not supported.
+ */
+psa_status_t mbedtls_ssl_cipher_to_psa(mbedtls_cipher_type_t mbedtls_cipher_type,
+                                       size_t taglen,
+                                       psa_algorithm_t *alg,
+                                       psa_key_type_t *key_type,
+                                       size_t *key_size);
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+/**
+ * \brief       Convert given PSA status to mbedtls error code.
+ *
+ * \param  status      [in] given PSA status
+ *
+ * \return             corresponding mbedtls error code
+ */
+static inline MBEDTLS_DEPRECATED int psa_ssl_status_to_mbedtls(psa_status_t status)
+{
+    switch (status) {
+        case PSA_SUCCESS:
+            return 0;
+        case PSA_ERROR_INSUFFICIENT_MEMORY:
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        case PSA_ERROR_NOT_SUPPORTED:
+            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+        case PSA_ERROR_INVALID_SIGNATURE:
+            return MBEDTLS_ERR_SSL_INVALID_MAC;
+        case PSA_ERROR_INVALID_ARGUMENT:
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        case PSA_ERROR_BAD_STATE:
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        case PSA_ERROR_BUFFER_TOO_SMALL:
+            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+        default:
+            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+    }
+}
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+#endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
+    defined(MBEDTLS_USE_PSA_CRYPTO)
+
+typedef enum {
+    MBEDTLS_ECJPAKE_ROUND_ONE,
+    MBEDTLS_ECJPAKE_ROUND_TWO
+} mbedtls_ecjpake_rounds_t;
+
+/**
+ * \brief       Parse the provided input buffer for getting the first round
+ *              of key exchange. This code is common between server and client
+ *
+ * \param  pake_ctx [in] the PAKE's operation/context structure
+ * \param  buf      [in] input buffer to parse
+ * \param  len      [in] length of the input buffer
+ * \param  round    [in] either MBEDTLS_ECJPAKE_ROUND_ONE or
+ *                       MBEDTLS_ECJPAKE_ROUND_TWO
+ *
+ * \return               0 on success or a negative error code in case of failure
+ */
+int mbedtls_psa_ecjpake_read_round(
+    psa_pake_operation_t *pake_ctx,
+    const unsigned char *buf,
+    size_t len, mbedtls_ecjpake_rounds_t round);
+
+/**
+ * \brief       Write the first round of key exchange into the provided output
+ *              buffer. This code is common between server and client
+ *
+ * \param  pake_ctx [in] the PAKE's operation/context structure
+ * \param  buf      [out] the output buffer in which data will be written to
+ * \param  len      [in] length of the output buffer
+ * \param  olen     [out] the length of the data really written on the buffer
+ * \param  round    [in] either MBEDTLS_ECJPAKE_ROUND_ONE or
+ *                       MBEDTLS_ECJPAKE_ROUND_TWO
+ *
+ * \return               0 on success or a negative error code in case of failure
+ */
+int mbedtls_psa_ecjpake_write_round(
+    psa_pake_operation_t *pake_ctx,
+    unsigned char *buf,
+    size_t len, size_t *olen,
+    mbedtls_ecjpake_rounds_t round);
+
+#endif //MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO
+
+/**
+ * \brief       TLS record protection modes
+ */
+typedef enum {
+    MBEDTLS_SSL_MODE_STREAM = 0,
+    MBEDTLS_SSL_MODE_CBC,
+    MBEDTLS_SSL_MODE_CBC_ETM,
+    MBEDTLS_SSL_MODE_AEAD
+} mbedtls_ssl_mode_t;
+
+mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_transform(
+    const mbedtls_ssl_transform *transform);
+
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite(
+    int encrypt_then_mac,
+    const mbedtls_ssl_ciphersuite_t *suite);
+#else
+mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite(
+    const mbedtls_ssl_ciphersuite_t *suite);
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
+
+#if defined(MBEDTLS_ECDH_C)
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_read_public_ecdhe_share(mbedtls_ssl_context *ssl,
+                                              const unsigned char *buf,
+                                              size_t buf_len);
+
+#endif /* MBEDTLS_ECDH_C */
+
+static inline int mbedtls_ssl_tls13_cipher_suite_is_offered(
+    mbedtls_ssl_context *ssl, int cipher_suite)
+{
+    const int *ciphersuite_list = ssl->conf->ciphersuite_list;
+
+    /* Check whether we have offered this ciphersuite */
+    for (size_t i = 0; ciphersuite_list[i] != 0; i++) {
+        if (ciphersuite_list[i] == cipher_suite) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/**
+ * \brief Validate cipher suite against config in SSL context.
+ *
+ * \param ssl              SSL context
+ * \param suite_info       Cipher suite to validate
+ * \param min_tls_version  Minimal TLS version to accept a cipher suite
+ * \param max_tls_version  Maximal TLS version to accept a cipher suite
+ *
+ * \return 0 if valid, negative value otherwise.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_validate_ciphersuite(
+    const mbedtls_ssl_context *ssl,
+    const mbedtls_ssl_ciphersuite_t *suite_info,
+    mbedtls_ssl_protocol_version min_tls_version,
+    mbedtls_ssl_protocol_version max_tls_version);
+
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_parse_server_name_ext(mbedtls_ssl_context *ssl,
+                                      const unsigned char *buf,
+                                      const unsigned char *end);
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+#define MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH (2)
+#define MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN (64)
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_parse_record_size_limit_ext(mbedtls_ssl_context *ssl,
+                                                  const unsigned char *buf,
+                                                  const unsigned char *end);
+#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
+
+#if defined(MBEDTLS_SSL_ALPN)
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_parse_alpn_ext(mbedtls_ssl_context *ssl,
+                               const unsigned char *buf,
+                               const unsigned char *end);
+
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_write_alpn_ext(mbedtls_ssl_context *ssl,
+                               unsigned char *buf,
+                               unsigned char *end,
+                               size_t *out_len);
+#endif /* MBEDTLS_SSL_ALPN */
+
+#if defined(MBEDTLS_TEST_HOOKS)
+int mbedtls_ssl_check_dtls_clihlo_cookie(
+    mbedtls_ssl_context *ssl,
+    const unsigned char *cli_id, size_t cli_id_len,
+    const unsigned char *in, size_t in_len,
+    unsigned char *obuf, size_t buf_len, size_t *olen);
+#endif
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+/**
+ * \brief Given an SSL context and its associated configuration, write the TLS
+ *        1.3 specific Pre-Shared key extension.
+ *
+ * \param[in]   ssl     SSL context
+ * \param[in]   buf     Base address of the buffer where to write the extension
+ * \param[in]   end     End address of the buffer where to write the extension
+ * \param[out]  out_len Length in bytes of the Pre-Shared key extension: data
+ *                      written into the buffer \p buf by this function plus
+ *                      the length of the binders to be written.
+ * \param[out]  binders_len Length of the binders to be written at the end of
+ *                          the extension.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext(
+    mbedtls_ssl_context *ssl,
+    unsigned char *buf, unsigned char *end,
+    size_t *out_len, size_t *binders_len);
+
+/**
+ * \brief Given an SSL context and its associated configuration, write the TLS
+ *        1.3 specific Pre-Shared key extension binders at the end of the
+ *        ClientHello.
+ *
+ * \param[in]   ssl     SSL context
+ * \param[in]   buf     Base address of the buffer where to write the binders
+ * \param[in]   end     End address of the buffer where to write the binders
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext(
+    mbedtls_ssl_context *ssl,
+    unsigned char *buf, unsigned char *end);
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
+    defined(MBEDTLS_SSL_SESSION_TICKETS) && \
+    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \
+    defined(MBEDTLS_SSL_CLI_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_session_set_hostname(mbedtls_ssl_session *session,
+                                     const char *hostname);
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)
+static inline unsigned int mbedtls_ssl_session_get_ticket_flags(
+    mbedtls_ssl_session *session, unsigned int flags)
+{
+    return session->ticket_flags &
+           (flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);
+}
+
+static inline void mbedtls_ssl_session_set_ticket_flags(
+    mbedtls_ssl_session *session, unsigned int flags)
+{
+    session->ticket_flags |= (flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);
+}
+
+static inline void mbedtls_ssl_session_clear_ticket_flags(
+    mbedtls_ssl_session *session, unsigned int flags)
+{
+    session->ticket_flags &= ~(flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);
+}
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */
+
+#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
+int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl);
+#endif
+
+#endif /* ssl_misc.h */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_msg.c b/lib/libmbedtls/mbedtls/library/ssl_msg.c
index e47c538..18c19f9 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_msg.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_msg.c
@@ -18,10 +18,6 @@
  *  limitations under the License.
  */
 /*
- *  The SSL 3.0 specification was drafted by Netscape in 1996,
- *  and became an IETF standard in 1999.
- *
- *  http://wp.netscape.com/eng/ssl3/
  *  http://www.ietf.org/rfc/rfc2246.txt
  *  http://www.ietf.org/rfc/rfc4346.txt
  */
@@ -30,16 +26,10 @@
 
 #if defined(MBEDTLS_SSL_TLS_C)
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free      free
-#endif
 
 #include "mbedtls/ssl.h"
-#include "mbedtls/ssl_internal.h"
+#include "ssl_misc.h"
 #include "mbedtls/debug.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
@@ -58,81 +48,80 @@
 #include "mbedtls/oid.h"
 #endif
 
-static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_ssl_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+#endif
+
+static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl);
 
 /*
  * Start a timer.
  * Passing millisecs = 0 cancels a running timer.
  */
-void mbedtls_ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs )
+void mbedtls_ssl_set_timer(mbedtls_ssl_context *ssl, uint32_t millisecs)
 {
-    if( ssl->f_set_timer == NULL )
+    if (ssl->f_set_timer == NULL) {
         return;
+    }
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "set_timer to %d ms", (int) millisecs ) );
-    ssl->f_set_timer( ssl->p_timer, millisecs / 4, millisecs );
+    MBEDTLS_SSL_DEBUG_MSG(3, ("set_timer to %d ms", (int) millisecs));
+    ssl->f_set_timer(ssl->p_timer, millisecs / 4, millisecs);
 }
 
 /*
  * Return -1 is timer is expired, 0 if it isn't.
  */
-int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_check_timer(mbedtls_ssl_context *ssl)
 {
-    if( ssl->f_get_timer == NULL )
-        return( 0 );
-
-    if( ssl->f_get_timer( ssl->p_timer ) == 2 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "timer expired" ) );
-        return( -1 );
+    if (ssl->f_get_timer == NULL) {
+        return 0;
     }
 
-    return( 0 );
+    if (ssl->f_get_timer(ssl->p_timer) == 2) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("timer expired"));
+        return -1;
+    }
+
+    return 0;
 }
 
-#if defined(MBEDTLS_SSL_RECORD_CHECKING)
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
-                                    unsigned char *buf,
-                                    size_t len,
-                                    mbedtls_record *rec );
+static int ssl_parse_record_header(mbedtls_ssl_context const *ssl,
+                                   unsigned char *buf,
+                                   size_t len,
+                                   mbedtls_record *rec);
 
-int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl,
-                              unsigned char *buf,
-                              size_t buflen )
+int mbedtls_ssl_check_record(mbedtls_ssl_context const *ssl,
+                             unsigned char *buf,
+                             size_t buflen)
 {
     int ret = 0;
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "=> mbedtls_ssl_check_record" ) );
-    MBEDTLS_SSL_DEBUG_BUF( 3, "record buffer", buf, buflen );
+    MBEDTLS_SSL_DEBUG_MSG(1, ("=> mbedtls_ssl_check_record"));
+    MBEDTLS_SSL_DEBUG_BUF(3, "record buffer", buf, buflen);
 
     /* We don't support record checking in TLS because
-     * (a) there doesn't seem to be a usecase for it, and
-     * (b) In SSLv3 and TLS 1.0, CBC record decryption has state
-     *     and we'd need to backup the transform here.
+     * there doesn't seem to be a usecase for it.
      */
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM )
-    {
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM) {
         ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
         goto exit;
     }
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    else
-    {
+    else {
         mbedtls_record rec;
 
-        ret = ssl_parse_record_header( ssl, buf, buflen, &rec );
-        if( ret != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 3, "ssl_parse_record_header", ret );
+        ret = ssl_parse_record_header(ssl, buf, buflen, &rec);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(3, "ssl_parse_record_header", ret);
             goto exit;
         }
 
-        if( ssl->transform_in != NULL )
-        {
-            ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in, &rec );
-            if( ret != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_RET( 3, "mbedtls_ssl_decrypt_buf", ret );
+        if (ssl->transform_in != NULL) {
+            ret = mbedtls_ssl_decrypt_buf(ssl, ssl->transform_in, &rec);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(3, "mbedtls_ssl_decrypt_buf", ret);
                 goto exit;
             }
         }
@@ -142,20 +131,18 @@
 exit:
     /* On success, we have decrypted the buffer in-place, so make
      * sure we don't leak any plaintext data. */
-    mbedtls_platform_zeroize( buf, buflen );
+    mbedtls_platform_zeroize(buf, buflen);
 
     /* For the purpose of this API, treat messages with unexpected CID
      * as well as such from future epochs as unexpected. */
-    if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID ||
-        ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
-    {
+    if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID ||
+        ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE) {
         ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "<= mbedtls_ssl_check_record" ) );
-    return( ret );
+    MBEDTLS_SSL_DEBUG_MSG(1, ("<= mbedtls_ssl_check_record"));
+    return ret;
 }
-#endif /* MBEDTLS_SSL_RECORD_CHECKING */
 
 #define SSL_DONT_FORCE_FLUSH 0
 #define SSL_FORCE_FLUSH      1
@@ -163,65 +150,66 @@
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
 
 /* Forward declarations for functions related to message buffering. */
-static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
-                                     uint8_t slot );
-static void ssl_free_buffered_record( mbedtls_ssl_context *ssl );
+static void ssl_buffering_free_slot(mbedtls_ssl_context *ssl,
+                                    uint8_t slot);
+static void ssl_free_buffered_record(mbedtls_ssl_context *ssl);
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_load_buffered_message( mbedtls_ssl_context *ssl );
+static int ssl_load_buffered_message(mbedtls_ssl_context *ssl);
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_load_buffered_record( mbedtls_ssl_context *ssl );
+static int ssl_load_buffered_record(mbedtls_ssl_context *ssl);
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_buffer_message( mbedtls_ssl_context *ssl );
+static int ssl_buffer_message(mbedtls_ssl_context *ssl);
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
-                                     mbedtls_record const *rec );
+static int ssl_buffer_future_record(mbedtls_ssl_context *ssl,
+                                    mbedtls_record const *rec);
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl );
+static int ssl_next_record_is_in_datagram(mbedtls_ssl_context *ssl);
 
-static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl )
+static size_t ssl_get_maximum_datagram_size(mbedtls_ssl_context const *ssl)
 {
-    size_t mtu = mbedtls_ssl_get_current_mtu( ssl );
+    size_t mtu = mbedtls_ssl_get_current_mtu(ssl);
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
     size_t out_buf_len = ssl->out_buf_len;
 #else
     size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
 #endif
 
-    if( mtu != 0 && mtu < out_buf_len )
-        return( mtu );
+    if (mtu != 0 && mtu < out_buf_len) {
+        return mtu;
+    }
 
-    return( out_buf_len );
+    return out_buf_len;
 }
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl )
+static int ssl_get_remaining_space_in_datagram(mbedtls_ssl_context const *ssl)
 {
     size_t const bytes_written = ssl->out_left;
-    size_t const mtu           = ssl_get_maximum_datagram_size( ssl );
+    size_t const mtu           = ssl_get_maximum_datagram_size(ssl);
 
     /* Double-check that the write-index hasn't gone
      * past what we can transmit in a single datagram. */
-    if( bytes_written > mtu )
-    {
+    if (bytes_written > mtu) {
         /* Should never happen... */
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    return( (int) ( mtu - bytes_written ) );
+    return (int) (mtu - bytes_written);
 }
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl )
+static int ssl_get_remaining_payload_in_datagram(mbedtls_ssl_context const *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t remaining, expansion;
     size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
 
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-    const size_t mfl = mbedtls_ssl_get_output_max_frag_len( ssl );
+    const size_t mfl = mbedtls_ssl_get_output_max_frag_len(ssl);
 
-    if( max_len > mfl )
+    if (max_len > mfl) {
         max_len = mfl;
+    }
 
     /* By the standard (RFC 6066 Sect. 4), the MFL extension
      * only limits the maximum record payload size, so in theory
@@ -232,30 +220,35 @@
      * The following reduction of max_len makes sure that we never
      * write datagrams larger than MFL + Record Expansion Overhead.
      */
-    if( max_len <= ssl->out_left )
-        return( 0 );
+    if (max_len <= ssl->out_left) {
+        return 0;
+    }
 
     max_len -= ssl->out_left;
 #endif
 
-    ret = ssl_get_remaining_space_in_datagram( ssl );
-    if( ret < 0 )
-        return( ret );
+    ret = ssl_get_remaining_space_in_datagram(ssl);
+    if (ret < 0) {
+        return ret;
+    }
     remaining = (size_t) ret;
 
-    ret = mbedtls_ssl_get_record_expansion( ssl );
-    if( ret < 0 )
-        return( ret );
+    ret = mbedtls_ssl_get_record_expansion(ssl);
+    if (ret < 0) {
+        return ret;
+    }
     expansion = (size_t) ret;
 
-    if( remaining <= expansion )
-        return( 0 );
+    if (remaining <= expansion) {
+        return 0;
+    }
 
     remaining -= expansion;
-    if( remaining >= max_len )
+    if (remaining >= max_len) {
         remaining = max_len;
+    }
 
-    return( (int) remaining );
+    return (int) remaining;
 }
 
 /*
@@ -263,12 +256,13 @@
  * returning -1 if the maximum value has already been reached.
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl )
+static int ssl_double_retransmit_timeout(mbedtls_ssl_context *ssl)
 {
     uint32_t new_timeout;
 
-    if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max )
-        return( -1 );
+    if (ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max) {
+        return -1;
+    }
 
     /* Implement the final paragraph of RFC 6347 section 4.1.1.1
      * in the following way: after the initial transmission and a first
@@ -276,62 +270,44 @@
      * This value is guaranteed to be deliverable (if not guaranteed to be
      * delivered) of any compliant IPv4 (and IPv6) network, and should work
      * on most non-IP stacks too. */
-    if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min )
-    {
+    if (ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min) {
         ssl->handshake->mtu = 508;
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) );
+        MBEDTLS_SSL_DEBUG_MSG(2, ("mtu autoreduction to %d bytes", ssl->handshake->mtu));
     }
 
     new_timeout = 2 * ssl->handshake->retransmit_timeout;
 
     /* Avoid arithmetic overflow and range overflow */
-    if( new_timeout < ssl->handshake->retransmit_timeout ||
-        new_timeout > ssl->conf->hs_timeout_max )
-    {
+    if (new_timeout < ssl->handshake->retransmit_timeout ||
+        new_timeout > ssl->conf->hs_timeout_max) {
         new_timeout = ssl->conf->hs_timeout_max;
     }
 
     ssl->handshake->retransmit_timeout = new_timeout;
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %lu millisecs",
-                        (unsigned long) ssl->handshake->retransmit_timeout ) );
+    MBEDTLS_SSL_DEBUG_MSG(3, ("update timeout value to %lu millisecs",
+                              (unsigned long) ssl->handshake->retransmit_timeout));
 
-    return( 0 );
+    return 0;
 }
 
-static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl )
+static void ssl_reset_retransmit_timeout(mbedtls_ssl_context *ssl)
 {
     ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min;
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %lu millisecs",
-                        (unsigned long) ssl->handshake->retransmit_timeout ) );
+    MBEDTLS_SSL_DEBUG_MSG(3, ("update timeout value to %lu millisecs",
+                              (unsigned long) ssl->handshake->retransmit_timeout));
 }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
-int (*mbedtls_ssl_hw_record_init)( mbedtls_ssl_context *ssl,
-                     const unsigned char *key_enc, const unsigned char *key_dec,
-                     size_t keylen,
-                     const unsigned char *iv_enc,  const unsigned char *iv_dec,
-                     size_t ivlen,
-                     const unsigned char *mac_enc, const unsigned char *mac_dec,
-                     size_t maclen ) = NULL;
-int (*mbedtls_ssl_hw_record_activate)( mbedtls_ssl_context *ssl, int direction) = NULL;
-int (*mbedtls_ssl_hw_record_reset)( mbedtls_ssl_context *ssl ) = NULL;
-int (*mbedtls_ssl_hw_record_write)( mbedtls_ssl_context *ssl ) = NULL;
-int (*mbedtls_ssl_hw_record_read)( mbedtls_ssl_context *ssl ) = NULL;
-int (*mbedtls_ssl_hw_record_finish)( mbedtls_ssl_context *ssl ) = NULL;
-#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
-
 /*
  * Encryption/decryption functions
  */
 
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ||  \
-    defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
 
-static size_t ssl_compute_padding_length( size_t len,
-                                          size_t granularity )
+static size_t ssl_compute_padding_length(size_t len,
+                                         size_t granularity)
 {
-    return( ( granularity - ( len + 1 ) % granularity ) % granularity );
+    return (granularity - (len + 1) % granularity) % granularity;
 }
 
 /* This functions transforms a (D)TLS plaintext fragment and a record content
@@ -363,201 +339,304 @@
  *    for the expansion.
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_build_inner_plaintext( unsigned char *content,
-                                      size_t *content_size,
-                                      size_t remaining,
-                                      uint8_t rec_type,
-                                      size_t pad )
+static int ssl_build_inner_plaintext(unsigned char *content,
+                                     size_t *content_size,
+                                     size_t remaining,
+                                     uint8_t rec_type,
+                                     size_t pad)
 {
     size_t len = *content_size;
 
     /* Write real content type */
-    if( remaining == 0 )
-        return( -1 );
-    content[ len ] = rec_type;
+    if (remaining == 0) {
+        return -1;
+    }
+    content[len] = rec_type;
     len++;
     remaining--;
 
-    if( remaining < pad )
-        return( -1 );
-    memset( content + len, 0, pad );
+    if (remaining < pad) {
+        return -1;
+    }
+    memset(content + len, 0, pad);
     len += pad;
     remaining -= pad;
 
     *content_size = len;
-    return( 0 );
+    return 0;
 }
 
 /* This function parses a (D)TLSInnerPlaintext structure.
  * See ssl_build_inner_plaintext() for details. */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_inner_plaintext( unsigned char const *content,
-                                          size_t *content_size,
-                                          uint8_t *rec_type )
+static int ssl_parse_inner_plaintext(unsigned char const *content,
+                                     size_t *content_size,
+                                     uint8_t *rec_type)
 {
     size_t remaining = *content_size;
 
     /* Determine length of padding by skipping zeroes from the back. */
-    do
-    {
-        if( remaining == 0 )
-            return( -1 );
+    do {
+        if (remaining == 0) {
+            return -1;
+        }
         remaining--;
-    } while( content[ remaining ] == 0 );
+    } while (content[remaining] == 0);
 
     *content_size = remaining;
-    *rec_type = content[ remaining ];
+    *rec_type = content[remaining];
 
-    return( 0 );
+    return 0;
 }
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID ||
-          MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID || MBEDTLS_SSL_PROTO_TLS1_3 */
 
-/* `add_data` must have size 13 Bytes if the CID extension is disabled,
- * and 13 + 1 + CID-length Bytes if the CID extension is enabled. */
-static void ssl_extract_add_data_from_record( unsigned char* add_data,
-                                              size_t *add_data_len,
-                                              mbedtls_record *rec,
-                                              unsigned minor_ver )
+/* The size of the `add_data` structure depends on various
+ * factors, namely
+ *
+ * 1) CID functionality disabled
+ *
+ * additional_data =
+ *    8:                    seq_num +
+ *    1:                       type +
+ *    2:                    version +
+ *    2:  length of inner plaintext +
+ *
+ * size = 13 bytes
+ *
+ * 2) CID functionality based on RFC 9146 enabled
+ *
+ * size = 8 + 1 + 1 + 1 + 2 + 2 + 6 + 2 + CID-length
+ *      = 23 + CID-length
+ *
+ * 3) CID functionality based on legacy CID version
+    according to draft-ietf-tls-dtls-connection-id-05
+ *  https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05
+ *
+ * size = 13 + 1 + CID-length
+ *
+ * More information about the CID usage:
+ *
+ * Per Section 5.3 of draft-ietf-tls-dtls-connection-id-05 the
+ * size of the additional data structure is calculated as:
+ *
+ * additional_data =
+ *    8:                    seq_num +
+ *    1:                  tls12_cid +
+ *    2:     DTLSCipherText.version +
+ *    n:                        cid +
+ *    1:                 cid_length +
+ *    2: length_of_DTLSInnerPlaintext
+ *
+ * Per RFC 9146 the size of the add_data structure is calculated as:
+ *
+ * additional_data =
+ *    8:        seq_num_placeholder +
+ *    1:                  tls12_cid +
+ *    1:                 cid_length +
+ *    1:                  tls12_cid +
+ *    2:     DTLSCiphertext.version +
+ *    2:                      epoch +
+ *    6:            sequence_number +
+ *    n:                        cid +
+ *    2: length_of_DTLSInnerPlaintext
+ *
+ */
+static void ssl_extract_add_data_from_record(unsigned char *add_data,
+                                             size_t *add_data_len,
+                                             mbedtls_record *rec,
+                                             mbedtls_ssl_protocol_version
+                                             tls_version,
+                                             size_t taglen)
 {
-    /* Quoting RFC 5246 (TLS 1.2):
+    /* Several types of ciphers have been defined for use with TLS and DTLS,
+     * and the MAC calculations for those ciphers differ slightly. Further
+     * variants were added when the CID functionality was added with RFC 9146.
+     * This implementations also considers the use of a legacy version of the
+     * CID specification published in draft-ietf-tls-dtls-connection-id-05,
+     * which is used in deployments.
+     *
+     * We will distinguish between the non-CID and the CID cases below.
+     *
+     * --- Non-CID cases ---
+     *
+     * Quoting RFC 5246 (TLS 1.2):
      *
      *    additional_data = seq_num + TLSCompressed.type +
      *                      TLSCompressed.version + TLSCompressed.length;
      *
-     * For the CID extension, this is extended as follows
-     * (quoting draft-ietf-tls-dtls-connection-id-05,
-     *  https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05):
-     *
-     *       additional_data = seq_num + DTLSPlaintext.type +
-     *                         DTLSPlaintext.version +
-     *                         cid +
-     *                         cid_length +
-     *                         length_of_DTLSInnerPlaintext;
-     *
      * For TLS 1.3, the record sequence number is dropped from the AAD
      * and encoded within the nonce of the AEAD operation instead.
+     * Moreover, the additional data involves the length of the TLS
+     * ciphertext, not the TLS plaintext as in earlier versions.
+     * Quoting RFC 8446 (TLS 1.3):
+     *
+     *      additional_data = TLSCiphertext.opaque_type ||
+     *                        TLSCiphertext.legacy_record_version ||
+     *                        TLSCiphertext.length
+     *
+     * We pass the tag length to this function in order to compute the
+     * ciphertext length from the inner plaintext length rec->data_len via
+     *
+     *     TLSCiphertext.length = TLSInnerPlaintext.length + taglen.
+     *
+     * --- CID cases ---
+     *
+     * RFC 9146 uses a common pattern when constructing the data
+     * passed into a MAC / AEAD cipher.
+     *
+     * Data concatenation for MACs used with block ciphers with
+     * Encrypt-then-MAC Processing (with CID):
+     *
+     *  data = seq_num_placeholder +
+     *         tls12_cid +
+     *         cid_length +
+     *         tls12_cid +
+     *         DTLSCiphertext.version +
+     *         epoch +
+     *         sequence_number +
+     *         cid +
+     *         DTLSCiphertext.length +
+     *         IV +
+     *         ENC(content + padding + padding_length)
+     *
+     * Data concatenation for MACs used with block ciphers (with CID):
+     *
+     *  data =  seq_num_placeholder +
+     *          tls12_cid +
+     *          cid_length +
+     *          tls12_cid +
+     *          DTLSCiphertext.version +
+     *          epoch +
+     *          sequence_number +
+     *          cid +
+     *          length_of_DTLSInnerPlaintext +
+     *          DTLSInnerPlaintext.content +
+     *          DTLSInnerPlaintext.real_type +
+     *          DTLSInnerPlaintext.zeros
+     *
+     * AEAD ciphers use the following additional data calculation (with CIDs):
+     *
+     *     additional_data = seq_num_placeholder +
+     *                tls12_cid +
+     *                cid_length +
+     *                tls12_cid +
+     *                DTLSCiphertext.version +
+     *                epoch +
+     *                sequence_number +
+     *                cid +
+     *                length_of_DTLSInnerPlaintext
+     *
+     * Section 5.3 of draft-ietf-tls-dtls-connection-id-05 (for legacy CID use)
+     * defines the additional data calculation as follows:
+     *
+     *     additional_data = seq_num +
+     *                tls12_cid +
+     *                DTLSCipherText.version +
+     *                cid +
+     *                cid_length +
+     *                length_of_DTLSInnerPlaintext
      */
 
     unsigned char *cur = add_data;
+    size_t ad_len_field = rec->data_len;
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
-    if( minor_ver != MBEDTLS_SSL_MINOR_VERSION_4 )
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
+    MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0
+    const unsigned char seq_num_placeholder[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
+        /* In TLS 1.3, the AAD contains the length of the TLSCiphertext,
+         * which differs from the length of the TLSInnerPlaintext
+         * by the length of the authentication tag. */
+        ad_len_field += taglen;
+    } else
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
     {
-        ((void) minor_ver);
-        memcpy( cur, rec->ctr, sizeof( rec->ctr ) );
-        cur += sizeof( rec->ctr );
+        ((void) tls_version);
+        ((void) taglen);
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
+        MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0
+        if (rec->cid_len != 0) {
+            // seq_num_placeholder
+            memcpy(cur, seq_num_placeholder, sizeof(seq_num_placeholder));
+            cur += sizeof(seq_num_placeholder);
+
+            // tls12_cid type
+            *cur = rec->type;
+            cur++;
+
+            // cid_length
+            *cur = rec->cid_len;
+            cur++;
+        } else
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+        {
+            // epoch + sequence number
+            memcpy(cur, rec->ctr, sizeof(rec->ctr));
+            cur += sizeof(rec->ctr);
+        }
     }
 
+    // type
     *cur = rec->type;
     cur++;
 
-    memcpy( cur, rec->ver, sizeof( rec->ver ) );
-    cur += sizeof( rec->ver );
+    // version
+    memcpy(cur, rec->ver, sizeof(rec->ver));
+    cur += sizeof(rec->ver);
 
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    if( rec->cid_len != 0 )
-    {
-        memcpy( cur, rec->cid, rec->cid_len );
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
+    MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 1
+
+    if (rec->cid_len != 0) {
+        // CID
+        memcpy(cur, rec->cid, rec->cid_len);
         cur += rec->cid_len;
 
+        // cid_length
         *cur = rec->cid_len;
         cur++;
 
-        MBEDTLS_PUT_UINT16_BE( rec->data_len, cur, 0 );
+        // length of inner plaintext
+        MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0);
         cur += 2;
-    }
-    else
+    } else
+#elif defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
+    MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0
+
+    if (rec->cid_len != 0) {
+        // epoch + sequence number
+        memcpy(cur, rec->ctr, sizeof(rec->ctr));
+        cur += sizeof(rec->ctr);
+
+        // CID
+        memcpy(cur, rec->cid, rec->cid_len);
+        cur += rec->cid_len;
+
+        // length of inner plaintext
+        MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0);
+        cur += 2;
+    } else
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
     {
-        MBEDTLS_PUT_UINT16_BE( rec->data_len, cur, 0 );
+        MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0);
         cur += 2;
     }
 
     *add_data_len = cur - add_data;
 }
 
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-
-#define SSL3_MAC_MAX_BYTES   20  /* MD-5 or SHA-1 */
-
-/*
- * SSLv3.0 MAC functions
- */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_mac( mbedtls_md_context_t *md_ctx,
-                    const unsigned char *secret,
-                    const unsigned char *buf, size_t len,
-                    const unsigned char *ctr, int type,
-                    unsigned char out[SSL3_MAC_MAX_BYTES] )
-{
-    unsigned char header[11];
-    unsigned char padding[48];
-    int padlen;
-    int md_size = mbedtls_md_get_size( md_ctx->md_info );
-    int md_type = mbedtls_md_get_type( md_ctx->md_info );
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    /* Only MD5 and SHA-1 supported */
-    if( md_type == MBEDTLS_MD_MD5 )
-        padlen = 48;
-    else
-        padlen = 40;
-
-    memcpy( header, ctr, 8 );
-    header[8] = (unsigned char)  type;
-    MBEDTLS_PUT_UINT16_BE( len, header, 9);
-
-    memset( padding, 0x36, padlen );
-    ret = mbedtls_md_starts( md_ctx );
-    if( ret != 0 )
-        return( ret );
-    ret = mbedtls_md_update( md_ctx, secret,  md_size );
-    if( ret != 0 )
-        return( ret );
-    ret = mbedtls_md_update( md_ctx, padding, padlen  );
-    if( ret != 0 )
-        return( ret );
-    ret = mbedtls_md_update( md_ctx, header,  11      );
-    if( ret != 0 )
-        return( ret );
-    ret = mbedtls_md_update( md_ctx, buf,     len     );
-    if( ret != 0 )
-        return( ret );
-    ret = mbedtls_md_finish( md_ctx, out              );
-    if( ret != 0 )
-        return( ret );
-
-    memset( padding, 0x5C, padlen );
-    ret = mbedtls_md_starts( md_ctx );
-    if( ret != 0 )
-        return( ret );
-    ret = mbedtls_md_update( md_ctx, secret,    md_size );
-    if( ret != 0 )
-        return( ret );
-    ret = mbedtls_md_update( md_ctx, padding,   padlen  );
-    if( ret != 0 )
-        return( ret );
-    ret = mbedtls_md_update( md_ctx, out,       md_size );
-    if( ret != 0 )
-        return( ret );
-    ret = mbedtls_md_finish( md_ctx, out                );
-    if( ret != 0 )
-        return( ret );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-
 #if defined(MBEDTLS_GCM_C) || \
     defined(MBEDTLS_CCM_C) || \
     defined(MBEDTLS_CHACHAPOLY_C)
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_transform_aead_dynamic_iv_is_explicit(
-                                mbedtls_ssl_transform const *transform )
+    mbedtls_ssl_transform const *transform)
 {
-    return( transform->ivlen != transform->fixed_ivlen );
+    return transform->ivlen != transform->fixed_ivlen;
 }
 
 /* Compute IV := ( fixed_iv || 0 ) XOR ( 0 || dynamic_IV )
@@ -583,35 +662,39 @@
  * which has to be ensured by the caller. If this precondition
  * violated, the behavior of this function is undefined.
  */
-static void ssl_build_record_nonce( unsigned char *dst_iv,
-                                    size_t dst_iv_len,
-                                    unsigned char const *fixed_iv,
-                                    size_t fixed_iv_len,
-                                    unsigned char const *dynamic_iv,
-                                    size_t dynamic_iv_len )
+static void ssl_build_record_nonce(unsigned char *dst_iv,
+                                   size_t dst_iv_len,
+                                   unsigned char const *fixed_iv,
+                                   size_t fixed_iv_len,
+                                   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 );
+    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 */
 
-int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
-                             mbedtls_ssl_transform *transform,
-                             mbedtls_record *rec,
-                             int (*f_rng)(void *, unsigned char *, size_t),
-                             void *p_rng )
+int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl,
+                            mbedtls_ssl_transform *transform,
+                            mbedtls_record *rec,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng)
 {
-    mbedtls_cipher_mode_t mode;
+    mbedtls_ssl_mode_t ssl_mode;
     int auth_done = 0;
-    unsigned char * data;
-    unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_OUT_LEN_MAX ];
+    unsigned char *data;
+    /* For an explanation of the additional data length see
+     * the description of ssl_extract_add_data_from_record().
+     */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    unsigned char add_data[23 + MBEDTLS_SSL_CID_OUT_LEN_MAX];
+#else
+    unsigned char add_data[13];
+#endif
     size_t add_data_len;
     size_t post_avail;
 
@@ -622,47 +705,44 @@
 #endif
 
     /* The PRNG is used for dynamic IV generation that's used
-     * for CBC transformations in TLS 1.1 and TLS 1.2. */
-#if !( defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \
-       ( defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) ) )
+     * for CBC transformations in TLS 1.2. */
+#if !(defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \
+    defined(MBEDTLS_SSL_PROTO_TLS1_2))
     ((void) f_rng);
     ((void) p_rng);
 #endif
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> encrypt buf"));
 
-    if( transform == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "no transform provided to encrypt_buf" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    if (transform == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("no transform provided to encrypt_buf"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
-    if( rec == NULL
+    if (rec == NULL
         || rec->buf == NULL
         || rec->buf_len < rec->data_offset
         || rec->buf_len - rec->data_offset < rec->data_len
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
         || rec->cid_len != 0
 #endif
-        )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to encrypt_buf" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        ) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad record structure provided to encrypt_buf"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
+    ssl_mode = mbedtls_ssl_get_mode_from_transform(transform);
+
     data = rec->buf + rec->data_offset;
-    post_avail = rec->buf_len - ( rec->data_len + rec->data_offset );
-    MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload",
-                           data, rec->data_len );
+    post_avail = rec->buf_len - (rec->data_len + rec->data_offset);
+    MBEDTLS_SSL_DEBUG_BUF(4, "before encrypt: output payload",
+                          data, rec->data_len);
 
-    mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc );
-
-    if( rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %" MBEDTLS_PRINTF_SIZET
-                                    " too large, maximum %" MBEDTLS_PRINTF_SIZET,
-                                    rec->data_len,
-                                    (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Record content %" MBEDTLS_PRINTF_SIZET
+                                  " too large, maximum %" MBEDTLS_PRINTF_SIZET,
+                                  rec->data_len,
+                                  (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
     /* The following two code paths implement the (D)TLSInnerPlaintext
@@ -677,38 +757,35 @@
      * since they apply to different versions of the protocol. There
      * is hence no risk of double-addition of the inner plaintext.
      */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
-    if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 )
-    {
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    if (transform->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
         size_t padding =
-            ssl_compute_padding_length( rec->data_len,
-                                        MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY );
-        if( ssl_build_inner_plaintext( data,
-                                       &rec->data_len,
-                                       post_avail,
-                                       rec->type,
-                                       padding ) != 0 )
-        {
-            return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+            ssl_compute_padding_length(rec->data_len,
+                                       MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY);
+        if (ssl_build_inner_plaintext(data,
+                                      &rec->data_len,
+                                      post_avail,
+                                      rec->type,
+                                      padding) != 0) {
+            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
         }
 
         rec->type = MBEDTLS_SSL_MSG_APPLICATION_DATA;
     }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
     /*
      * Add CID information
      */
     rec->cid_len = transform->out_cid_len;
-    memcpy( rec->cid, transform->out_cid, transform->out_cid_len );
-    MBEDTLS_SSL_DEBUG_BUF( 3, "CID", rec->cid, rec->cid_len );
+    memcpy(rec->cid, transform->out_cid, transform->out_cid_len);
+    MBEDTLS_SSL_DEBUG_BUF(3, "CID", rec->cid, rec->cid_len);
 
-    if( rec->cid_len != 0 )
-    {
+    if (rec->cid_len != 0) {
         size_t padding =
-            ssl_compute_padding_length( rec->data_len,
-                                        MBEDTLS_SSL_CID_PADDING_GRANULARITY );
+            ssl_compute_padding_length(rec->data_len,
+                                       MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY);
         /*
          * Wrap plaintext into DTLSInnerPlaintext structure.
          * See ssl_build_inner_plaintext() for more information.
@@ -716,156 +793,143 @@
          * Note that this changes `rec->data_len`, and hence
          * `post_avail` needs to be recalculated afterwards.
          */
-        if( ssl_build_inner_plaintext( data,
-                        &rec->data_len,
-                        post_avail,
-                        rec->type,
-                        padding ) != 0 )
-        {
-            return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+        if (ssl_build_inner_plaintext(data,
+                                      &rec->data_len,
+                                      post_avail,
+                                      rec->type,
+                                      padding) != 0) {
+            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
         }
 
         rec->type = MBEDTLS_SSL_MSG_CID;
     }
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
-    post_avail = rec->buf_len - ( rec->data_len + rec->data_offset );
+    post_avail = rec->buf_len - (rec->data_len + rec->data_offset);
 
     /*
      * Add MAC before if needed
      */
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
-    if( mode == MBEDTLS_MODE_STREAM ||
-        ( mode == MBEDTLS_MODE_CBC
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-          && transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
+    if (ssl_mode == MBEDTLS_SSL_MODE_STREAM ||
+        ssl_mode == MBEDTLS_SSL_MODE_CBC) {
+        if (post_avail < transform->maclen) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough"));
+            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+        }
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        unsigned char mac[MBEDTLS_SSL_MAC_ADD];
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+        size_t sign_mac_length = 0;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+        ssl_extract_add_data_from_record(add_data, &add_data_len, rec,
+                                         transform->tls_version,
+                                         transform->taglen);
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        status = psa_mac_sign_setup(&operation, transform->psa_mac_enc,
+                                    transform->psa_mac_alg);
+        if (status != PSA_SUCCESS) {
+            goto hmac_failed_etm_disabled;
+        }
+
+        status = psa_mac_update(&operation, add_data, add_data_len);
+        if (status != PSA_SUCCESS) {
+            goto hmac_failed_etm_disabled;
+        }
+
+        status = psa_mac_update(&operation, data, rec->data_len);
+        if (status != PSA_SUCCESS) {
+            goto hmac_failed_etm_disabled;
+        }
+
+        status = psa_mac_sign_finish(&operation, mac, MBEDTLS_SSL_MAC_ADD,
+                                     &sign_mac_length);
+        if (status != PSA_SUCCESS) {
+            goto hmac_failed_etm_disabled;
+        }
+#else
+        ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, add_data,
+                                     add_data_len);
+        if (ret != 0) {
+            goto hmac_failed_etm_disabled;
+        }
+        ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, data, rec->data_len);
+        if (ret != 0) {
+            goto hmac_failed_etm_disabled;
+        }
+        ret = mbedtls_md_hmac_finish(&transform->md_ctx_enc, mac);
+        if (ret != 0) {
+            goto hmac_failed_etm_disabled;
+        }
+        ret = mbedtls_md_hmac_reset(&transform->md_ctx_enc);
+        if (ret != 0) {
+            goto hmac_failed_etm_disabled;
+        }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+        memcpy(data + rec->data_len, mac, transform->maclen);
 #endif
-        ) )
-    {
-        if( post_avail < transform->maclen )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
-            return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
-        }
 
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-        if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
-        {
-            unsigned char mac[SSL3_MAC_MAX_BYTES];
-            int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-            ret = ssl_mac( &transform->md_ctx_enc, transform->mac_enc,
-                           data, rec->data_len, rec->ctr, rec->type, mac );
-            if( ret == 0 )
-                memcpy( data + rec->data_len, mac, transform->maclen );
-            mbedtls_platform_zeroize( mac, transform->maclen );
-            if( ret != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_RET( 1, "ssl_mac", ret );
-                return( ret );
-            }
-        }
-        else
-#endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
-        defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 )
-        {
-            unsigned char mac[MBEDTLS_SSL_MAC_ADD];
-            int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-            ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
-                                              transform->minor_ver );
-
-            ret = mbedtls_md_hmac_update( &transform->md_ctx_enc,
-                                          add_data, add_data_len );
-            if( ret != 0 )
-                goto hmac_failed_etm_disabled;
-            ret = mbedtls_md_hmac_update( &transform->md_ctx_enc,
-                                          data, rec->data_len );
-            if( ret != 0 )
-                goto hmac_failed_etm_disabled;
-            ret = mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac );
-            if( ret != 0 )
-                goto hmac_failed_etm_disabled;
-            ret = mbedtls_md_hmac_reset( &transform->md_ctx_enc );
-            if( ret != 0 )
-                goto hmac_failed_etm_disabled;
-
-            memcpy( data + rec->data_len, mac, transform->maclen );
-
-        hmac_failed_etm_disabled:
-            mbedtls_platform_zeroize( mac, transform->maclen );
-            if( ret != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_hmac_xxx", ret );
-                return( ret );
-            }
-        }
-        else
-#endif
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-        }
-
-        MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", data + rec->data_len,
-                               transform->maclen );
+        MBEDTLS_SSL_DEBUG_BUF(4, "computed mac", data + rec->data_len,
+                              transform->maclen);
 
         rec->data_len += transform->maclen;
         post_avail -= transform->maclen;
         auth_done++;
+
+hmac_failed_etm_disabled:
+        mbedtls_platform_zeroize(mac, transform->maclen);
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        status = psa_mac_abort(&operation);
+        if (ret == 0 && status != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+        }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_hmac_xxx", ret);
+            return ret;
+        }
     }
-#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
 
     /*
      * Encrypt
      */
-#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
-    if( mode == MBEDTLS_MODE_STREAM )
-    {
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        size_t olen;
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
-                                    "including %d bytes of padding",
-                                    rec->data_len, 0 ) );
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM)
+    if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
+                                                                                    "including %d bytes of padding",
+                                  rec->data_len, 0));
 
-        if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc,
-                                   transform->iv_enc, transform->ivlen,
-                                   data, rec->data_len,
-                                   data, &olen ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
-            return( ret );
-        }
-
-        if( rec->data_len != olen )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-        }
-    }
-    else
-#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */
+        /* The only supported stream cipher is "NULL",
+         * so there's nothing to do here.*/
+    } else
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_STREAM */
 
 #if defined(MBEDTLS_GCM_C) || \
     defined(MBEDTLS_CCM_C) || \
     defined(MBEDTLS_CHACHAPOLY_C)
-    if( mode == MBEDTLS_MODE_GCM ||
-        mode == MBEDTLS_MODE_CCM ||
-        mode == MBEDTLS_MODE_CHACHAPOLY )
-    {
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) {
         unsigned char iv[12];
         unsigned char *dynamic_iv;
         size_t dynamic_iv_len;
         int dynamic_iv_is_explicit =
-            ssl_transform_aead_dynamic_iv_is_explicit( transform );
+            ssl_transform_aead_dynamic_iv_is_explicit(transform);
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
         /* Check that there's space for the authentication tag. */
-        if( post_avail < transform->taglen )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
-            return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+        if (post_avail < transform->taglen) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough"));
+            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
         }
 
         /*
@@ -881,259 +945,342 @@
          *       record sequence number here in all cases.
          */
         dynamic_iv     = rec->ctr;
-        dynamic_iv_len = sizeof( rec->ctr );
+        dynamic_iv_len = sizeof(rec->ctr);
 
-        ssl_build_record_nonce( iv, sizeof( iv ),
-                                transform->iv_enc,
-                                transform->fixed_ivlen,
-                                dynamic_iv,
-                                dynamic_iv_len );
+        ssl_build_record_nonce(iv, sizeof(iv),
+                               transform->iv_enc,
+                               transform->fixed_ivlen,
+                               dynamic_iv,
+                               dynamic_iv_len);
 
         /*
          * Build additional data for AEAD encryption.
          * This depends on the TLS version.
          */
-        ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
-                                          transform->minor_ver );
+        ssl_extract_add_data_from_record(add_data, &add_data_len, rec,
+                                         transform->tls_version,
+                                         transform->taglen);
 
-        MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)",
-                               iv, transform->ivlen );
-        MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)",
-                               dynamic_iv,
-                               dynamic_iv_is_explicit ? dynamic_iv_len : 0 );
-        MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
-                               add_data, add_data_len );
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
-                                    "including 0 bytes of padding",
-                                    rec->data_len ) );
+        MBEDTLS_SSL_DEBUG_BUF(4, "IV used (internal)",
+                              iv, transform->ivlen);
+        MBEDTLS_SSL_DEBUG_BUF(4, "IV used (transmitted)",
+                              dynamic_iv,
+                              dynamic_iv_is_explicit ? dynamic_iv_len : 0);
+        MBEDTLS_SSL_DEBUG_BUF(4, "additional data used for AEAD",
+                              add_data, add_data_len);
+        MBEDTLS_SSL_DEBUG_MSG(3, ("before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
+                                                                                    "including 0 bytes of padding",
+                                  rec->data_len));
 
         /*
          * Encrypt and authenticate
          */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        status = psa_aead_encrypt(transform->psa_key_enc,
+                                  transform->psa_alg,
+                                  iv, transform->ivlen,
+                                  add_data, add_data_len,
+                                  data, rec->data_len,
+                                  data, rec->buf_len - (data - rec->buf),
+                                  &rec->data_len);
 
-        if( ( ret = mbedtls_cipher_auth_encrypt_ext( &transform->cipher_ctx_enc,
-                   iv, transform->ivlen,
-                   add_data, add_data_len,
-                   data, rec->data_len,                     /* src */
-                   data, rec->buf_len - (data - rec->buf),  /* dst */
-                   &rec->data_len,
-                   transform->taglen ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret );
-            return( ret );
+        if (status != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_encrypt_buf", ret);
+            return ret;
         }
-        MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag",
-                               data + rec->data_len - transform->taglen,
-                               transform->taglen );
+#else
+        if ((ret = mbedtls_cipher_auth_encrypt_ext(&transform->cipher_ctx_enc,
+                                                   iv, transform->ivlen,
+                                                   add_data, add_data_len,
+                                                   data, rec->data_len, /* src */
+                                                   data, rec->buf_len - (data - rec->buf), /* dst */
+                                                   &rec->data_len,
+                                                   transform->taglen)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_auth_encrypt_ext", ret);
+            return ret;
+        }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+        MBEDTLS_SSL_DEBUG_BUF(4, "after encrypt: tag",
+                              data + rec->data_len - transform->taglen,
+                              transform->taglen);
         /* Account for authentication tag. */
         post_avail -= transform->taglen;
 
         /*
          * Prefix record content with dynamic IV in case it is explicit.
          */
-        if( dynamic_iv_is_explicit != 0 )
-        {
-            if( rec->data_offset < dynamic_iv_len )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
-                return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+        if (dynamic_iv_is_explicit != 0) {
+            if (rec->data_offset < dynamic_iv_len) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough"));
+                return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
             }
 
-            memcpy( data - dynamic_iv_len, dynamic_iv, dynamic_iv_len );
+            memcpy(data - dynamic_iv_len, dynamic_iv, dynamic_iv_len);
             rec->data_offset -= dynamic_iv_len;
             rec->data_len    += dynamic_iv_len;
         }
 
         auth_done++;
-    }
-    else
+    } else
 #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */
 #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC)
-    if( mode == MBEDTLS_MODE_CBC )
-    {
+    if (ssl_mode == MBEDTLS_SSL_MODE_CBC ||
+        ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) {
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         size_t padlen, i;
         size_t olen;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+        size_t part_len;
+        psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
         /* Currently we're always using minimal padding
          * (up to 255 bytes would be allowed). */
-        padlen = transform->ivlen - ( rec->data_len + 1 ) % transform->ivlen;
-        if( padlen == transform->ivlen )
+        padlen = transform->ivlen - (rec->data_len + 1) % transform->ivlen;
+        if (padlen == transform->ivlen) {
             padlen = 0;
-
-        /* Check there's enough space in the buffer for the padding. */
-        if( post_avail < padlen + 1 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
-            return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
         }
 
-        for( i = 0; i <= padlen; i++ )
+        /* Check there's enough space in the buffer for the padding. */
+        if (post_avail < padlen + 1) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough"));
+            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+        }
+
+        for (i = 0; i <= padlen; i++) {
             data[rec->data_len + i] = (unsigned char) padlen;
+        }
 
         rec->data_len += padlen + 1;
         post_avail -= padlen + 1;
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
         /*
-         * Prepend per-record IV for block cipher in TLS v1.1 and up as per
+         * Prepend per-record IV for block cipher in TLS v1.2 as per
          * Method 1 (6.2.3.2. in RFC4346 and RFC5246)
          */
-        if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
-        {
-            if( f_rng == NULL )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "No PRNG provided to encrypt_record routine" ) );
-                return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-            }
+        if (f_rng == NULL) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("No PRNG provided to encrypt_record routine"));
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        }
 
-            if( rec->data_offset < transform->ivlen )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
-                return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
-            }
+        if (rec->data_offset < transform->ivlen) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough"));
+            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+        }
 
-            /*
-             * Generate IV
-             */
-            ret = f_rng( p_rng, transform->iv_enc, transform->ivlen );
-            if( ret != 0 )
-                return( ret );
+        /*
+         * Generate IV
+         */
+        ret = f_rng(p_rng, transform->iv_enc, transform->ivlen);
+        if (ret != 0) {
+            return ret;
+        }
 
-            memcpy( data - transform->ivlen, transform->iv_enc,
-                    transform->ivlen );
+        memcpy(data - transform->ivlen, transform->iv_enc, transform->ivlen);
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+        MBEDTLS_SSL_DEBUG_MSG(3, ("before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
+                                                                                    "including %"
+                                  MBEDTLS_PRINTF_SIZET
+                                  " bytes of IV and %" MBEDTLS_PRINTF_SIZET " bytes of padding",
+                                  rec->data_len, transform->ivlen,
+                                  padlen + 1));
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        status = psa_cipher_encrypt_setup(&cipher_op,
+                                          transform->psa_key_enc, transform->psa_alg);
+
+        if (status != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_encrypt_setup", ret);
+            return ret;
+        }
+
+        status = psa_cipher_set_iv(&cipher_op, transform->iv_enc, transform->ivlen);
+
+        if (status != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_set_iv", ret);
+            return ret;
 
         }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
 
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", "
-                            "including %" MBEDTLS_PRINTF_SIZET
-                            " bytes of IV and %" MBEDTLS_PRINTF_SIZET " bytes of padding",
-                            rec->data_len, transform->ivlen,
-                            padlen + 1 ) );
-
-        if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc,
-                                   transform->iv_enc,
-                                   transform->ivlen,
+        status = psa_cipher_update(&cipher_op,
                                    data, rec->data_len,
-                                   data, &olen ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
-            return( ret );
+                                   data, rec->data_len, &olen);
+
+        if (status != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_update", ret);
+            return ret;
+
         }
 
-        if( rec->data_len != olen )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        status = psa_cipher_finish(&cipher_op,
+                                   data + olen, rec->data_len - olen,
+                                   &part_len);
+
+        if (status != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_finish", ret);
+            return ret;
+
         }
 
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1)
-        if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 )
-        {
-            /*
-             * Save IV in SSL3 and TLS1
-             */
-            memcpy( transform->iv_enc, transform->cipher_ctx_enc.iv,
-                    transform->ivlen );
+        olen += part_len;
+#else
+        if ((ret = mbedtls_cipher_crypt(&transform->cipher_ctx_enc,
+                                        transform->iv_enc,
+                                        transform->ivlen,
+                                        data, rec->data_len,
+                                        data, &olen)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_crypt", ret);
+            return ret;
         }
-        else
-#endif
-        {
-            data             -= transform->ivlen;
-            rec->data_offset -= transform->ivlen;
-            rec->data_len    += transform->ivlen;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+        if (rec->data_len != olen) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
         }
 
+        data             -= transform->ivlen;
+        rec->data_offset -= transform->ivlen;
+        rec->data_len    += transform->ivlen;
+
 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-        if( auth_done == 0 )
-        {
+        if (auth_done == 0) {
             unsigned char mac[MBEDTLS_SSL_MAC_ADD];
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+            psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+            size_t sign_mac_length = 0;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-            /*
-             * MAC(MAC_write_key, seq_num +
-             *     TLSCipherText.type +
-             *     TLSCipherText.version +
-             *     length_of( (IV +) ENC(...) ) +
-             *     IV + // except for TLS 1.0
-             *     ENC(content + padding + padding_length));
+            /* MAC(MAC_write_key, add_data, IV, ENC(content + padding + padding_length))
              */
 
-            if( post_avail < transform->maclen)
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
-                return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+            if (post_avail < transform->maclen) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough"));
+                return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
             }
 
-            ssl_extract_add_data_from_record( add_data, &add_data_len,
-                                              rec, transform->minor_ver );
+            ssl_extract_add_data_from_record(add_data, &add_data_len,
+                                             rec, transform->tls_version,
+                                             transform->taglen);
 
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
-            MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data,
-                                   add_data_len );
+            MBEDTLS_SSL_DEBUG_MSG(3, ("using encrypt then mac"));
+            MBEDTLS_SSL_DEBUG_BUF(4, "MAC'd meta-data", add_data,
+                                  add_data_len);
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+            status = psa_mac_sign_setup(&operation, transform->psa_mac_enc,
+                                        transform->psa_mac_alg);
+            if (status != PSA_SUCCESS) {
+                goto hmac_failed_etm_enabled;
+            }
 
-            ret = mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data,
-                                          add_data_len );
-            if( ret != 0 )
+            status = psa_mac_update(&operation, add_data, add_data_len);
+            if (status != PSA_SUCCESS) {
                 goto hmac_failed_etm_enabled;
-            ret = mbedtls_md_hmac_update( &transform->md_ctx_enc,
-                                          data, rec->data_len );
-            if( ret != 0 )
-                goto hmac_failed_etm_enabled;
-            ret = mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac );
-            if( ret != 0 )
-                goto hmac_failed_etm_enabled;
-            ret = mbedtls_md_hmac_reset( &transform->md_ctx_enc );
-            if( ret != 0 )
-                goto hmac_failed_etm_enabled;
+            }
 
-            memcpy( data + rec->data_len, mac, transform->maclen );
+            status = psa_mac_update(&operation, data, rec->data_len);
+            if (status != PSA_SUCCESS) {
+                goto hmac_failed_etm_enabled;
+            }
+
+            status = psa_mac_sign_finish(&operation, mac, MBEDTLS_SSL_MAC_ADD,
+                                         &sign_mac_length);
+            if (status != PSA_SUCCESS) {
+                goto hmac_failed_etm_enabled;
+            }
+#else
+
+            ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, add_data,
+                                         add_data_len);
+            if (ret != 0) {
+                goto hmac_failed_etm_enabled;
+            }
+            ret = mbedtls_md_hmac_update(&transform->md_ctx_enc,
+                                         data, rec->data_len);
+            if (ret != 0) {
+                goto hmac_failed_etm_enabled;
+            }
+            ret = mbedtls_md_hmac_finish(&transform->md_ctx_enc, mac);
+            if (ret != 0) {
+                goto hmac_failed_etm_enabled;
+            }
+            ret = mbedtls_md_hmac_reset(&transform->md_ctx_enc);
+            if (ret != 0) {
+                goto hmac_failed_etm_enabled;
+            }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+            memcpy(data + rec->data_len, mac, transform->maclen);
 
             rec->data_len += transform->maclen;
             post_avail -= transform->maclen;
             auth_done++;
 
-        hmac_failed_etm_enabled:
-            mbedtls_platform_zeroize( mac, transform->maclen );
-            if( ret != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_RET( 1, "HMAC calculation failed", ret );
-                return( ret );
+hmac_failed_etm_enabled:
+            mbedtls_platform_zeroize(mac, transform->maclen);
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            status = psa_mac_abort(&operation);
+            if (ret == 0 && status != PSA_SUCCESS) {
+                ret = PSA_TO_MBEDTLS_ERR(status);
+            }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "HMAC calculation failed", ret);
+                return ret;
             }
         }
 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
-    }
-    else
+    } else
 #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC) */
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
     /* Make extra sure authentication was performed, exactly once */
-    if( auth_done != 1 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    if (auth_done != 1) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= encrypt buf"));
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
-                             mbedtls_ssl_transform *transform,
-                             mbedtls_record *rec )
+int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl,
+                            mbedtls_ssl_transform *transform,
+                            mbedtls_record *rec)
 {
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) || defined(MBEDTLS_CIPHER_MODE_AEAD)
     size_t olen;
-    mbedtls_cipher_mode_t mode;
-    int ret, auth_done = 0;
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC || MBEDTLS_CIPHER_MODE_AEAD */
+    mbedtls_ssl_mode_t ssl_mode;
+    int ret;
+
+    int auth_done = 0;
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
     size_t padlen = 0, correct = 1;
 #endif
-    unsigned char* data;
-    unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_IN_LEN_MAX ];
+    unsigned char *data;
+    /* For an explanation of the additional data length see
+     * the description of ssl_extract_add_data_from_record().
+     */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    unsigned char add_data[23 + MBEDTLS_SSL_CID_IN_LEN_MAX];
+#else
+    unsigned char add_data[13];
+#endif
     size_t add_data_len;
 
 #if !defined(MBEDTLS_DEBUG_C)
@@ -1141,62 +1288,44 @@
     ((void) ssl);
 #endif
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) );
-    if( rec == NULL                     ||
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> decrypt buf"));
+    if (rec == NULL                     ||
         rec->buf == NULL                ||
         rec->buf_len < rec->data_offset ||
-        rec->buf_len - rec->data_offset < rec->data_len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to decrypt_buf" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        rec->buf_len - rec->data_offset < rec->data_len) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad record structure provided to decrypt_buf"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
     data = rec->buf + rec->data_offset;
-    mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_dec );
+    ssl_mode = mbedtls_ssl_get_mode_from_transform(transform);
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
     /*
      * Match record's CID with incoming CID.
      */
-    if( rec->cid_len != transform->in_cid_len ||
-        memcmp( rec->cid, transform->in_cid, rec->cid_len ) != 0 )
-    {
-        return( MBEDTLS_ERR_SSL_UNEXPECTED_CID );
+    if (rec->cid_len != transform->in_cid_len ||
+        memcmp(rec->cid, transform->in_cid, rec->cid_len) != 0) {
+        return MBEDTLS_ERR_SSL_UNEXPECTED_CID;
     }
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
-#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
-    if( mode == MBEDTLS_MODE_STREAM )
-    {
-        padlen = 0;
-        if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec,
-                                   transform->iv_dec,
-                                   transform->ivlen,
-                                   data, rec->data_len,
-                                   data, &olen ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
-            return( ret );
-        }
-
-        if( rec->data_len != olen )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-        }
-    }
-    else
-#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM)
+    if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) {
+        /* The only supported stream cipher is "NULL",
+         * so there's nothing to do here.*/
+    } else
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_STREAM */
 #if defined(MBEDTLS_GCM_C) || \
     defined(MBEDTLS_CCM_C) || \
     defined(MBEDTLS_CHACHAPOLY_C)
-    if( mode == MBEDTLS_MODE_GCM ||
-        mode == MBEDTLS_MODE_CCM ||
-        mode == MBEDTLS_MODE_CHACHAPOLY )
-    {
+    if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) {
         unsigned char iv[12];
         unsigned char *dynamic_iv;
         size_t dynamic_iv_len;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
         /*
          * Extract dynamic part of nonce for AEAD decryption.
@@ -1206,109 +1335,122 @@
          *       can be chosen freely - in particular, it need not
          *       agree with the record sequence number.
          */
-        dynamic_iv_len = sizeof( rec->ctr );
-        if( ssl_transform_aead_dynamic_iv_is_explicit( transform ) == 1 )
-        {
-            if( rec->data_len < dynamic_iv_len )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
-                                            " ) < explicit_iv_len (%" MBEDTLS_PRINTF_SIZET ") ",
-                                            rec->data_len,
-                                            dynamic_iv_len ) );
-                return( MBEDTLS_ERR_SSL_INVALID_MAC );
+        dynamic_iv_len = sizeof(rec->ctr);
+        if (ssl_transform_aead_dynamic_iv_is_explicit(transform) == 1) {
+            if (rec->data_len < dynamic_iv_len) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("msglen (%" MBEDTLS_PRINTF_SIZET
+                                          " ) < explicit_iv_len (%" MBEDTLS_PRINTF_SIZET ") ",
+                                          rec->data_len,
+                                          dynamic_iv_len));
+                return MBEDTLS_ERR_SSL_INVALID_MAC;
             }
             dynamic_iv = data;
 
             data += dynamic_iv_len;
             rec->data_offset += dynamic_iv_len;
             rec->data_len    -= dynamic_iv_len;
-        }
-        else
-        {
+        } else {
             dynamic_iv = rec->ctr;
         }
 
         /* Check that there's space for the authentication tag. */
-        if( rec->data_len < transform->taglen )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
-                                        ") < taglen (%" MBEDTLS_PRINTF_SIZET ") ",
-                                        rec->data_len,
-                                        transform->taglen ) );
-            return( MBEDTLS_ERR_SSL_INVALID_MAC );
+        if (rec->data_len < transform->taglen) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("msglen (%" MBEDTLS_PRINTF_SIZET
+                                      ") < taglen (%" MBEDTLS_PRINTF_SIZET ") ",
+                                      rec->data_len,
+                                      transform->taglen));
+            return MBEDTLS_ERR_SSL_INVALID_MAC;
         }
         rec->data_len -= transform->taglen;
 
         /*
          * Prepare nonce from dynamic and static parts.
          */
-        ssl_build_record_nonce( iv, sizeof( iv ),
-                                transform->iv_dec,
-                                transform->fixed_ivlen,
-                                dynamic_iv,
-                                dynamic_iv_len );
+        ssl_build_record_nonce(iv, sizeof(iv),
+                               transform->iv_dec,
+                               transform->fixed_ivlen,
+                               dynamic_iv,
+                               dynamic_iv_len);
 
         /*
          * Build additional data for AEAD encryption.
          * This depends on the TLS version.
          */
-        ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
-                                          transform->minor_ver );
-        MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
-                               add_data, add_data_len );
+        ssl_extract_add_data_from_record(add_data, &add_data_len, rec,
+                                         transform->tls_version,
+                                         transform->taglen);
+        MBEDTLS_SSL_DEBUG_BUF(4, "additional data used for AEAD",
+                              add_data, add_data_len);
 
         /* Because of the check above, we know that there are
          * explicit_iv_len Bytes preceding data, and taglen
          * bytes following data + data_len. This justifies
          * the debug message and the invocation of
-         * mbedtls_cipher_auth_decrypt() below. */
+         * mbedtls_cipher_auth_decrypt_ext() below. */
 
-        MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen );
-        MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", data + rec->data_len,
-                               transform->taglen );
+        MBEDTLS_SSL_DEBUG_BUF(4, "IV used", iv, transform->ivlen);
+        MBEDTLS_SSL_DEBUG_BUF(4, "TAG used", data + rec->data_len,
+                              transform->taglen);
 
         /*
          * Decrypt and authenticate
          */
-        if( ( ret = mbedtls_cipher_auth_decrypt_ext( &transform->cipher_ctx_dec,
-                  iv, transform->ivlen,
-                  add_data, add_data_len,
-                  data, rec->data_len + transform->taglen,          /* src */
-                  data, rec->buf_len - (data - rec->buf), &olen,    /* dst */
-                  transform->taglen ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_decrypt", ret );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        status = psa_aead_decrypt(transform->psa_key_dec,
+                                  transform->psa_alg,
+                                  iv, transform->ivlen,
+                                  add_data, add_data_len,
+                                  data, rec->data_len + transform->taglen,
+                                  data, rec->buf_len - (data - rec->buf),
+                                  &olen);
 
-            if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED )
-                return( MBEDTLS_ERR_SSL_INVALID_MAC );
-
-            return( ret );
+        if (status != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_aead_decrypt", ret);
+            return ret;
         }
+#else
+        if ((ret = mbedtls_cipher_auth_decrypt_ext(&transform->cipher_ctx_dec,
+                                                   iv, transform->ivlen,
+                                                   add_data, add_data_len,
+                                                   data, rec->data_len + transform->taglen, /* src */
+                                                   data, rec->buf_len - (data - rec->buf), &olen, /* dst */
+                                                   transform->taglen)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_auth_decrypt_ext", ret);
+
+            if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) {
+                return MBEDTLS_ERR_SSL_INVALID_MAC;
+            }
+
+            return ret;
+        }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
         auth_done++;
 
         /* Double-check that AEAD decryption doesn't change content length. */
-        if( olen != rec->data_len )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        if (olen != rec->data_len) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
         }
-    }
-    else
+    } else
 #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */
 #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC)
-    if( mode == MBEDTLS_MODE_CBC )
-    {
+    if (ssl_mode == MBEDTLS_SSL_MODE_CBC ||
+        ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) {
         size_t minlen = 0;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+        size_t part_len;
+        psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
         /*
          * Check immediate ciphertext sanity
          */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
-        {
-            /* The ciphertext is prefixed with the CBC IV. */
-            minlen += transform->ivlen;
-        }
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        /* The ciphertext is prefixed with the CBC IV. */
+        minlen += transform->ivlen;
 #endif
 
         /* Size considerations:
@@ -1332,27 +1474,30 @@
          * lower bound minlen + maclen + 1 on the record size, which
          * we test for in the second check below.
          */
-        if( rec->data_len < minlen + transform->ivlen ||
-            rec->data_len < minlen + transform->maclen + 1 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
-                                        ") < max( ivlen(%" MBEDTLS_PRINTF_SIZET
-                                        "), maclen (%" MBEDTLS_PRINTF_SIZET ") "
-                                "+ 1 ) ( + expl IV )", rec->data_len,
-                                transform->ivlen,
-                                transform->maclen ) );
-            return( MBEDTLS_ERR_SSL_INVALID_MAC );
+        if (rec->data_len < minlen + transform->ivlen ||
+            rec->data_len < minlen + transform->maclen + 1) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("msglen (%" MBEDTLS_PRINTF_SIZET
+                                      ") < max( ivlen(%" MBEDTLS_PRINTF_SIZET
+                                      "), maclen (%" MBEDTLS_PRINTF_SIZET ") "
+                                                                          "+ 1 ) ( + expl IV )",
+                                      rec->data_len,
+                                      transform->ivlen,
+                                      transform->maclen));
+            return MBEDTLS_ERR_SSL_INVALID_MAC;
         }
 
         /*
          * Authenticate before decrypt if enabled
          */
 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-        if( transform->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED )
-        {
+        if (ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+            psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+#else
             unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD];
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
+            MBEDTLS_SSL_DEBUG_MSG(3, ("using encrypt then mac"));
 
             /* Update data_len in tandem with add_data.
              *
@@ -1365,49 +1510,86 @@
              *
              * Further, we still know that data_len > minlen */
             rec->data_len -= transform->maclen;
-            ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
-                                              transform->minor_ver );
+            ssl_extract_add_data_from_record(add_data, &add_data_len, rec,
+                                             transform->tls_version,
+                                             transform->taglen);
 
             /* Calculate expected MAC. */
-            MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data,
-                                   add_data_len );
-            ret = mbedtls_md_hmac_update( &transform->md_ctx_dec, add_data,
-                                          add_data_len );
-            if( ret != 0 )
+            MBEDTLS_SSL_DEBUG_BUF(4, "MAC'd meta-data", add_data,
+                                  add_data_len);
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+            status = psa_mac_verify_setup(&operation, transform->psa_mac_dec,
+                                          transform->psa_mac_alg);
+            if (status != PSA_SUCCESS) {
                 goto hmac_failed_etm_enabled;
-            ret = mbedtls_md_hmac_update( &transform->md_ctx_dec,
-                                    data, rec->data_len );
-            if( ret != 0 )
-                goto hmac_failed_etm_enabled;
-            ret = mbedtls_md_hmac_finish( &transform->md_ctx_dec, mac_expect );
-            if( ret != 0 )
-                goto hmac_failed_etm_enabled;
-            ret = mbedtls_md_hmac_reset( &transform->md_ctx_dec );
-            if( ret != 0 )
-                goto hmac_failed_etm_enabled;
+            }
 
-            MBEDTLS_SSL_DEBUG_BUF( 4, "message  mac", data + rec->data_len,
-                                   transform->maclen );
-            MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect,
-                                   transform->maclen );
+            status = psa_mac_update(&operation, add_data, add_data_len);
+            if (status != PSA_SUCCESS) {
+                goto hmac_failed_etm_enabled;
+            }
+
+            status = psa_mac_update(&operation, data, rec->data_len);
+            if (status != PSA_SUCCESS) {
+                goto hmac_failed_etm_enabled;
+            }
 
             /* Compare expected MAC with MAC at the end of the record. */
-            if( mbedtls_ct_memcmp( data + rec->data_len, mac_expect,
-                                              transform->maclen ) != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
+            status = psa_mac_verify_finish(&operation, data + rec->data_len,
+                                           transform->maclen);
+            if (status != PSA_SUCCESS) {
+                goto hmac_failed_etm_enabled;
+            }
+#else
+            ret = mbedtls_md_hmac_update(&transform->md_ctx_dec, add_data,
+                                         add_data_len);
+            if (ret != 0) {
+                goto hmac_failed_etm_enabled;
+            }
+            ret = mbedtls_md_hmac_update(&transform->md_ctx_dec,
+                                         data, rec->data_len);
+            if (ret != 0) {
+                goto hmac_failed_etm_enabled;
+            }
+            ret = mbedtls_md_hmac_finish(&transform->md_ctx_dec, mac_expect);
+            if (ret != 0) {
+                goto hmac_failed_etm_enabled;
+            }
+            ret = mbedtls_md_hmac_reset(&transform->md_ctx_dec);
+            if (ret != 0) {
+                goto hmac_failed_etm_enabled;
+            }
+
+            MBEDTLS_SSL_DEBUG_BUF(4, "message  mac", data + rec->data_len,
+                                  transform->maclen);
+            MBEDTLS_SSL_DEBUG_BUF(4, "expected mac", mac_expect,
+                                  transform->maclen);
+
+            /* Compare expected MAC with MAC at the end of the record. */
+            if (mbedtls_ct_memcmp(data + rec->data_len, mac_expect,
+                                  transform->maclen) != 0) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("message mac does not match"));
                 ret = MBEDTLS_ERR_SSL_INVALID_MAC;
                 goto hmac_failed_etm_enabled;
             }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
             auth_done++;
 
-        hmac_failed_etm_enabled:
-            mbedtls_platform_zeroize( mac_expect, transform->maclen );
-            if( ret != 0 )
-            {
-                if( ret != MBEDTLS_ERR_SSL_INVALID_MAC )
-                    MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_hmac_xxx", ret );
-                return( ret );
+hmac_failed_etm_enabled:
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            status = psa_mac_abort(&operation);
+            if (ret == 0 && status != PSA_SUCCESS) {
+                ret = PSA_TO_MBEDTLS_ERR(status);
+            }
+#else
+            mbedtls_platform_zeroize(mac_expect, transform->maclen);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+            if (ret != 0) {
+                if (ret != MBEDTLS_ERR_SSL_INVALID_MAC) {
+                    MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_hmac_xxx", ret);
+                }
+                return ret;
             }
         }
 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
@@ -1419,91 +1601,109 @@
         /* We know from above that data_len > minlen >= 0,
          * so the following check in particular implies that
          * data_len >= minlen + ivlen ( = minlen or 2 * minlen ). */
-        if( rec->data_len % transform->ivlen != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
-                                        ") %% ivlen (%" MBEDTLS_PRINTF_SIZET ") != 0",
-                                        rec->data_len, transform->ivlen ) );
-            return( MBEDTLS_ERR_SSL_INVALID_MAC );
+        if (rec->data_len % transform->ivlen != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("msglen (%" MBEDTLS_PRINTF_SIZET
+                                      ") %% ivlen (%" MBEDTLS_PRINTF_SIZET ") != 0",
+                                      rec->data_len, transform->ivlen));
+            return MBEDTLS_ERR_SSL_INVALID_MAC;
         }
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
         /*
-         * Initialize for prepended IV for block cipher in TLS v1.1 and up
+         * Initialize for prepended IV for block cipher in TLS v1.2
          */
-        if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
-        {
-            /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */
-            memcpy( transform->iv_dec, data, transform->ivlen );
+        /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */
+        memcpy(transform->iv_dec, data, transform->ivlen);
 
-            data += transform->ivlen;
-            rec->data_offset += transform->ivlen;
-            rec->data_len -= transform->ivlen;
-        }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
+        data += transform->ivlen;
+        rec->data_offset += transform->ivlen;
+        rec->data_len -= transform->ivlen;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
         /* We still have data_len % ivlen == 0 and data_len >= ivlen here. */
 
-        if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec,
-                                   transform->iv_dec, transform->ivlen,
-                                   data, rec->data_len, data, &olen ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
-            return( ret );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        status = psa_cipher_decrypt_setup(&cipher_op,
+                                          transform->psa_key_dec, transform->psa_alg);
+
+        if (status != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_decrypt_setup", ret);
+            return ret;
         }
 
+        status = psa_cipher_set_iv(&cipher_op, transform->iv_dec, transform->ivlen);
+
+        if (status != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_set_iv", ret);
+            return ret;
+        }
+
+        status = psa_cipher_update(&cipher_op,
+                                   data, rec->data_len,
+                                   data, rec->data_len, &olen);
+
+        if (status != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_update", ret);
+            return ret;
+        }
+
+        status = psa_cipher_finish(&cipher_op,
+                                   data + olen, rec->data_len - olen,
+                                   &part_len);
+
+        if (status != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_finish", ret);
+            return ret;
+        }
+
+        olen += part_len;
+#else
+
+        if ((ret = mbedtls_cipher_crypt(&transform->cipher_ctx_dec,
+                                        transform->iv_dec, transform->ivlen,
+                                        data, rec->data_len, data, &olen)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_crypt", ret);
+            return ret;
+        }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
         /* Double-check that length hasn't changed during decryption. */
-        if( rec->data_len != olen )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        if (rec->data_len != olen) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
         }
 
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1)
-        if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 )
-        {
-            /*
-             * Save IV in SSL3 and TLS1, where CBC decryption of consecutive
-             * records is equivalent to CBC decryption of the concatenation
-             * of the records; in other words, IVs are maintained across
-             * record decryptions.
-             */
-            memcpy( transform->iv_dec, transform->cipher_ctx_dec.iv,
-                    transform->ivlen );
-        }
-#endif
-
         /* Safe since data_len >= minlen + maclen + 1, so after having
          * subtracted at most minlen and maclen up to this point,
          * data_len > 0 (because of data_len % ivlen == 0, it's actually
          * >= ivlen ). */
         padlen = data[rec->data_len - 1];
 
-        if( auth_done == 1 )
-        {
+        if (auth_done == 1) {
             const size_t mask = mbedtls_ct_size_mask_ge(
-                                rec->data_len,
-                                padlen + 1 );
+                rec->data_len,
+                padlen + 1);
             correct &= mask;
             padlen  &= mask;
-        }
-        else
-        {
+        } else {
 #if defined(MBEDTLS_SSL_DEBUG_ALL)
-            if( rec->data_len < transform->maclen + padlen + 1 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET
-                                            ") < maclen (%" MBEDTLS_PRINTF_SIZET
-                                            ") + padlen (%" MBEDTLS_PRINTF_SIZET ")",
-                                            rec->data_len,
-                                            transform->maclen,
-                                            padlen + 1 ) );
+            if (rec->data_len < transform->maclen + padlen + 1) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("msglen (%" MBEDTLS_PRINTF_SIZET
+                                          ") < maclen (%" MBEDTLS_PRINTF_SIZET
+                                          ") + padlen (%" MBEDTLS_PRINTF_SIZET ")",
+                                          rec->data_len,
+                                          transform->maclen,
+                                          padlen + 1));
             }
 #endif
 
             const size_t mask = mbedtls_ct_size_mask_ge(
-                                rec->data_len,
-                                transform->maclen + padlen + 1 );
+                rec->data_len,
+                transform->maclen + padlen + 1);
             correct &= mask;
             padlen  &= mask;
         }
@@ -1513,96 +1713,66 @@
         /* Regardless of the validity of the padding,
          * we have data_len >= padlen here. */
 
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-        if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
-        {
-            /* This is the SSL 3.0 path, we don't have to worry about Lucky
-             * 13, because there's a strictly worse padding attack built in
-             * the protocol (known as part of POODLE), so we don't care if the
-             * code is not constant-time, in particular branches are OK. */
-            if( padlen > transform->ivlen )
-            {
-#if defined(MBEDTLS_SSL_DEBUG_ALL)
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %" MBEDTLS_PRINTF_SIZET ", "
-                                            "should be no more than %" MBEDTLS_PRINTF_SIZET,
-                                            padlen, transform->ivlen ) );
-#endif
-                correct = 0;
-            }
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        /* The padding check involves a series of up to 256
+         * consecutive memory reads at the end of the record
+         * plaintext buffer. In order to hide the length and
+         * validity of the padding, always perform exactly
+         * `min(256,plaintext_len)` reads (but take into account
+         * only the last `padlen` bytes for the padding check). */
+        size_t pad_count = 0;
+        volatile unsigned char * const check = data;
+
+        /* Index of first padding byte; it has been ensured above
+         * that the subtraction is safe. */
+        size_t const padding_idx = rec->data_len - padlen;
+        size_t const num_checks = rec->data_len <= 256 ? rec->data_len : 256;
+        size_t const start_idx = rec->data_len - num_checks;
+        size_t idx;
+
+        for (idx = start_idx; idx < rec->data_len; idx++) {
+            /* pad_count += (idx >= padding_idx) &&
+             *              (check[idx] == padlen - 1);
+             */
+            const size_t mask = mbedtls_ct_size_mask_ge(idx, padding_idx);
+            const size_t equal = mbedtls_ct_size_bool_eq(check[idx],
+                                                         padlen - 1);
+            pad_count += mask & equal;
         }
-        else
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 )
-        {
-            /* The padding check involves a series of up to 256
-             * consecutive memory reads at the end of the record
-             * plaintext buffer. In order to hide the length and
-             * validity of the padding, always perform exactly
-             * `min(256,plaintext_len)` reads (but take into account
-             * only the last `padlen` bytes for the padding check). */
-            size_t pad_count = 0;
-            volatile unsigned char* const check = data;
-
-            /* Index of first padding byte; it has been ensured above
-             * that the subtraction is safe. */
-            size_t const padding_idx = rec->data_len - padlen;
-            size_t const num_checks = rec->data_len <= 256 ? rec->data_len : 256;
-            size_t const start_idx = rec->data_len - num_checks;
-            size_t idx;
-
-            for( idx = start_idx; idx < rec->data_len; idx++ )
-            {
-                /* pad_count += (idx >= padding_idx) &&
-                 *              (check[idx] == padlen - 1);
-                 */
-                const size_t mask = mbedtls_ct_size_mask_ge( idx, padding_idx );
-                const size_t equal = mbedtls_ct_size_bool_eq( check[idx],
-                                                              padlen - 1 );
-                pad_count += mask & equal;
-            }
-            correct &= mbedtls_ct_size_bool_eq( pad_count, padlen );
+        correct &= mbedtls_ct_size_bool_eq(pad_count, padlen);
 
 #if defined(MBEDTLS_SSL_DEBUG_ALL)
-            if( padlen > 0 && correct == 0 )
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) );
+        if (padlen > 0 && correct == 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad padding byte detected"));
+        }
 #endif
-            padlen &= mbedtls_ct_size_mask( correct );
-        }
-        else
-#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
-          MBEDTLS_SSL_PROTO_TLS1_2 */
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-        }
+        padlen &= mbedtls_ct_size_mask(correct);
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
         /* If the padding was found to be invalid, padlen == 0
          * and the subtraction is safe. If the padding was found valid,
          * padlen hasn't been changed and the previous assertion
          * data_len >= padlen still holds. */
         rec->data_len -= padlen;
-    }
-    else
+    } else
 #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC */
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
 #if defined(MBEDTLS_SSL_DEBUG_ALL)
-    MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption",
-                           data, rec->data_len );
+    MBEDTLS_SSL_DEBUG_BUF(4, "raw buffer after decryption",
+                          data, rec->data_len);
 #endif
 
     /*
      * Authenticate if not done yet.
      * Compute the MAC regardless of the padding result (RFC4346, CBCTIME).
      */
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
-    if( auth_done == 0 )
-    {
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
+    if (auth_done == 0) {
         unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD] = { 0 };
         unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD] = { 0 };
 
@@ -1620,244 +1790,114 @@
          * hence data_len >= maclen in any case.
          */
         rec->data_len -= transform->maclen;
-        ssl_extract_add_data_from_record( add_data, &add_data_len, rec,
-                                          transform->minor_ver );
+        ssl_extract_add_data_from_record(add_data, &add_data_len, rec,
+                                         transform->tls_version,
+                                         transform->taglen);
 
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-        if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
-        {
-            ret = ssl_mac( &transform->md_ctx_dec,
-                           transform->mac_dec,
-                           data, rec->data_len,
-                           rec->ctr, rec->type,
-                           mac_expect );
-            if( ret != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_RET( 1, "ssl_mac", ret );
-                goto hmac_failed_etm_disabled;
-            }
-            memcpy( mac_peer, data + rec->data_len, transform->maclen );
-        }
-        else
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
-        defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 )
-        {
-            /*
-             * The next two sizes are the minimum and maximum values of
-             * data_len over all padlen values.
-             *
-             * They're independent of padlen, since we previously did
-             * data_len -= padlen.
-             *
-             * Note that max_len + maclen is never more than the buffer
-             * length, as we previously did in_msglen -= maclen too.
-             */
-            const size_t max_len = rec->data_len + padlen;
-            const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0;
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        /*
+         * The next two sizes are the minimum and maximum values of
+         * data_len over all padlen values.
+         *
+         * They're independent of padlen, since we previously did
+         * data_len -= padlen.
+         *
+         * Note that max_len + maclen is never more than the buffer
+         * length, as we previously did in_msglen -= maclen too.
+         */
+        const size_t max_len = rec->data_len + padlen;
+        const size_t min_len = (max_len > 256) ? max_len - 256 : 0;
 
-            ret = mbedtls_ct_hmac( &transform->md_ctx_dec,
-                                   add_data, add_data_len,
-                                   data, rec->data_len, min_len, max_len,
-                                   mac_expect );
-            if( ret != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ct_hmac", ret );
-                goto hmac_failed_etm_disabled;
-            }
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        ret = mbedtls_ct_hmac(transform->psa_mac_dec,
+                              transform->psa_mac_alg,
+                              add_data, add_data_len,
+                              data, rec->data_len, min_len, max_len,
+                              mac_expect);
+#else
+        ret = mbedtls_ct_hmac(&transform->md_ctx_dec,
+                              add_data, add_data_len,
+                              data, rec->data_len, min_len, max_len,
+                              mac_expect);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ct_hmac", ret);
+            goto hmac_failed_etm_disabled;
+        }
 
-            mbedtls_ct_memcpy_offset( mac_peer, data,
-                                      rec->data_len,
-                                      min_len, max_len,
-                                      transform->maclen );
-        }
-        else
-#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
-              MBEDTLS_SSL_PROTO_TLS1_2 */
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-        }
+        mbedtls_ct_memcpy_offset(mac_peer, data,
+                                 rec->data_len,
+                                 min_len, max_len,
+                                 transform->maclen);
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
 #if defined(MBEDTLS_SSL_DEBUG_ALL)
-        MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, transform->maclen );
-        MBEDTLS_SSL_DEBUG_BUF( 4, "message  mac", mac_peer, transform->maclen );
+        MBEDTLS_SSL_DEBUG_BUF(4, "expected mac", mac_expect, transform->maclen);
+        MBEDTLS_SSL_DEBUG_BUF(4, "message  mac", mac_peer, transform->maclen);
 #endif
 
-        if( mbedtls_ct_memcmp( mac_peer, mac_expect,
-                                          transform->maclen ) != 0 )
-        {
+        if (mbedtls_ct_memcmp(mac_peer, mac_expect,
+                              transform->maclen) != 0) {
 #if defined(MBEDTLS_SSL_DEBUG_ALL)
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
+            MBEDTLS_SSL_DEBUG_MSG(1, ("message mac does not match"));
 #endif
             correct = 0;
         }
         auth_done++;
 
-    hmac_failed_etm_disabled:
-        mbedtls_platform_zeroize( mac_peer, transform->maclen );
-        mbedtls_platform_zeroize( mac_expect, transform->maclen );
-        if( ret != 0 )
-            return( ret );
+hmac_failed_etm_disabled:
+        mbedtls_platform_zeroize(mac_peer, transform->maclen);
+        mbedtls_platform_zeroize(mac_expect, transform->maclen);
+        if (ret != 0) {
+            return ret;
+        }
     }
 
     /*
      * Finally check the correct flag
      */
-    if( correct == 0 )
-        return( MBEDTLS_ERR_SSL_INVALID_MAC );
-#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
+    if (correct == 0) {
+        return MBEDTLS_ERR_SSL_INVALID_MAC;
+    }
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
 
     /* Make extra sure authentication was performed, exactly once */
-    if( auth_done != 1 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    if (auth_done != 1) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
-    if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 )
-    {
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    if (transform->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
         /* Remove inner padding and infer true content type. */
-        ret = ssl_parse_inner_plaintext( data, &rec->data_len,
-                                         &rec->type );
+        ret = ssl_parse_inner_plaintext(data, &rec->data_len,
+                                        &rec->type);
 
-        if( ret != 0 )
-            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+        if (ret != 0) {
+            return MBEDTLS_ERR_SSL_INVALID_RECORD;
+        }
     }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    if( rec->cid_len != 0 )
-    {
-        ret = ssl_parse_inner_plaintext( data, &rec->data_len,
-                                         &rec->type );
-        if( ret != 0 )
-            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+    if (rec->cid_len != 0) {
+        ret = ssl_parse_inner_plaintext(data, &rec->data_len,
+                                        &rec->type);
+        if (ret != 0) {
+            return MBEDTLS_ERR_SSL_INVALID_RECORD;
+        }
     }
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= decrypt buf"));
 
-    return( 0 );
+    return 0;
 }
 
 #undef MAC_NONE
 #undef MAC_PLAINTEXT
 #undef MAC_CIPHERTEXT
 
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-/*
- * Compression/decompression functions
- */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_compress_buf( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char *msg_post = ssl->out_msg;
-    ptrdiff_t bytes_written = ssl->out_msg - ssl->out_buf;
-    size_t len_pre = ssl->out_msglen;
-    unsigned char *msg_pre = ssl->compress_buf;
-#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
-    size_t out_buf_len = ssl->out_buf_len;
-#else
-    size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
-#endif
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> compress buf" ) );
-
-    if( len_pre == 0 )
-        return( 0 );
-
-    memcpy( msg_pre, ssl->out_msg, len_pre );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %" MBEDTLS_PRINTF_SIZET ", ",
-                   ssl->out_msglen ) );
-
-    MBEDTLS_SSL_DEBUG_BUF( 4, "before compression: output payload",
-                   ssl->out_msg, ssl->out_msglen );
-
-    ssl->transform_out->ctx_deflate.next_in = msg_pre;
-    ssl->transform_out->ctx_deflate.avail_in = len_pre;
-    ssl->transform_out->ctx_deflate.next_out = msg_post;
-    ssl->transform_out->ctx_deflate.avail_out = out_buf_len - bytes_written;
-
-    ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH );
-    if( ret != Z_OK )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) );
-        return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
-    }
-
-    ssl->out_msglen = out_buf_len -
-                      ssl->transform_out->ctx_deflate.avail_out - bytes_written;
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %" MBEDTLS_PRINTF_SIZET ", ",
-                   ssl->out_msglen ) );
-
-    MBEDTLS_SSL_DEBUG_BUF( 4, "after compression: output payload",
-                   ssl->out_msg, ssl->out_msglen );
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= compress buf" ) );
-
-    return( 0 );
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_decompress_buf( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char *msg_post = ssl->in_msg;
-    ptrdiff_t header_bytes = ssl->in_msg - ssl->in_buf;
-    size_t len_pre = ssl->in_msglen;
-    unsigned char *msg_pre = ssl->compress_buf;
-#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
-    size_t in_buf_len = ssl->in_buf_len;
-#else
-    size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
-#endif
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) );
-
-    if( len_pre == 0 )
-        return( 0 );
-
-    memcpy( msg_pre, ssl->in_msg, len_pre );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %" MBEDTLS_PRINTF_SIZET ", ",
-                   ssl->in_msglen ) );
-
-    MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload",
-                   ssl->in_msg, ssl->in_msglen );
-
-    ssl->transform_in->ctx_inflate.next_in = msg_pre;
-    ssl->transform_in->ctx_inflate.avail_in = len_pre;
-    ssl->transform_in->ctx_inflate.next_out = msg_post;
-    ssl->transform_in->ctx_inflate.avail_out = in_buf_len - header_bytes;
-
-    ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH );
-    if( ret != Z_OK )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) );
-        return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
-    }
-
-    ssl->in_msglen = in_buf_len -
-                     ssl->transform_in->ctx_inflate.avail_out - header_bytes;
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %" MBEDTLS_PRINTF_SIZET ", ",
-                   ssl->in_msglen ) );
-
-    MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload",
-                   ssl->in_msg, ssl->in_msglen );
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_ZLIB_SUPPORT */
-
 /*
  * Fill the input message buffer by appending data to it.
  * The amount of data already fetched is in ssl->in_left.
@@ -1873,7 +1913,7 @@
  * For DTLS, it is up to the caller to set ssl->next_record_offset when
  * they're done reading a record.
  */
-int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
+int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
@@ -1883,24 +1923,20 @@
     size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
 #endif
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> fetch input"));
 
-    if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() "
-                            "or mbedtls_ssl_set_bio()" ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl->f_recv == NULL && ssl->f_recv_timeout == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Bad usage of mbedtls_ssl_set_bio() "));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    if( nb_want > in_buf_len - (size_t)( ssl->in_hdr - ssl->in_buf ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (nb_want > in_buf_len - (size_t) (ssl->in_hdr - ssl->in_buf)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("requesting more data than fits"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
         uint32_t timeout;
 
         /*
@@ -1913,40 +1949,36 @@
         /*
          * Move to the next record in the already read datagram if applicable
          */
-        if( ssl->next_record_offset != 0 )
-        {
-            if( ssl->in_left < ssl->next_record_offset )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-                return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        if (ssl->next_record_offset != 0) {
+            if (ssl->in_left < ssl->next_record_offset) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+                return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
             }
 
             ssl->in_left -= ssl->next_record_offset;
 
-            if( ssl->in_left != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %"
-                                            MBEDTLS_PRINTF_SIZET,
-                                    ssl->next_record_offset ) );
-                memmove( ssl->in_hdr,
-                         ssl->in_hdr + ssl->next_record_offset,
-                         ssl->in_left );
+            if (ssl->in_left != 0) {
+                MBEDTLS_SSL_DEBUG_MSG(2, ("next record in same datagram, offset: %"
+                                          MBEDTLS_PRINTF_SIZET,
+                                          ssl->next_record_offset));
+                memmove(ssl->in_hdr,
+                        ssl->in_hdr + ssl->next_record_offset,
+                        ssl->in_left);
             }
 
             ssl->next_record_offset = 0;
         }
 
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
-                                    ", nb_want: %" MBEDTLS_PRINTF_SIZET,
-                       ssl->in_left, nb_want ) );
+        MBEDTLS_SSL_DEBUG_MSG(2, ("in_left: %" MBEDTLS_PRINTF_SIZET
+                                  ", nb_want: %" MBEDTLS_PRINTF_SIZET,
+                                  ssl->in_left, nb_want));
 
         /*
          * Done if we already have enough data.
          */
-        if( nb_want <= ssl->in_left)
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) );
-            return( 0 );
+        if (nb_want <= ssl->in_left) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("<= fetch input"));
+            return 0;
         }
 
         /*
@@ -1954,10 +1986,9 @@
          * are not at the beginning of a new record, the caller did something
          * wrong.
          */
-        if( ssl->in_left != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        if (ssl->in_left != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
         }
 
         /*
@@ -1965,196 +1996,182 @@
          * This avoids by-passing the timer when repeatedly receiving messages
          * that will end up being dropped.
          */
-        if( mbedtls_ssl_check_timer( ssl ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "timer has expired" ) );
+        if (mbedtls_ssl_check_timer(ssl) != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("timer has expired"));
             ret = MBEDTLS_ERR_SSL_TIMEOUT;
-        }
-        else
-        {
-            len = in_buf_len - ( ssl->in_hdr - ssl->in_buf );
+        } else {
+            len = in_buf_len - (ssl->in_hdr - ssl->in_buf);
 
-            if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
+            if (mbedtls_ssl_is_handshake_over(ssl) == 0) {
                 timeout = ssl->handshake->retransmit_timeout;
-            else
+            } else {
                 timeout = ssl->conf->read_timeout;
+            }
 
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %lu ms", (unsigned long) timeout ) );
+            MBEDTLS_SSL_DEBUG_MSG(3, ("f_recv_timeout: %lu ms", (unsigned long) timeout));
 
-            if( ssl->f_recv_timeout != NULL )
-                ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len,
-                                                                    timeout );
-            else
-                ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len );
+            if (ssl->f_recv_timeout != NULL) {
+                ret = ssl->f_recv_timeout(ssl->p_bio, ssl->in_hdr, len,
+                                          timeout);
+            } else {
+                ret = ssl->f_recv(ssl->p_bio, ssl->in_hdr, len);
+            }
 
-            MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret );
+            MBEDTLS_SSL_DEBUG_RET(2, "ssl->f_recv(_timeout)", ret);
 
-            if( ret == 0 )
-                return( MBEDTLS_ERR_SSL_CONN_EOF );
+            if (ret == 0) {
+                return MBEDTLS_ERR_SSL_CONN_EOF;
+            }
         }
 
-        if( ret == MBEDTLS_ERR_SSL_TIMEOUT )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) );
-            mbedtls_ssl_set_timer( ssl, 0 );
+        if (ret == MBEDTLS_ERR_SSL_TIMEOUT) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("timeout"));
+            mbedtls_ssl_set_timer(ssl, 0);
 
-            if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
-            {
-                if( ssl_double_retransmit_timeout( ssl ) != 0 )
-                {
-                    MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) );
-                    return( MBEDTLS_ERR_SSL_TIMEOUT );
+            if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) {
+                if (ssl_double_retransmit_timeout(ssl) != 0) {
+                    MBEDTLS_SSL_DEBUG_MSG(1, ("handshake timeout"));
+                    return MBEDTLS_ERR_SSL_TIMEOUT;
                 }
 
-                if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
-                {
-                    MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret );
-                    return( ret );
+                if ((ret = mbedtls_ssl_resend(ssl)) != 0) {
+                    MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_resend", ret);
+                    return ret;
                 }
 
-                return( MBEDTLS_ERR_SSL_WANT_READ );
+                return MBEDTLS_ERR_SSL_WANT_READ;
             }
 #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
-            else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
-                     ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
-            {
-                if( ( ret = mbedtls_ssl_resend_hello_request( ssl ) ) != 0 )
-                {
-                    MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend_hello_request",
-                                           ret );
-                    return( ret );
+            else if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+                     ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) {
+                if ((ret = mbedtls_ssl_resend_hello_request(ssl)) != 0) {
+                    MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_resend_hello_request",
+                                          ret);
+                    return ret;
                 }
 
-                return( MBEDTLS_ERR_SSL_WANT_READ );
+                return MBEDTLS_ERR_SSL_WANT_READ;
             }
 #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
         }
 
-        if( ret < 0 )
-            return( ret );
+        if (ret < 0) {
+            return ret;
+        }
 
         ssl->in_left = ret;
-    }
-    else
+    } else
 #endif
     {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
-                                    ", nb_want: %" MBEDTLS_PRINTF_SIZET,
-                       ssl->in_left, nb_want ) );
+        MBEDTLS_SSL_DEBUG_MSG(2, ("in_left: %" MBEDTLS_PRINTF_SIZET
+                                  ", nb_want: %" MBEDTLS_PRINTF_SIZET,
+                                  ssl->in_left, nb_want));
 
-        while( ssl->in_left < nb_want )
-        {
+        while (ssl->in_left < nb_want) {
             len = nb_want - ssl->in_left;
 
-            if( mbedtls_ssl_check_timer( ssl ) != 0 )
+            if (mbedtls_ssl_check_timer(ssl) != 0) {
                 ret = MBEDTLS_ERR_SSL_TIMEOUT;
-            else
-            {
-                if( ssl->f_recv_timeout != NULL )
-                {
-                    ret = ssl->f_recv_timeout( ssl->p_bio,
-                                               ssl->in_hdr + ssl->in_left, len,
-                                               ssl->conf->read_timeout );
-                }
-                else
-                {
-                    ret = ssl->f_recv( ssl->p_bio,
-                                       ssl->in_hdr + ssl->in_left, len );
+            } else {
+                if (ssl->f_recv_timeout != NULL) {
+                    ret = ssl->f_recv_timeout(ssl->p_bio,
+                                              ssl->in_hdr + ssl->in_left, len,
+                                              ssl->conf->read_timeout);
+                } else {
+                    ret = ssl->f_recv(ssl->p_bio,
+                                      ssl->in_hdr + ssl->in_left, len);
                 }
             }
 
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET
-                                        ", nb_want: %" MBEDTLS_PRINTF_SIZET,
-                                        ssl->in_left, nb_want ) );
-            MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret );
+            MBEDTLS_SSL_DEBUG_MSG(2, ("in_left: %" MBEDTLS_PRINTF_SIZET
+                                      ", nb_want: %" MBEDTLS_PRINTF_SIZET,
+                                      ssl->in_left, nb_want));
+            MBEDTLS_SSL_DEBUG_RET(2, "ssl->f_recv(_timeout)", ret);
 
-            if( ret == 0 )
-                return( MBEDTLS_ERR_SSL_CONN_EOF );
+            if (ret == 0) {
+                return MBEDTLS_ERR_SSL_CONN_EOF;
+            }
 
-            if( ret < 0 )
-                return( ret );
+            if (ret < 0) {
+                return ret;
+            }
 
-            if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1,
-                    ( "f_recv returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " were requested",
-                    ret, len ) );
-                return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+            if ((size_t) ret > len) {
+                MBEDTLS_SSL_DEBUG_MSG(1,
+                                      ("f_recv returned %d bytes but only %" MBEDTLS_PRINTF_SIZET
+                                       " were requested",
+                                       ret, len));
+                return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
             }
 
             ssl->in_left += ret;
         }
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= fetch input"));
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Flush any data not yet written
  */
-int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_flush_output(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *buf;
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> flush output"));
 
-    if( ssl->f_send == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() "
-                            "or mbedtls_ssl_set_bio()" ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl->f_send == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Bad usage of mbedtls_ssl_set_bio() "));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
     /* Avoid incrementing counter if data is flushed */
-    if( ssl->out_left == 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
-        return( 0 );
+    if (ssl->out_left == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= flush output"));
+        return 0;
     }
 
-    while( ssl->out_left > 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %" MBEDTLS_PRINTF_SIZET
-                                    ", out_left: %" MBEDTLS_PRINTF_SIZET,
-                       mbedtls_ssl_out_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) );
+    while (ssl->out_left > 0) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("message length: %" MBEDTLS_PRINTF_SIZET
+                                  ", out_left: %" MBEDTLS_PRINTF_SIZET,
+                                  mbedtls_ssl_out_hdr_len(ssl) + ssl->out_msglen, ssl->out_left));
 
         buf = ssl->out_hdr - ssl->out_left;
-        ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left );
+        ret = ssl->f_send(ssl->p_bio, buf, ssl->out_left);
 
-        MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret );
+        MBEDTLS_SSL_DEBUG_RET(2, "ssl->f_send", ret);
 
-        if( ret <= 0 )
-            return( ret );
+        if (ret <= 0) {
+            return ret;
+        }
 
-        if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1,
-                ( "f_send returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " bytes were sent",
-                ret, ssl->out_left ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        if ((size_t) ret > ssl->out_left) {
+            MBEDTLS_SSL_DEBUG_MSG(1,
+                                  ("f_send returned %d bytes but only %" MBEDTLS_PRINTF_SIZET
+                                   " bytes were sent",
+                                   ret, ssl->out_left));
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
         }
 
         ssl->out_left -= ret;
     }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
         ssl->out_hdr = ssl->out_buf;
-    }
-    else
+    } else
 #endif
     {
         ssl->out_hdr = ssl->out_buf + 8;
     }
-    mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out );
+    mbedtls_ssl_update_out_pointers(ssl, ssl->transform_out);
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= flush output"));
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -2165,64 +2182,61 @@
  * Append current handshake message to current outgoing flight
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_flight_append( mbedtls_ssl_context *ssl )
+static int ssl_flight_append(mbedtls_ssl_context *ssl)
 {
     mbedtls_ssl_flight_item *msg;
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) );
-    MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight",
-                           ssl->out_msg, ssl->out_msglen );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_flight_append"));
+    MBEDTLS_SSL_DEBUG_BUF(4, "message appended to flight",
+                          ssl->out_msg, ssl->out_msglen);
 
     /* Allocate space for current message */
-    if( ( msg = mbedtls_calloc( 1, sizeof(  mbedtls_ssl_flight_item ) ) ) == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %" MBEDTLS_PRINTF_SIZET " bytes failed",
-                            sizeof( mbedtls_ssl_flight_item ) ) );
-        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+    if ((msg = mbedtls_calloc(1, sizeof(mbedtls_ssl_flight_item))) == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("alloc %" MBEDTLS_PRINTF_SIZET " bytes failed",
+                                  sizeof(mbedtls_ssl_flight_item)));
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
     }
 
-    if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %" MBEDTLS_PRINTF_SIZET " bytes failed",
-                                    ssl->out_msglen ) );
-        mbedtls_free( msg );
-        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+    if ((msg->p = mbedtls_calloc(1, ssl->out_msglen)) == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("alloc %" MBEDTLS_PRINTF_SIZET " bytes failed",
+                                  ssl->out_msglen));
+        mbedtls_free(msg);
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
     }
 
     /* Copy current handshake message with headers */
-    memcpy( msg->p, ssl->out_msg, ssl->out_msglen );
+    memcpy(msg->p, ssl->out_msg, ssl->out_msglen);
     msg->len = ssl->out_msglen;
     msg->type = ssl->out_msgtype;
     msg->next = NULL;
 
     /* Append to the current flight */
-    if( ssl->handshake->flight == NULL )
+    if (ssl->handshake->flight == NULL) {
         ssl->handshake->flight = msg;
-    else
-    {
+    } else {
         mbedtls_ssl_flight_item *cur = ssl->handshake->flight;
-        while( cur->next != NULL )
+        while (cur->next != NULL) {
             cur = cur->next;
+        }
         cur->next = msg;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) );
-    return( 0 );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_flight_append"));
+    return 0;
 }
 
 /*
  * Free the current flight of handshake messages
  */
-void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight )
+void mbedtls_ssl_flight_free(mbedtls_ssl_flight_item *flight)
 {
     mbedtls_ssl_flight_item *cur = flight;
     mbedtls_ssl_flight_item *next;
 
-    while( cur != NULL )
-    {
+    while (cur != NULL) {
         next = cur->next;
 
-        mbedtls_free( cur->p );
-        mbedtls_free( cur );
+        mbedtls_free(cur->p);
+        mbedtls_free(cur);
 
         cur = next;
     }
@@ -2232,18 +2246,17 @@
  * Swap transform_out and out_ctr with the alternative ones
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_swap_epochs( mbedtls_ssl_context *ssl )
+static int ssl_swap_epochs(mbedtls_ssl_context *ssl)
 {
     mbedtls_ssl_transform *tmp_transform;
-    unsigned char tmp_out_ctr[8];
+    unsigned char tmp_out_ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN];
 
-    if( ssl->transform_out == ssl->handshake->alt_transform_out )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) );
-        return( 0 );
+    if (ssl->transform_out == ssl->handshake->alt_transform_out) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("skip swap epochs"));
+        return 0;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) );
+    MBEDTLS_SSL_DEBUG_MSG(3, ("swap epochs"));
 
     /* Swap transforms */
     tmp_transform                     = ssl->transform_out;
@@ -2251,42 +2264,32 @@
     ssl->handshake->alt_transform_out = tmp_transform;
 
     /* Swap epoch + sequence_number */
-    memcpy( tmp_out_ctr,                 ssl->cur_out_ctr,            8 );
-    memcpy( ssl->cur_out_ctr,            ssl->handshake->alt_out_ctr, 8 );
-    memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr,                 8 );
+    memcpy(tmp_out_ctr, ssl->cur_out_ctr, sizeof(tmp_out_ctr));
+    memcpy(ssl->cur_out_ctr, ssl->handshake->alt_out_ctr,
+           sizeof(ssl->cur_out_ctr));
+    memcpy(ssl->handshake->alt_out_ctr, tmp_out_ctr,
+           sizeof(ssl->handshake->alt_out_ctr));
 
     /* Adjust to the newly activated transform */
-    mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out );
+    mbedtls_ssl_update_out_pointers(ssl, ssl->transform_out);
 
-#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
-    if( mbedtls_ssl_hw_record_activate != NULL )
-    {
-        int ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND );
-        if( ret != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret );
-            return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-        }
-    }
-#endif
-
-    return( 0 );
+    return 0;
 }
 
 /*
  * Retransmit the current flight of messages.
  */
-int mbedtls_ssl_resend( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_resend(mbedtls_ssl_context *ssl)
 {
     int ret = 0;
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> mbedtls_ssl_resend"));
 
-    ret = mbedtls_ssl_flight_transmit( ssl );
+    ret = mbedtls_ssl_flight_transmit(ssl);
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= mbedtls_ssl_resend"));
 
-    return( ret );
+    return ret;
 }
 
 /*
@@ -2296,121 +2299,117 @@
  * WANT_WRITE, causing us to exit this function and come back later.
  * This function must be called until state is no longer SENDING.
  */
-int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_flight_transmit(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> mbedtls_ssl_flight_transmit"));
 
-    if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise flight transmission" ) );
+    if (ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("initialise flight transmission"));
 
         ssl->handshake->cur_msg = ssl->handshake->flight;
         ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12;
-        ret = ssl_swap_epochs( ssl );
-        if( ret != 0 )
-            return( ret );
+        ret = ssl_swap_epochs(ssl);
+        if (ret != 0) {
+            return ret;
+        }
 
         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING;
     }
 
-    while( ssl->handshake->cur_msg != NULL )
-    {
+    while (ssl->handshake->cur_msg != NULL) {
         size_t max_frag_len;
         const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg;
 
         int const is_finished =
-            ( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE &&
-              cur->p[0] == MBEDTLS_SSL_HS_FINISHED );
+            (cur->type == MBEDTLS_SSL_MSG_HANDSHAKE &&
+             cur->p[0] == MBEDTLS_SSL_HS_FINISHED);
 
-        uint8_t const force_flush = ssl->disable_datagram_packing == 1 ?
-            SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH;
+        int const force_flush = ssl->disable_datagram_packing == 1 ?
+                                SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH;
 
         /* Swap epochs before sending Finished: we can't do it after
          * sending ChangeCipherSpec, in case write returns WANT_READ.
          * Must be done before copying, may change out_msg pointer */
-        if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) );
-            ret = ssl_swap_epochs( ssl );
-            if( ret != 0 )
-                return( ret );
+        if (is_finished && ssl->handshake->cur_msg_p == (cur->p + 12)) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("swap epochs to send finished message"));
+            ret = ssl_swap_epochs(ssl);
+            if (ret != 0) {
+                return ret;
+            }
         }
 
-        ret = ssl_get_remaining_payload_in_datagram( ssl );
-        if( ret < 0 )
-            return( ret );
+        ret = ssl_get_remaining_payload_in_datagram(ssl);
+        if (ret < 0) {
+            return ret;
+        }
         max_frag_len = (size_t) ret;
 
         /* CCS is copied as is, while HS messages may need fragmentation */
-        if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
-        {
-            if( max_frag_len == 0 )
-            {
-                if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
-                    return( ret );
+        if (cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) {
+            if (max_frag_len == 0) {
+                if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) {
+                    return ret;
+                }
 
                 continue;
             }
 
-            memcpy( ssl->out_msg, cur->p, cur->len );
+            memcpy(ssl->out_msg, cur->p, cur->len);
             ssl->out_msglen  = cur->len;
             ssl->out_msgtype = cur->type;
 
             /* Update position inside current message */
             ssl->handshake->cur_msg_p += cur->len;
-        }
-        else
-        {
+        } else {
             const unsigned char * const p = ssl->handshake->cur_msg_p;
             const size_t hs_len = cur->len - 12;
-            const size_t frag_off = p - ( cur->p + 12 );
+            const size_t frag_off = p - (cur->p + 12);
             const size_t rem_len = hs_len - frag_off;
             size_t cur_hs_frag_len, max_hs_frag_len;
 
-            if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) )
-            {
-                if( is_finished )
-                {
-                    ret = ssl_swap_epochs( ssl );
-                    if( ret != 0 )
-                        return( ret );
+            if ((max_frag_len < 12) || (max_frag_len == 12 && hs_len != 0)) {
+                if (is_finished) {
+                    ret = ssl_swap_epochs(ssl);
+                    if (ret != 0) {
+                        return ret;
+                    }
                 }
 
-                if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
-                    return( ret );
+                if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) {
+                    return ret;
+                }
 
                 continue;
             }
             max_hs_frag_len = max_frag_len - 12;
 
             cur_hs_frag_len = rem_len > max_hs_frag_len ?
-                max_hs_frag_len : rem_len;
+                              max_hs_frag_len : rem_len;
 
-            if( frag_off == 0 && cur_hs_frag_len != hs_len )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)",
-                                            (unsigned) cur_hs_frag_len,
-                                            (unsigned) max_hs_frag_len ) );
+            if (frag_off == 0 && cur_hs_frag_len != hs_len) {
+                MBEDTLS_SSL_DEBUG_MSG(2, ("fragmenting handshake message (%u > %u)",
+                                          (unsigned) cur_hs_frag_len,
+                                          (unsigned) max_hs_frag_len));
             }
 
             /* Messages are stored with handshake headers as if not fragmented,
              * copy beginning of headers then fill fragmentation fields.
              * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */
-            memcpy( ssl->out_msg, cur->p, 6 );
+            memcpy(ssl->out_msg, cur->p, 6);
 
-            ssl->out_msg[6] = MBEDTLS_BYTE_2( frag_off );
-            ssl->out_msg[7] = MBEDTLS_BYTE_1( frag_off );
-            ssl->out_msg[8] = MBEDTLS_BYTE_0( frag_off );
+            ssl->out_msg[6] = MBEDTLS_BYTE_2(frag_off);
+            ssl->out_msg[7] = MBEDTLS_BYTE_1(frag_off);
+            ssl->out_msg[8] = MBEDTLS_BYTE_0(frag_off);
 
-            ssl->out_msg[ 9] = MBEDTLS_BYTE_2( cur_hs_frag_len );
-            ssl->out_msg[10] = MBEDTLS_BYTE_1( cur_hs_frag_len );
-            ssl->out_msg[11] = MBEDTLS_BYTE_0( cur_hs_frag_len );
+            ssl->out_msg[9] = MBEDTLS_BYTE_2(cur_hs_frag_len);
+            ssl->out_msg[10] = MBEDTLS_BYTE_1(cur_hs_frag_len);
+            ssl->out_msg[11] = MBEDTLS_BYTE_0(cur_hs_frag_len);
 
-            MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 );
+            MBEDTLS_SSL_DEBUG_BUF(3, "handshake header", ssl->out_msg, 12);
 
             /* Copy the handshake message content and set records fields */
-            memcpy( ssl->out_msg + 12, p, cur_hs_frag_len );
+            memcpy(ssl->out_msg + 12, p, cur_hs_frag_len);
             ssl->out_msglen = cur_hs_frag_len + 12;
             ssl->out_msgtype = cur->type;
 
@@ -2419,52 +2418,47 @@
         }
 
         /* If done with the current message move to the next one if any */
-        if( ssl->handshake->cur_msg_p >= cur->p + cur->len )
-        {
-            if( cur->next != NULL )
-            {
+        if (ssl->handshake->cur_msg_p >= cur->p + cur->len) {
+            if (cur->next != NULL) {
                 ssl->handshake->cur_msg = cur->next;
                 ssl->handshake->cur_msg_p = cur->next->p + 12;
-            }
-            else
-            {
+            } else {
                 ssl->handshake->cur_msg = NULL;
                 ssl->handshake->cur_msg_p = NULL;
             }
         }
 
         /* Actually send the message out */
-        if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
-            return( ret );
+        if ((ret = mbedtls_ssl_write_record(ssl, force_flush)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_record", ret);
+            return ret;
         }
     }
 
-    if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
-        return( ret );
-
-    /* Update state and set timer */
-    if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
-        ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
-    else
-    {
-        ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;
-        mbedtls_ssl_set_timer( ssl, ssl->handshake->retransmit_timeout );
+    if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) {
+        return ret;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_flight_transmit" ) );
+    /* Update state and set timer */
+    if (mbedtls_ssl_is_handshake_over(ssl) == 1) {
+        ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
+    } else {
+        ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;
+        mbedtls_ssl_set_timer(ssl, ssl->handshake->retransmit_timeout);
+    }
 
-    return( 0 );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= mbedtls_ssl_flight_transmit"));
+
+    return 0;
 }
 
 /*
  * To be called when the last message of an incoming flight is received.
  */
-void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl )
+void mbedtls_ssl_recv_flight_completed(mbedtls_ssl_context *ssl)
 {
     /* We won't need to resend that one any more */
-    mbedtls_ssl_flight_free( ssl->handshake->flight );
+    mbedtls_ssl_flight_free(ssl->handshake->flight);
     ssl->handshake->flight = NULL;
     ssl->handshake->cur_msg = NULL;
 
@@ -2475,41 +2469,57 @@
     ssl->handshake->buffering.seen_ccs = 0;
 
     /* Clear future message buffering structure. */
-    mbedtls_ssl_buffering_free( ssl );
+    mbedtls_ssl_buffering_free(ssl);
 
     /* Cancel timer */
-    mbedtls_ssl_set_timer( ssl, 0 );
+    mbedtls_ssl_set_timer(ssl, 0);
 
-    if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
-        ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED )
-    {
+    if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+        ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED) {
         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
-    }
-    else
+    } else {
         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING;
+    }
 }
 
 /*
  * To be called when the last message of an outgoing flight is send.
  */
-void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl )
+void mbedtls_ssl_send_flight_completed(mbedtls_ssl_context *ssl)
 {
-    ssl_reset_retransmit_timeout( ssl );
-    mbedtls_ssl_set_timer( ssl, ssl->handshake->retransmit_timeout );
+    ssl_reset_retransmit_timeout(ssl);
+    mbedtls_ssl_set_timer(ssl, ssl->handshake->retransmit_timeout);
 
-    if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
-        ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED )
-    {
+    if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+        ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED) {
         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
-    }
-    else
+    } else {
         ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;
+    }
 }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
 /*
  * Handshake layer functions
  */
+int mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned hs_type,
+                                    unsigned char **buf, size_t *buf_len)
+{
+    /*
+     * Reserve 4 bytes for handshake header. ( Section 4,RFC 8446 )
+     *    ...
+     *    HandshakeType msg_type;
+     *    uint24 length;
+     *    ...
+     */
+    *buf = ssl->out_msg + 4;
+    *buf_len = MBEDTLS_SSL_OUT_CONTENT_LEN - 4;
+
+    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = hs_type;
+
+    return 0;
+}
 
 /*
  * Write (DTLS: or queue) current handshake (including CCS) message.
@@ -2533,49 +2543,40 @@
  *      (including handshake headers but excluding record headers)
  *   - ssl->out_msg: the record contents (handshake headers + content)
  */
-int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_write_handshake_msg_ext(mbedtls_ssl_context *ssl,
+                                        int update_checksum,
+                                        int force_flush)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const size_t hs_len = ssl->out_msglen - 4;
     const unsigned char hs_type = ssl->out_msg[0];
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write handshake message" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write handshake message"));
 
     /*
      * Sanity checks
      */
-    if( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE          &&
-        ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
-    {
-        /* In SSLv3, the client might send a NoCertificate alert. */
-#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C)
-        if( ! ( ssl->minor_ver      == MBEDTLS_SSL_MINOR_VERSION_0 &&
-                ssl->out_msgtype    == MBEDTLS_SSL_MSG_ALERT       &&
-                ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) )
-#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-        }
+    if (ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE          &&
+        ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
     /* Whenever we send anything different from a
      * HelloRequest we should be in a handshake - double check. */
-    if( ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
-            hs_type          == MBEDTLS_SSL_HS_HELLO_REQUEST ) &&
-        ssl->handshake == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    if (!(ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+          hs_type          == MBEDTLS_SSL_HS_HELLO_REQUEST) &&
+        ssl->handshake == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
         ssl->handshake != NULL &&
-        ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 #endif
 
@@ -2587,24 +2588,22 @@
      *
      * Note: We deliberately do not check for the MTU or MFL here.
      */
-    if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: "
-                                    "size %" MBEDTLS_PRINTF_SIZET
-                                    ", maximum %" MBEDTLS_PRINTF_SIZET,
-                                    ssl->out_msglen,
-                                    (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    if (ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Record too large: "
+                                  "size %" MBEDTLS_PRINTF_SIZET
+                                  ", maximum %" MBEDTLS_PRINTF_SIZET,
+                                  ssl->out_msglen,
+                                  (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
     /*
      * Fill handshake headers
      */
-    if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
-    {
-        ssl->out_msg[1] = MBEDTLS_BYTE_2( hs_len );
-        ssl->out_msg[2] = MBEDTLS_BYTE_1( hs_len );
-        ssl->out_msg[3] = MBEDTLS_BYTE_0( hs_len );
+    if (ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) {
+        ssl->out_msg[1] = MBEDTLS_BYTE_2(hs_len);
+        ssl->out_msg[2] = MBEDTLS_BYTE_1(hs_len);
+        ssl->out_msg[3] = MBEDTLS_BYTE_0(hs_len);
 
         /*
          * DTLS has additional fields in the Handshake layer,
@@ -2614,70 +2613,84 @@
          *      uint24 fragment_length;
          */
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-        if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-        {
+        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
             /* Make room for the additional DTLS fields */
-            if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: "
-                              "size %" MBEDTLS_PRINTF_SIZET ", maximum %" MBEDTLS_PRINTF_SIZET,
-                               hs_len,
-                               (size_t) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) );
-                return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+            if (MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS handshake message too large: "
+                                          "size %" MBEDTLS_PRINTF_SIZET ", maximum %"
+                                          MBEDTLS_PRINTF_SIZET,
+                                          hs_len,
+                                          (size_t) (MBEDTLS_SSL_OUT_CONTENT_LEN - 12)));
+                return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
             }
 
-            memmove( ssl->out_msg + 12, ssl->out_msg + 4, hs_len );
+            memmove(ssl->out_msg + 12, ssl->out_msg + 4, hs_len);
             ssl->out_msglen += 8;
 
             /* Write message_seq and update it, except for HelloRequest */
-            if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
-            {
-                MBEDTLS_PUT_UINT16_BE( ssl->handshake->out_msg_seq, ssl->out_msg, 4 );
-                ++( ssl->handshake->out_msg_seq );
-            }
-            else
-            {
+            if (hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST) {
+                MBEDTLS_PUT_UINT16_BE(ssl->handshake->out_msg_seq, ssl->out_msg, 4);
+                ++(ssl->handshake->out_msg_seq);
+            } else {
                 ssl->out_msg[4] = 0;
                 ssl->out_msg[5] = 0;
             }
 
             /* Handshake hashes are computed without fragmentation,
              * so set frag_offset = 0 and frag_len = hs_len for now */
-            memset( ssl->out_msg + 6, 0x00, 3 );
-            memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 );
+            memset(ssl->out_msg + 6, 0x00, 3);
+            memcpy(ssl->out_msg + 9, ssl->out_msg + 1, 3);
         }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
         /* Update running hashes of handshake messages seen */
-        if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
-            ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen );
+        if (hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST && update_checksum != 0) {
+            ret = ssl->handshake->update_checksum(ssl, ssl->out_msg,
+                                                  ssl->out_msglen);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret);
+                return ret;
+            }
+        }
     }
 
     /* Either send now, or just save to be sent (and resent) later */
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
-            hs_type          == MBEDTLS_SSL_HS_HELLO_REQUEST ) )
-    {
-        if( ( ret = ssl_flight_append( ssl ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret );
-            return( ret );
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        !(ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+          hs_type          == MBEDTLS_SSL_HS_HELLO_REQUEST)) {
+        if ((ret = ssl_flight_append(ssl)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "ssl_flight_append", ret);
+            return ret;
         }
-    }
-    else
+    } else
 #endif
     {
-        if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret );
-            return( ret );
+        if ((ret = mbedtls_ssl_write_record(ssl, force_flush)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_record", ret);
+            return ret;
         }
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write handshake message" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write handshake message"));
 
-    return( 0 );
+    return 0;
+}
+
+int mbedtls_ssl_finish_handshake_msg(mbedtls_ssl_context *ssl,
+                                     size_t buf_len, size_t msg_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t msg_with_header_len;
+    ((void) buf_len);
+
+    /* Add reserved 4 bytes for handshake header */
+    msg_with_header_len = msg_len + 4;
+    ssl->out_msglen = msg_with_header_len;
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_handshake_msg_ext(ssl, 0, 0));
+
+cleanup:
+    return ret;
 }
 
 /*
@@ -2692,46 +2705,15 @@
  *  - ssl->out_msglen: length of the record content (excl headers)
  *  - ssl->out_msg: record content
  */
-int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush )
+int mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, int force_flush)
 {
     int ret, done = 0;
     size_t len = ssl->out_msglen;
-    uint8_t flush = force_flush;
+    int flush = force_flush;
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write record"));
 
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-    if( ssl->transform_out != NULL &&
-        ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE )
-    {
-        if( ( ret = ssl_compress_buf( ssl ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compress_buf", ret );
-            return( ret );
-        }
-
-        len = ssl->out_msglen;
-    }
-#endif /*MBEDTLS_ZLIB_SUPPORT */
-
-#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
-    if( mbedtls_ssl_hw_record_write != NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_write()" ) );
-
-        ret = mbedtls_ssl_hw_record_write( ssl );
-        if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_write", ret );
-            return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-        }
-
-        if( ret == 0 )
-            done = 1;
-    }
-#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
-    if( !done )
-    {
+    if (!done) {
         unsigned i;
         size_t protected_record_size;
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
@@ -2741,25 +2723,30 @@
 #endif
         /* Skip writing the record content type to after the encryption,
          * as it may change when using the CID extension. */
+        mbedtls_ssl_protocol_version tls_ver = ssl->tls_version;
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        /* TLS 1.3 still uses the TLS 1.2 version identifier
+         * for backwards compatibility. */
+        if (tls_ver == MBEDTLS_SSL_VERSION_TLS1_3) {
+            tls_ver = MBEDTLS_SSL_VERSION_TLS1_2;
+        }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+        mbedtls_ssl_write_version(ssl->out_hdr + 1, ssl->conf->transport,
+                                  tls_ver);
 
-        mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
-                           ssl->conf->transport, ssl->out_hdr + 1 );
+        memcpy(ssl->out_ctr, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN);
+        MBEDTLS_PUT_UINT16_BE(len, ssl->out_len, 0);
 
-        memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 );
-        MBEDTLS_PUT_UINT16_BE( len, ssl->out_len, 0);
-
-        if( ssl->transform_out != NULL )
-        {
+        if (ssl->transform_out != NULL) {
             mbedtls_record rec;
 
             rec.buf         = ssl->out_iv;
-            rec.buf_len     = out_buf_len - ( ssl->out_iv - ssl->out_buf );
+            rec.buf_len     = out_buf_len - (ssl->out_iv - ssl->out_buf);
             rec.data_len    = ssl->out_msglen;
             rec.data_offset = ssl->out_msg - rec.buf;
 
-            memcpy( &rec.ctr[0], ssl->out_ctr, 8 );
-            mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
-                                       ssl->conf->transport, rec.ver );
+            memcpy(&rec.ctr[0], ssl->out_ctr, sizeof(rec.ctr));
+            mbedtls_ssl_write_version(rec.ver, ssl->conf->transport, tls_ver);
             rec.type = ssl->out_msgtype;
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
@@ -2767,43 +2754,40 @@
             rec.cid_len = 0;
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
-            if( ( ret = mbedtls_ssl_encrypt_buf( ssl, ssl->transform_out, &rec,
-                                         ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret );
-                return( ret );
+            if ((ret = mbedtls_ssl_encrypt_buf(ssl, ssl->transform_out, &rec,
+                                               ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "ssl_encrypt_buf", ret);
+                return ret;
             }
 
-            if( rec.data_offset != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-                return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+            if (rec.data_offset != 0) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+                return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
             }
 
             /* Update the record content type and CID. */
             ssl->out_msgtype = rec.type;
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID )
-            memcpy( ssl->out_cid, rec.cid, rec.cid_len );
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+            memcpy(ssl->out_cid, rec.cid, rec.cid_len);
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
             ssl->out_msglen = len = rec.data_len;
-            MBEDTLS_PUT_UINT16_BE( rec.data_len, ssl->out_len, 0 );
+            MBEDTLS_PUT_UINT16_BE(rec.data_len, ssl->out_len, 0);
         }
 
-        protected_record_size = len + mbedtls_ssl_out_hdr_len( ssl );
+        protected_record_size = len + mbedtls_ssl_out_hdr_len(ssl);
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
         /* In case of DTLS, double-check that we don't exceed
          * the remaining space in the datagram. */
-        if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-        {
-            ret = ssl_get_remaining_space_in_datagram( ssl );
-            if( ret < 0 )
-                return( ret );
+        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+            ret = ssl_get_remaining_space_in_datagram(ssl);
+            if (ret < 0) {
+                return ret;
+            }
 
-            if( protected_record_size > (size_t) ret )
-            {
+            if (protected_record_size > (size_t) ret) {
                 /* Should never happen */
-                return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+                return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
             }
         }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
@@ -2811,133 +2795,131 @@
         /* Now write the potentially updated record content type. */
         ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
 
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %u, "
-                                    "version = [%u:%u], msglen = %" MBEDTLS_PRINTF_SIZET,
-                                    ssl->out_hdr[0], ssl->out_hdr[1],
-                                    ssl->out_hdr[2], len ) );
+        MBEDTLS_SSL_DEBUG_MSG(3, ("output record: msgtype = %u, "
+                                  "version = [%u:%u], msglen = %" MBEDTLS_PRINTF_SIZET,
+                                  ssl->out_hdr[0], ssl->out_hdr[1],
+                                  ssl->out_hdr[2], len));
 
-        MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network",
-                               ssl->out_hdr, protected_record_size );
+        MBEDTLS_SSL_DEBUG_BUF(4, "output record sent to network",
+                              ssl->out_hdr, protected_record_size);
 
         ssl->out_left += protected_record_size;
         ssl->out_hdr  += protected_record_size;
-        mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out );
+        mbedtls_ssl_update_out_pointers(ssl, ssl->transform_out);
 
-        for( i = 8; i > mbedtls_ssl_ep_len( ssl ); i-- )
-            if( ++ssl->cur_out_ctr[i - 1] != 0 )
+        for (i = 8; i > mbedtls_ssl_ep_len(ssl); i--) {
+            if (++ssl->cur_out_ctr[i - 1] != 0) {
                 break;
+            }
+        }
 
-        /* The loop goes to its end iff the counter is wrapping */
-        if( i == mbedtls_ssl_ep_len( ssl ) )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) );
-            return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
+        /* The loop goes to its end if the counter is wrapping */
+        if (i == mbedtls_ssl_ep_len(ssl)) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("outgoing message counter would wrap"));
+            return MBEDTLS_ERR_SSL_COUNTER_WRAPPING;
         }
     }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        flush == SSL_DONT_FORCE_FLUSH )
-    {
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        flush == SSL_DONT_FORCE_FLUSH) {
         size_t remaining;
-        ret = ssl_get_remaining_payload_in_datagram( ssl );
-        if( ret < 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram",
-                                   ret );
-            return( ret );
+        ret = ssl_get_remaining_payload_in_datagram(ssl);
+        if (ret < 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "ssl_get_remaining_payload_in_datagram",
+                                  ret);
+            return ret;
         }
 
         remaining = (size_t) ret;
-        if( remaining == 0 )
-        {
+        if (remaining == 0) {
             flush = SSL_FORCE_FLUSH;
-        }
-        else
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) );
+        } else {
+            MBEDTLS_SSL_DEBUG_MSG(2,
+                                  ("Still %u bytes available in current datagram",
+                                   (unsigned) remaining));
         }
     }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-    if( ( flush == SSL_FORCE_FLUSH ) &&
-        ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret );
-        return( ret );
+    if ((flush == SSL_FORCE_FLUSH) &&
+        (ret = mbedtls_ssl_flush_output(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flush_output", ret);
+        return ret;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write record"));
 
-    return( 0 );
+    return 0;
 }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl )
+static int ssl_hs_is_proper_fragment(mbedtls_ssl_context *ssl)
 {
-    if( ssl->in_msglen < ssl->in_hslen ||
-        memcmp( ssl->in_msg + 6, "\0\0\0",        3 ) != 0 ||
-        memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 )
-    {
-        return( 1 );
+    if (ssl->in_msglen < ssl->in_hslen ||
+        memcmp(ssl->in_msg + 6, "\0\0\0",        3) != 0 ||
+        memcmp(ssl->in_msg + 9, ssl->in_msg + 1, 3) != 0) {
+        return 1;
     }
-    return( 0 );
+    return 0;
 }
 
-static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl )
+static uint32_t ssl_get_hs_frag_len(mbedtls_ssl_context const *ssl)
 {
-    return( ( ssl->in_msg[9] << 16  ) |
-            ( ssl->in_msg[10] << 8  ) |
-              ssl->in_msg[11] );
+    return (ssl->in_msg[9] << 16) |
+           (ssl->in_msg[10] << 8) |
+           ssl->in_msg[11];
 }
 
-static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl )
+static uint32_t ssl_get_hs_frag_off(mbedtls_ssl_context const *ssl)
 {
-    return( ( ssl->in_msg[6] << 16 ) |
-            ( ssl->in_msg[7] << 8  ) |
-              ssl->in_msg[8] );
+    return (ssl->in_msg[6] << 16) |
+           (ssl->in_msg[7] << 8) |
+           ssl->in_msg[8];
 }
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_check_hs_header( mbedtls_ssl_context const *ssl )
+static int ssl_check_hs_header(mbedtls_ssl_context const *ssl)
 {
     uint32_t msg_len, frag_off, frag_len;
 
-    msg_len  = ssl_get_hs_total_len( ssl );
-    frag_off = ssl_get_hs_frag_off( ssl );
-    frag_len = ssl_get_hs_frag_len( ssl );
+    msg_len  = ssl_get_hs_total_len(ssl);
+    frag_off = ssl_get_hs_frag_off(ssl);
+    frag_len = ssl_get_hs_frag_len(ssl);
 
-    if( frag_off > msg_len )
-        return( -1 );
+    if (frag_off > msg_len) {
+        return -1;
+    }
 
-    if( frag_len > msg_len - frag_off )
-        return( -1 );
+    if (frag_len > msg_len - frag_off) {
+        return -1;
+    }
 
-    if( frag_len + 12 > ssl->in_msglen )
-        return( -1 );
+    if (frag_len + 12 > ssl->in_msglen) {
+        return -1;
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Mark bits in bitmask (used for DTLS HS reassembly)
  */
-static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len )
+static void ssl_bitmask_set(unsigned char *mask, size_t offset, size_t len)
 {
     unsigned int start_bits, end_bits;
 
-    start_bits = 8 - ( offset % 8 );
-    if( start_bits != 8 )
-    {
+    start_bits = 8 - (offset % 8);
+    if (start_bits != 8) {
         size_t first_byte_idx = offset / 8;
 
         /* Special case */
-        if( len <= start_bits )
-        {
-            for( ; len != 0; len-- )
-                mask[first_byte_idx] |= 1 << ( start_bits - len );
+        if (len <= start_bits) {
+            for (; len != 0; len--) {
+                mask[first_byte_idx] |= 1 << (start_bits - len);
+            }
 
             /* Avoid potential issues with offset or len becoming invalid */
             return;
@@ -2946,134 +2928,134 @@
         offset += start_bits; /* Now offset % 8 == 0 */
         len -= start_bits;
 
-        for( ; start_bits != 0; start_bits-- )
-            mask[first_byte_idx] |= 1 << ( start_bits - 1 );
+        for (; start_bits != 0; start_bits--) {
+            mask[first_byte_idx] |= 1 << (start_bits - 1);
+        }
     }
 
     end_bits = len % 8;
-    if( end_bits != 0 )
-    {
-        size_t last_byte_idx = ( offset + len ) / 8;
+    if (end_bits != 0) {
+        size_t last_byte_idx = (offset + len) / 8;
 
         len -= end_bits; /* Now len % 8 == 0 */
 
-        for( ; end_bits != 0; end_bits-- )
-            mask[last_byte_idx] |= 1 << ( 8 - end_bits );
+        for (; end_bits != 0; end_bits--) {
+            mask[last_byte_idx] |= 1 << (8 - end_bits);
+        }
     }
 
-    memset( mask + offset / 8, 0xFF, len / 8 );
+    memset(mask + offset / 8, 0xFF, len / 8);
 }
 
 /*
  * Check that bitmask is full
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_bitmask_check( unsigned char *mask, size_t len )
+static int ssl_bitmask_check(unsigned char *mask, size_t len)
 {
     size_t i;
 
-    for( i = 0; i < len / 8; i++ )
-        if( mask[i] != 0xFF )
-            return( -1 );
+    for (i = 0; i < len / 8; i++) {
+        if (mask[i] != 0xFF) {
+            return -1;
+        }
+    }
 
-    for( i = 0; i < len % 8; i++ )
-        if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 )
-            return( -1 );
+    for (i = 0; i < len % 8; i++) {
+        if ((mask[len / 8] & (1 << (7 - i))) == 0) {
+            return -1;
+        }
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /* msg_len does not include the handshake header */
-static size_t ssl_get_reassembly_buffer_size( size_t msg_len,
-                                              unsigned add_bitmap )
+static size_t ssl_get_reassembly_buffer_size(size_t msg_len,
+                                             unsigned add_bitmap)
 {
     size_t alloc_len;
 
     alloc_len  = 12;                                 /* Handshake header */
     alloc_len += msg_len;                            /* Content buffer   */
 
-    if( add_bitmap )
-        alloc_len += msg_len / 8 + ( msg_len % 8 != 0 ); /* Bitmap       */
+    if (add_bitmap) {
+        alloc_len += msg_len / 8 + (msg_len % 8 != 0);   /* Bitmap       */
 
-    return( alloc_len );
+    }
+    return alloc_len;
 }
 
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl )
+static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl)
 {
-    return( ( ssl->in_msg[1] << 16 ) |
-            ( ssl->in_msg[2] << 8  ) |
-              ssl->in_msg[3] );
+    return (ssl->in_msg[1] << 16) |
+           (ssl->in_msg[2] << 8) |
+           ssl->in_msg[3];
 }
 
-int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
 {
-    if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %" MBEDTLS_PRINTF_SIZET,
-                            ssl->in_msglen ) );
-        return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+    if (ssl->in_msglen < mbedtls_ssl_hs_hdr_len(ssl)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("handshake message too short: %" MBEDTLS_PRINTF_SIZET,
+                                  ssl->in_msglen));
+        return MBEDTLS_ERR_SSL_INVALID_RECORD;
     }
 
-    ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl );
+    ssl->in_hslen = mbedtls_ssl_hs_hdr_len(ssl) + ssl_get_hs_total_len(ssl);
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
-                        " %" MBEDTLS_PRINTF_SIZET ", type = %u, hslen = %" MBEDTLS_PRINTF_SIZET,
-                        ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) );
+    MBEDTLS_SSL_DEBUG_MSG(3, ("handshake message: msglen ="
+                              " %" MBEDTLS_PRINTF_SIZET ", type = %u, hslen = %"
+                              MBEDTLS_PRINTF_SIZET,
+                              ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen));
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
+        unsigned int recv_msg_seq = (ssl->in_msg[4] << 8) | ssl->in_msg[5];
 
-        if( ssl_check_hs_header( ssl ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid handshake header" ) );
-            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+        if (ssl_check_hs_header(ssl) != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("invalid handshake header"));
+            return MBEDTLS_ERR_SSL_INVALID_RECORD;
         }
 
-        if( ssl->handshake != NULL &&
-            ( ( ssl->state   != MBEDTLS_SSL_HANDSHAKE_OVER &&
-                recv_msg_seq != ssl->handshake->in_msg_seq ) ||
-              ( ssl->state  == MBEDTLS_SSL_HANDSHAKE_OVER &&
-                ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) )
-        {
-            if( recv_msg_seq > ssl->handshake->in_msg_seq )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 2, ( "received future handshake message of sequence number %u (next %u)",
-                                            recv_msg_seq,
-                                            ssl->handshake->in_msg_seq ) );
-                return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
+        if (ssl->handshake != NULL &&
+            ((mbedtls_ssl_is_handshake_over(ssl) == 0 &&
+              recv_msg_seq != ssl->handshake->in_msg_seq) ||
+             (mbedtls_ssl_is_handshake_over(ssl) == 1 &&
+              ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO))) {
+            if (recv_msg_seq > ssl->handshake->in_msg_seq) {
+                MBEDTLS_SSL_DEBUG_MSG(2,
+                                      (
+                                          "received future handshake message of sequence number %u (next %u)",
+                                          recv_msg_seq,
+                                          ssl->handshake->in_msg_seq));
+                return MBEDTLS_ERR_SSL_EARLY_MESSAGE;
             }
 
             /* Retransmit only on last message from previous flight, to avoid
              * too many retransmissions.
              * Besides, No sane server ever retransmits HelloVerifyRequest */
-            if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 &&
-                ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, "
-                                    "message_seq = %u, start_of_flight = %u",
-                                    recv_msg_seq,
-                                    ssl->handshake->in_flight_start_seq ) );
+            if (recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 &&
+                ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST) {
+                MBEDTLS_SSL_DEBUG_MSG(2, ("received message from last flight, "
+                                          "message_seq = %u, start_of_flight = %u",
+                                          recv_msg_seq,
+                                          ssl->handshake->in_flight_start_seq));
 
-                if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
-                {
-                    MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret );
-                    return( ret );
+                if ((ret = mbedtls_ssl_resend(ssl)) != 0) {
+                    MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_resend", ret);
+                    return ret;
                 }
-            }
-            else
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: "
-                                    "message_seq = %u, expected = %u",
-                                    recv_msg_seq,
-                                    ssl->handshake->in_msg_seq ) );
+            } else {
+                MBEDTLS_SSL_DEBUG_MSG(2, ("dropping out-of-sequence message: "
+                                          "message_seq = %u, expected = %u",
+                                          recv_msg_seq,
+                                          ssl->handshake->in_msg_seq));
             }
 
-            return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
+            return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
         }
         /* Wait until message completion to increment in_msg_seq */
 
@@ -3081,38 +3063,38 @@
          * messages; the commonality is that both handshake fragments and
          * future messages cannot be forwarded immediately to the
          * handshake logic layer. */
-        if( ssl_hs_is_proper_fragment( ssl ) == 1 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) );
-            return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
+        if (ssl_hs_is_proper_fragment(ssl) == 1) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("found fragmented DTLS handshake message"));
+            return MBEDTLS_ERR_SSL_EARLY_MESSAGE;
         }
-    }
-    else
+    } else
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
     /* With TLS we don't handle fragmentation (for now) */
-    if( ssl->in_msglen < ssl->in_hslen )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) );
-        return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+    if (ssl->in_msglen < ssl->in_hslen) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("TLS handshake fragmentation not supported"));
+        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
     }
 
-    return( 0 );
+    return 0;
 }
 
-void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl)
 {
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
 
-    if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL )
-    {
-        ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
+    if (mbedtls_ssl_is_handshake_over(ssl) == 0 && hs != NULL) {
+        ret = ssl->handshake->update_checksum(ssl, ssl->in_msg, ssl->in_hslen);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret);
+            return ret;
+        }
     }
 
     /* Handshake message is complete, increment counter */
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ssl->handshake != NULL )
-    {
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        ssl->handshake != NULL) {
         unsigned offset;
         mbedtls_ssl_hs_buffer *hs_buf;
 
@@ -3124,20 +3106,20 @@
          */
 
         /* Free first entry */
-        ssl_buffering_free_slot( ssl, 0 );
+        ssl_buffering_free_slot(ssl, 0);
 
         /* Shift all other entries */
-        for( offset = 0, hs_buf = &hs->buffering.hs[0];
+        for (offset = 0, hs_buf = &hs->buffering.hs[0];
              offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS;
-             offset++, hs_buf++ )
-        {
+             offset++, hs_buf++) {
             *hs_buf = *(hs_buf + 1);
         }
 
         /* Create a fresh last entry */
-        memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
+        memset(hs_buf, 0, sizeof(mbedtls_ssl_hs_buffer));
     }
 #endif
+    return 0;
 }
 
 /*
@@ -3151,24 +3133,24 @@
  * not seen yet).
  */
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-void mbedtls_ssl_dtls_replay_reset( mbedtls_ssl_context *ssl )
+void mbedtls_ssl_dtls_replay_reset(mbedtls_ssl_context *ssl)
 {
     ssl->in_window_top = 0;
     ssl->in_window = 0;
 }
 
-static inline uint64_t ssl_load_six_bytes( unsigned char *buf )
+static inline uint64_t ssl_load_six_bytes(unsigned char *buf)
 {
-    return( ( (uint64_t) buf[0] << 40 ) |
-            ( (uint64_t) buf[1] << 32 ) |
-            ( (uint64_t) buf[2] << 24 ) |
-            ( (uint64_t) buf[3] << 16 ) |
-            ( (uint64_t) buf[4] <<  8 ) |
-            ( (uint64_t) buf[5]       ) );
+    return ((uint64_t) buf[0] << 40) |
+           ((uint64_t) buf[1] << 32) |
+           ((uint64_t) buf[2] << 24) |
+           ((uint64_t) buf[3] << 16) |
+           ((uint64_t) buf[4] <<  8) |
+           ((uint64_t) buf[5]);
 }
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int mbedtls_ssl_dtls_record_replay_check( mbedtls_ssl_context *ssl, uint8_t *record_in_ctr )
+static int mbedtls_ssl_dtls_record_replay_check(mbedtls_ssl_context *ssl, uint8_t *record_in_ctr)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *original_in_ctr;
@@ -3179,7 +3161,7 @@
     // use counter from record
     ssl->in_ctr = record_in_ctr;
 
-    ret = mbedtls_ssl_dtls_replay_check( (mbedtls_ssl_context const *) ssl );
+    ret = mbedtls_ssl_dtls_replay_check((mbedtls_ssl_context const *) ssl);
 
     // restore the counter
     ssl->in_ctr = original_in_ctr;
@@ -3190,60 +3172,62 @@
 /*
  * Return 0 if sequence number is acceptable, -1 otherwise
  */
-int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl )
+int mbedtls_ssl_dtls_replay_check(mbedtls_ssl_context const *ssl)
 {
-    uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 );
+    uint64_t rec_seqnum = ssl_load_six_bytes(ssl->in_ctr + 2);
     uint64_t bit;
 
-    if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED )
-        return( 0 );
+    if (ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED) {
+        return 0;
+    }
 
-    if( rec_seqnum > ssl->in_window_top )
-        return( 0 );
+    if (rec_seqnum > ssl->in_window_top) {
+        return 0;
+    }
 
     bit = ssl->in_window_top - rec_seqnum;
 
-    if( bit >= 64 )
-        return( -1 );
+    if (bit >= 64) {
+        return -1;
+    }
 
-    if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 )
-        return( -1 );
+    if ((ssl->in_window & ((uint64_t) 1 << bit)) != 0) {
+        return -1;
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Update replay window on new validated record
  */
-void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl )
+void mbedtls_ssl_dtls_replay_update(mbedtls_ssl_context *ssl)
 {
-    uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 );
+    uint64_t rec_seqnum = ssl_load_six_bytes(ssl->in_ctr + 2);
 
-    if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED )
+    if (ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED) {
         return;
+    }
 
-    if( rec_seqnum > ssl->in_window_top )
-    {
+    if (rec_seqnum > ssl->in_window_top) {
         /* Update window_top and the contents of the window */
         uint64_t shift = rec_seqnum - ssl->in_window_top;
 
-        if( shift >= 64 )
+        if (shift >= 64) {
             ssl->in_window = 1;
-        else
-        {
+        } else {
             ssl->in_window <<= shift;
             ssl->in_window |= 1;
         }
 
         ssl->in_window_top = rec_seqnum;
-    }
-    else
-    {
+    } else {
         /* Mark that number as seen in the current window */
         uint64_t bit = ssl->in_window_top - rec_seqnum;
 
-        if( bit < 64 ) /* Always true, but be extra sure */
+        if (bit < 64) { /* Always true, but be extra sure */
             ssl->in_window |= (uint64_t) 1 << bit;
+        }
     }
 }
 #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
@@ -3263,12 +3247,12 @@
 MBEDTLS_CHECK_RETURN_CRITICAL
 MBEDTLS_STATIC_TESTABLE
 int mbedtls_ssl_check_dtls_clihlo_cookie(
-                           mbedtls_ssl_context *ssl,
-                           const unsigned char *cli_id, size_t cli_id_len,
-                           const unsigned char *in, size_t in_len,
-                           unsigned char *obuf, size_t buf_len, size_t *olen )
+    mbedtls_ssl_context *ssl,
+    const unsigned char *cli_id, size_t cli_id_len,
+    const unsigned char *in, size_t in_len,
+    unsigned char *obuf, size_t buf_len, size_t *olen)
 {
-    size_t sid_len, cookie_len;
+    size_t sid_len, cookie_len, epoch, fragment_offset;
     unsigned char *p;
 
     /*
@@ -3297,54 +3281,51 @@
      *
      * Minimum length is 61 bytes.
      */
-    MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: in_len=%u",
-                                (unsigned) in_len ) );
-    MBEDTLS_SSL_DEBUG_BUF( 4, "cli_id", cli_id, cli_id_len );
-    if( in_len < 61 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: record too short" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: in_len=%u",
+                              (unsigned) in_len));
+    MBEDTLS_SSL_DEBUG_BUF(4, "cli_id", cli_id, cli_id_len);
+    if (in_len < 61) {
+        MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: record too short"));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
     }
-    if( in[0] != MBEDTLS_SSL_MSG_HANDSHAKE ||
-        in[3] != 0 || in[4] != 0 ||
-        in[19] != 0 || in[20] != 0 || in[21] != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: not a good ClientHello" ) );
-        MBEDTLS_SSL_DEBUG_MSG( 4, ( "    type=%u epoch=%u fragment_offset=%u",
-                                    in[0],
-                                    (unsigned) in[3] << 8 | in[4],
-                                    (unsigned) in[19] << 16 | in[20] << 8 | in[21] ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+
+    epoch = MBEDTLS_GET_UINT16_BE(in, 3);
+    fragment_offset = MBEDTLS_GET_UINT24_BE(in, 19);
+
+    if (in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || epoch != 0 ||
+        fragment_offset != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: not a good ClientHello"));
+        MBEDTLS_SSL_DEBUG_MSG(4, ("    type=%u epoch=%u fragment_offset=%u",
+                                  in[0], (unsigned) epoch,
+                                  (unsigned) fragment_offset));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
     }
 
     sid_len = in[59];
-    if( 59 + 1 + sid_len + 1 > in_len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: sid_len=%u > %u",
-                                    (unsigned) sid_len,
-                                    (unsigned) in_len - 61 ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    if (59 + 1 + sid_len + 1 > in_len) {
+        MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: sid_len=%u > %u",
+                                  (unsigned) sid_len,
+                                  (unsigned) in_len - 61));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
     }
-    MBEDTLS_SSL_DEBUG_BUF( 4, "sid received from network",
-                           in + 60, sid_len );
+    MBEDTLS_SSL_DEBUG_BUF(4, "sid received from network",
+                          in + 60, sid_len);
 
     cookie_len = in[60 + sid_len];
-    if( 59 + 1 + sid_len + 1 + cookie_len > in_len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: cookie_len=%u > %u",
-                                    (unsigned) cookie_len,
-                                    (unsigned) ( in_len - sid_len - 61 ) ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    if (59 + 1 + sid_len + 1 + cookie_len > in_len) {
+        MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: cookie_len=%u > %u",
+                                  (unsigned) cookie_len,
+                                  (unsigned) (in_len - sid_len - 61)));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
     }
 
-    MBEDTLS_SSL_DEBUG_BUF( 4, "cookie received from network",
-                           in + sid_len + 61, cookie_len );
-    if( ssl->conf->f_cookie_check( ssl->conf->p_cookie,
-                                   in + sid_len + 61, cookie_len,
-                                   cli_id, cli_id_len ) == 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: valid" ) );
-        return( 0 );
+    MBEDTLS_SSL_DEBUG_BUF(4, "cookie received from network",
+                          in + sid_len + 61, cookie_len);
+    if (ssl->conf->f_cookie_check(ssl->conf->p_cookie,
+                                  in + sid_len + 61, cookie_len,
+                                  cli_id, cli_id_len) == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: valid"));
+        return 0;
     }
 
     /*
@@ -3367,36 +3348,36 @@
      *
      * Minimum length is 28.
      */
-    if( buf_len < 28 )
-        return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+    if (buf_len < 28) {
+        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+    }
 
     /* Copy most fields and adapt others */
-    memcpy( obuf, in, 25 );
+    memcpy(obuf, in, 25);
     obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST;
     obuf[25] = 0xfe;
     obuf[26] = 0xff;
 
     /* Generate and write actual cookie */
     p = obuf + 28;
-    if( ssl->conf->f_cookie_write( ssl->conf->p_cookie,
-                                   &p, obuf + buf_len,
-                                   cli_id, cli_id_len ) != 0 )
-    {
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    if (ssl->conf->f_cookie_write(ssl->conf->p_cookie,
+                                  &p, obuf + buf_len,
+                                  cli_id, cli_id_len) != 0) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
     *olen = p - obuf;
 
     /* Go back and fill length fields */
-    obuf[27] = (unsigned char)( *olen - 28 );
+    obuf[27] = (unsigned char) (*olen - 28);
 
-    obuf[14] = obuf[22] = MBEDTLS_BYTE_2( *olen - 25 );
-    obuf[15] = obuf[23] = MBEDTLS_BYTE_1( *olen - 25 );
-    obuf[16] = obuf[24] = MBEDTLS_BYTE_0( *olen - 25 );
+    obuf[14] = obuf[22] = MBEDTLS_BYTE_2(*olen - 25);
+    obuf[15] = obuf[23] = MBEDTLS_BYTE_1(*olen - 25);
+    obuf[16] = obuf[24] = MBEDTLS_BYTE_0(*olen - 25);
 
-    MBEDTLS_PUT_UINT16_BE( *olen - 13, obuf, 11 );
+    MBEDTLS_PUT_UINT16_BE(*olen - 13, obuf, 11);
 
-    return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED );
+    return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED;
 }
 
 /*
@@ -3420,73 +3401,68 @@
  * errors, and is the right thing to do in both cases).
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
+static int ssl_handle_possible_reconnect(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
-    if( ssl->conf->f_cookie_write == NULL ||
-        ssl->conf->f_cookie_check == NULL )
-    {
+    if (ssl->conf->f_cookie_write == NULL ||
+        ssl->conf->f_cookie_check == NULL) {
         /* If we can't use cookies to verify reachability of the peer,
          * drop the record. */
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "no cookie callbacks, "
-                                    "can't check reconnect validity" ) );
-        return( 0 );
+        MBEDTLS_SSL_DEBUG_MSG(1, ("no cookie callbacks, "
+                                  "can't check reconnect validity"));
+        return 0;
     }
 
     ret = mbedtls_ssl_check_dtls_clihlo_cookie(
-            ssl,
-            ssl->cli_id, ssl->cli_id_len,
-            ssl->in_buf, ssl->in_left,
-            ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len );
+        ssl,
+        ssl->cli_id, ssl->cli_id_len,
+        ssl->in_buf, ssl->in_left,
+        ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len);
 
-    MBEDTLS_SSL_DEBUG_RET( 2, "mbedtls_ssl_check_dtls_clihlo_cookie", ret );
+    MBEDTLS_SSL_DEBUG_RET(2, "mbedtls_ssl_check_dtls_clihlo_cookie", ret);
 
-    if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
-    {
+    if (ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) {
         int send_ret;
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "sending HelloVerifyRequest" ) );
-        MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network",
-                                  ssl->out_buf, len );
+        MBEDTLS_SSL_DEBUG_MSG(1, ("sending HelloVerifyRequest"));
+        MBEDTLS_SSL_DEBUG_BUF(4, "output record sent to network",
+                              ssl->out_buf, len);
         /* Don't check write errors as we can't do anything here.
          * If the error is permanent we'll catch it later,
          * if it's not, then hopefully it'll work next time. */
-        send_ret = ssl->f_send( ssl->p_bio, ssl->out_buf, len );
-        MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", send_ret );
+        send_ret = ssl->f_send(ssl->p_bio, ssl->out_buf, len);
+        MBEDTLS_SSL_DEBUG_RET(2, "ssl->f_send", send_ret);
         (void) send_ret;
 
-        return( 0 );
+        return 0;
     }
 
-    if( ret == 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "cookie is valid, resetting context" ) );
-        if( ( ret = mbedtls_ssl_session_reset_int( ssl, 1 ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret );
-            return( ret );
+    if (ret == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("cookie is valid, resetting context"));
+        if ((ret = mbedtls_ssl_session_reset_int(ssl, 1)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "reset", ret);
+            return ret;
         }
 
-        return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT );
+        return MBEDTLS_ERR_SSL_CLIENT_RECONNECT;
     }
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_check_record_type( uint8_t record_type )
+static int ssl_check_record_type(uint8_t record_type)
 {
-    if( record_type != MBEDTLS_SSL_MSG_HANDSHAKE &&
+    if (record_type != MBEDTLS_SSL_MSG_HANDSHAKE &&
         record_type != MBEDTLS_SSL_MSG_ALERT &&
         record_type != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC &&
-        record_type != MBEDTLS_SSL_MSG_APPLICATION_DATA )
-    {
-        return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+        record_type != MBEDTLS_SSL_MSG_APPLICATION_DATA) {
+        return MBEDTLS_ERR_SSL_INVALID_RECORD;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -3509,12 +3485,12 @@
  * the first record from a datagram but are still waiting for the others.
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
-                                    unsigned char *buf,
-                                    size_t len,
-                                    mbedtls_record *rec )
+static int ssl_parse_record_header(mbedtls_ssl_context const *ssl,
+                                   unsigned char *buf,
+                                   size_t len,
+                                   mbedtls_record *rec)
 {
-    int major_ver, minor_ver;
+    mbedtls_ssl_protocol_version tls_version;
 
     size_t const rec_hdr_type_offset    = 0;
     size_t const rec_hdr_type_len       = 1;
@@ -3544,41 +3520,39 @@
      */
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
         rec_hdr_len_offset = rec_hdr_ctr_offset + rec_hdr_ctr_len;
-    }
-    else
+    } else
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
     {
         rec_hdr_len_offset = rec_hdr_version_offset + rec_hdr_version_len;
     }
 
-    if( len < rec_hdr_len_offset + rec_hdr_len_len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header of length %u",
-                 (unsigned) len,
-                 (unsigned)( rec_hdr_len_len + rec_hdr_len_len ) ) );
-        return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+    if (len < rec_hdr_len_offset + rec_hdr_len_len) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              (
+                                  "datagram of length %u too small to hold DTLS record header of length %u",
+                                  (unsigned) len,
+                                  (unsigned) (rec_hdr_len_len + rec_hdr_len_len)));
+        return MBEDTLS_ERR_SSL_INVALID_RECORD;
     }
 
     /*
      * Parse and validate record content type
      */
 
-    rec->type = buf[ rec_hdr_type_offset ];
+    rec->type = buf[rec_hdr_type_offset];
 
     /* Check record content type */
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
     rec->cid_len = 0;
 
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
         ssl->conf->cid_len != 0                                &&
-        rec->type == MBEDTLS_SSL_MSG_CID )
-    {
+        rec->type == MBEDTLS_SSL_MSG_CID) {
         /* Shift pointers to account for record header including CID
          * struct {
-         *   ContentType special_type = tls12_cid;
+         *   ContentType outer_type = tls12_cid;
          *   ProtocolVersion version;
          *   uint16 epoch;
          *   uint48 sequence_number;
@@ -3594,70 +3568,58 @@
         rec_hdr_cid_len = ssl->conf->cid_len;
         rec_hdr_len_offset += rec_hdr_cid_len;
 
-        if( len < rec_hdr_len_offset + rec_hdr_len_len )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header including CID, length %u",
-                (unsigned) len,
-                (unsigned)( rec_hdr_len_offset + rec_hdr_len_len ) ) );
-            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+        if (len < rec_hdr_len_offset + rec_hdr_len_len) {
+            MBEDTLS_SSL_DEBUG_MSG(1,
+                                  (
+                                      "datagram of length %u too small to hold DTLS record header including CID, length %u",
+                                      (unsigned) len,
+                                      (unsigned) (rec_hdr_len_offset + rec_hdr_len_len)));
+            return MBEDTLS_ERR_SSL_INVALID_RECORD;
         }
 
         /* configured CID len is guaranteed at most 255, see
          * MBEDTLS_SSL_CID_OUT_LEN_MAX in check_config.h */
         rec->cid_len = (uint8_t) rec_hdr_cid_len;
-        memcpy( rec->cid, buf + rec_hdr_cid_offset, rec_hdr_cid_len );
-    }
-    else
+        memcpy(rec->cid, buf + rec_hdr_cid_offset, rec_hdr_cid_len);
+    } else
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
     {
-        if( ssl_check_record_type( rec->type ) )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type %u",
-                                        (unsigned) rec->type ) );
-            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+        if (ssl_check_record_type(rec->type)) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("unknown record type %u",
+                                      (unsigned) rec->type));
+            return MBEDTLS_ERR_SSL_INVALID_RECORD;
         }
     }
 
     /*
      * Parse and validate record version
      */
-    rec->ver[0] = buf[ rec_hdr_version_offset + 0 ];
-    rec->ver[1] = buf[ rec_hdr_version_offset + 1 ];
-    mbedtls_ssl_read_version( &major_ver, &minor_ver,
-                              ssl->conf->transport,
-                              &rec->ver[0] );
+    rec->ver[0] = buf[rec_hdr_version_offset + 0];
+    rec->ver[1] = buf[rec_hdr_version_offset + 1];
+    tls_version = mbedtls_ssl_read_version(buf + rec_hdr_version_offset,
+                                           ssl->conf->transport);
 
-    if( major_ver != ssl->major_ver )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch: got %u, expected %u",
-                                    (unsigned) major_ver,
-                                    (unsigned) ssl->major_ver ) );
-        return( MBEDTLS_ERR_SSL_INVALID_RECORD );
-    }
+    if (tls_version > ssl->conf->max_tls_version) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("TLS version mismatch: got %u, expected max %u",
+                                  (unsigned) tls_version,
+                                  (unsigned) ssl->conf->max_tls_version));
 
-    if( minor_ver > ssl->conf->max_minor_ver )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch: got %u, expected max %u",
-                                    (unsigned) minor_ver,
-                                    (unsigned) ssl->conf->max_minor_ver ) );
-        return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+        return MBEDTLS_ERR_SSL_INVALID_RECORD;
     }
     /*
      * Parse/Copy record sequence number.
      */
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
         /* Copy explicit record sequence number from input buffer. */
-        memcpy( &rec->ctr[0], buf + rec_hdr_ctr_offset,
-                rec_hdr_ctr_len );
-    }
-    else
+        memcpy(&rec->ctr[0], buf + rec_hdr_ctr_offset,
+               rec_hdr_ctr_len);
+    } else
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
     {
         /* Copy implicit record sequence number from SSL context structure. */
-        memcpy( &rec->ctr[0], ssl->in_ctr, rec_hdr_ctr_len );
+        memcpy(&rec->ctr[0], ssl->in_ctr, rec_hdr_ctr_len);
     }
 
     /*
@@ -3665,20 +3627,20 @@
      */
 
     rec->data_offset = rec_hdr_len_offset + rec_hdr_len_len;
-    rec->data_len    = ( (size_t) buf[ rec_hdr_len_offset + 0 ] << 8 ) |
-                       ( (size_t) buf[ rec_hdr_len_offset + 1 ] << 0 );
-    MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", buf, rec->data_offset );
+    rec->data_len    = ((size_t) buf[rec_hdr_len_offset + 0] << 8) |
+                       ((size_t) buf[rec_hdr_len_offset + 1] << 0);
+    MBEDTLS_SSL_DEBUG_BUF(4, "input record header", buf, rec->data_offset);
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %u, "
-                                "version = [%d:%d], msglen = %" MBEDTLS_PRINTF_SIZET,
-                                rec->type,
-                                major_ver, minor_ver, rec->data_len ) );
+    MBEDTLS_SSL_DEBUG_MSG(3, ("input record: msgtype = %u, "
+                              "version = [0x%x], msglen = %" MBEDTLS_PRINTF_SIZET,
+                              rec->type, (unsigned) tls_version, rec->data_len));
 
     rec->buf     = buf;
     rec->buf_len = rec->data_offset + rec->data_len;
 
-    if( rec->data_len == 0 )
-        return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+    if (rec->data_len == 0) {
+        return MBEDTLS_ERR_SSL_INVALID_RECORD;
+    }
 
     /*
      * DTLS-related tests.
@@ -3693,61 +3655,58 @@
      * record leads to the entire datagram being dropped.
      */
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        rec_epoch = ( rec->ctr[0] << 8 ) | rec->ctr[1];
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        rec_epoch = (rec->ctr[0] << 8) | rec->ctr[1];
 
         /* Check that the datagram is large enough to contain a record
          * of the advertised length. */
-        if( len < rec->data_offset + rec->data_len )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "Datagram of length %u too small to contain record of advertised length %u.",
-                             (unsigned) len,
-                             (unsigned)( rec->data_offset + rec->data_len ) ) );
-            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+        if (len < rec->data_offset + rec->data_len) {
+            MBEDTLS_SSL_DEBUG_MSG(1,
+                                  (
+                                      "Datagram of length %u too small to contain record of advertised length %u.",
+                                      (unsigned) len,
+                                      (unsigned) (rec->data_offset + rec->data_len)));
+            return MBEDTLS_ERR_SSL_INVALID_RECORD;
         }
 
         /* Records from other, non-matching epochs are silently discarded.
          * (The case of same-port Client reconnects must be considered in
          *  the caller). */
-        if( rec_epoch != ssl->in_epoch )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: "
-                                        "expected %u, received %lu",
-                                        ssl->in_epoch, (unsigned long) rec_epoch ) );
+        if (rec_epoch != ssl->in_epoch) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("record from another epoch: "
+                                      "expected %u, received %lu",
+                                      ssl->in_epoch, (unsigned long) rec_epoch));
 
             /* Records from the next epoch are considered for buffering
              * (concretely: early Finished messages). */
-            if( rec_epoch == (unsigned) ssl->in_epoch + 1 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) );
-                return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
+            if (rec_epoch == (unsigned) ssl->in_epoch + 1) {
+                MBEDTLS_SSL_DEBUG_MSG(2, ("Consider record for buffering"));
+                return MBEDTLS_ERR_SSL_EARLY_MESSAGE;
             }
 
-            return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
+            return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
         }
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
         /* For records from the correct epoch, check whether their
          * sequence number has been seen before. */
-        else if( mbedtls_ssl_dtls_record_replay_check( (mbedtls_ssl_context *) ssl,
-            &rec->ctr[0] ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) );
-            return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
+        else if (mbedtls_ssl_dtls_record_replay_check((mbedtls_ssl_context *) ssl,
+                                                      &rec->ctr[0]) != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("replayed record"));
+            return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
         }
 #endif
     }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-    return( 0 );
+    return 0;
 }
 
 
 #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl )
+static int ssl_check_client_reconnect(mbedtls_ssl_context *ssl)
 {
-    unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1];
+    unsigned int rec_epoch = (ssl->in_ctr[0] << 8) | ssl->in_ctr[1];
 
     /*
      * Check for an epoch 0 ClientHello. We can't use in_msg here to
@@ -3755,19 +3714,18 @@
      * have an active transform (possibly iv_len != 0), so use the
      * fact that the record header len is 13 instead.
      */
-    if( rec_epoch == 0 &&
+    if (rec_epoch == 0 &&
         ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
-        ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
+        mbedtls_ssl_is_handshake_over(ssl) == 1 &&
         ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
         ssl->in_left > 13 &&
-        ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect "
-                                    "from the same port" ) );
-        return( ssl_handle_possible_reconnect( ssl ) );
+        ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("possible client reconnect "
+                                  "from the same port"));
+        return ssl_handle_possible_reconnect(ssl);
     }
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
 
@@ -3775,60 +3733,54 @@
  * If applicable, decrypt record content
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_prepare_record_content( mbedtls_ssl_context *ssl,
-                                       mbedtls_record *rec )
+static int ssl_prepare_record_content(mbedtls_ssl_context *ssl,
+                                      mbedtls_record *rec)
 {
     int ret, done = 0;
 
-    MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network",
-                           rec->buf, rec->buf_len );
+    MBEDTLS_SSL_DEBUG_BUF(4, "input record from network",
+                          rec->buf, rec->buf_len);
 
-#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
-    if( mbedtls_ssl_hw_record_read != NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_read()" ) );
-
-        ret = mbedtls_ssl_hw_record_read( ssl );
-        if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_read", ret );
-            return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-        }
-
-        if( ret == 0 )
+    /*
+     * In TLS 1.3, always treat ChangeCipherSpec records
+     * as unencrypted. The only thing we do with them is
+     * check the length and content and ignore them.
+     */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    if (ssl->transform_in != NULL &&
+        ssl->transform_in->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
+        if (rec->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) {
             done = 1;
+        }
     }
-#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
-    if( !done && ssl->transform_in != NULL )
-    {
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+    if (!done && ssl->transform_in != NULL) {
         unsigned char const old_msg_type = rec->type;
 
-        if( ( ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in,
-                                             rec ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret );
+        if ((ret = mbedtls_ssl_decrypt_buf(ssl, ssl->transform_in,
+                                           rec)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "ssl_decrypt_buf", ret);
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-            if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID &&
+            if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID &&
                 ssl->conf->ignore_unexpected_cid
-                    == MBEDTLS_SSL_UNEXPECTED_CID_IGNORE )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "ignoring unexpected CID" ) );
+                == MBEDTLS_SSL_UNEXPECTED_CID_IGNORE) {
+                MBEDTLS_SSL_DEBUG_MSG(3, ("ignoring unexpected CID"));
                 ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
             }
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
-            return( ret );
+            return ret;
         }
 
-        if( old_msg_type != rec->type )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 4, ( "record type after decrypt (before %d): %d",
-                                        old_msg_type, rec->type ) );
+        if (old_msg_type != rec->type) {
+            MBEDTLS_SSL_DEBUG_MSG(4, ("record type after decrypt (before %d): %d",
+                                      old_msg_type, rec->type));
         }
 
-        MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt",
-                               rec->buf + rec->data_offset, rec->data_len );
+        MBEDTLS_SSL_DEBUG_BUF(4, "input payload after decrypt",
+                              rec->buf + rec->data_offset, rec->data_len);
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
         /* We have already checked the record content type
@@ -3838,22 +3790,19 @@
          * Since with the use of CIDs, the record content type
          * might change during decryption, re-check the record
          * content type, but treat a failure as fatal this time. */
-        if( ssl_check_record_type( rec->type ) )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) );
-            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+        if (ssl_check_record_type(rec->type)) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("unknown record type"));
+            return MBEDTLS_ERR_SSL_INVALID_RECORD;
         }
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
-        if( rec->data_len == 0 )
-        {
+        if (rec->data_len == 0) {
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-            if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3
-                && rec->type != MBEDTLS_SSL_MSG_APPLICATION_DATA )
-            {
+            if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2
+                && rec->type != MBEDTLS_SSL_MSG_APPLICATION_DATA) {
                 /* TLS v1.2 explicitly disallows zero-length messages which are not application data */
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) );
-                return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+                MBEDTLS_SSL_DEBUG_MSG(1, ("invalid zero-length message type: %d", ssl->in_msgtype));
+                return MBEDTLS_ERR_SSL_INVALID_RECORD;
             }
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
@@ -3863,58 +3812,55 @@
              * Three or more empty messages may be a DoS attack
              * (excessive CPU consumption).
              */
-            if( ssl->nb_zero > 3 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "received four consecutive empty "
-                                            "messages, possible DoS attack" ) );
+            if (ssl->nb_zero > 3) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("received four consecutive empty "
+                                          "messages, possible DoS attack"));
                 /* Treat the records as if they were not properly authenticated,
                  * thereby failing the connection if we see more than allowed
                  * by the configured bad MAC threshold. */
-                return( MBEDTLS_ERR_SSL_INVALID_MAC );
+                return MBEDTLS_ERR_SSL_INVALID_MAC;
             }
-        }
-        else
+        } else {
             ssl->nb_zero = 0;
+        }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-        if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-        {
+        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
             ; /* in_ctr read from peer, not maintained internally */
-        }
-        else
+        } else
 #endif
         {
             unsigned i;
-            for( i = 8; i > mbedtls_ssl_ep_len( ssl ); i-- )
-                if( ++ssl->in_ctr[i - 1] != 0 )
+            for (i = MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
+                 i > mbedtls_ssl_ep_len(ssl); i--) {
+                if (++ssl->in_ctr[i - 1] != 0) {
                     break;
+                }
+            }
 
             /* The loop goes to its end iff the counter is wrapping */
-            if( i == mbedtls_ssl_ep_len( ssl ) )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) );
-                return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
+            if (i == mbedtls_ssl_ep_len(ssl)) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("incoming message counter would wrap"));
+                return MBEDTLS_ERR_SSL_COUNTER_WRAPPING;
             }
         }
 
     }
 
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        mbedtls_ssl_dtls_replay_update( ssl );
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        mbedtls_ssl_dtls_replay_update(ssl);
     }
 #endif
 
     /* Check actual (decrypted) record content length against
      * configured maximum. */
-    if( rec->data_len > MBEDTLS_SSL_IN_CONTENT_LEN )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
-        return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+    if (rec->data_len > MBEDTLS_SSL_IN_CONTENT_LEN) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad message length"));
+        return MBEDTLS_ERR_SSL_INVALID_RECORD;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -3927,131 +3873,129 @@
 
 /* Helper functions for mbedtls_ssl_read_record(). */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_consume_current_message( mbedtls_ssl_context *ssl );
+static int ssl_consume_current_message(mbedtls_ssl_context *ssl);
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_get_next_record( mbedtls_ssl_context *ssl );
+static int ssl_get_next_record(mbedtls_ssl_context *ssl);
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl );
+static int ssl_record_is_in_progress(mbedtls_ssl_context *ssl);
 
-int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
-                             unsigned update_hs_digest )
+int mbedtls_ssl_read_record(mbedtls_ssl_context *ssl,
+                            unsigned update_hs_digest)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> read record"));
 
-    if( ssl->keep_current_message == 0 )
-    {
+    if (ssl->keep_current_message == 0) {
         do {
 
-            ret = ssl_consume_current_message( ssl );
-            if( ret != 0 )
-                return( ret );
+            ret = ssl_consume_current_message(ssl);
+            if (ret != 0) {
+                return ret;
+            }
 
-            if( ssl_record_is_in_progress( ssl ) == 0 )
-            {
+            if (ssl_record_is_in_progress(ssl) == 0) {
+                int dtls_have_buffered = 0;
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-                int have_buffered = 0;
 
                 /* We only check for buffered messages if the
                  * current datagram is fully consumed. */
-                if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-                    ssl_next_record_is_in_datagram( ssl ) == 0 )
-                {
-                    if( ssl_load_buffered_message( ssl ) == 0 )
-                        have_buffered = 1;
+                if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+                    ssl_next_record_is_in_datagram(ssl) == 0) {
+                    if (ssl_load_buffered_message(ssl) == 0) {
+                        dtls_have_buffered = 1;
+                    }
                 }
 
-                if( have_buffered == 0 )
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
-                {
-                    ret = ssl_get_next_record( ssl );
-                    if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING )
+                if (dtls_have_buffered == 0) {
+                    ret = ssl_get_next_record(ssl);
+                    if (ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) {
                         continue;
+                    }
 
-                    if( ret != 0 )
-                    {
-                        MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret );
-                        return( ret );
+                    if (ret != 0) {
+                        MBEDTLS_SSL_DEBUG_RET(1, ("ssl_get_next_record"), ret);
+                        return ret;
                     }
                 }
             }
 
-            ret = mbedtls_ssl_handle_message_type( ssl );
+            ret = mbedtls_ssl_handle_message_type(ssl);
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-            if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
-            {
+            if (ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE) {
                 /* Buffer future message */
-                ret = ssl_buffer_message( ssl );
-                if( ret != 0 )
-                    return( ret );
+                ret = ssl_buffer_message(ssl);
+                if (ret != 0) {
+                    return ret;
+                }
 
                 ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
             }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-        } while( MBEDTLS_ERR_SSL_NON_FATAL           == ret  ||
-                 MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret );
+        } while (MBEDTLS_ERR_SSL_NON_FATAL           == ret  ||
+                 MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret);
 
-        if( 0 != ret )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret );
-            return( ret );
+        if (0 != ret) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_handle_message_type"), ret);
+            return ret;
         }
 
-        if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
-            update_hs_digest == 1 )
-        {
-            mbedtls_ssl_update_handshake_status( ssl );
+        if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+            update_hs_digest == 1) {
+            ret = mbedtls_ssl_update_handshake_status(ssl);
+            if (0 != ret) {
+                MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_update_handshake_status"), ret);
+                return ret;
+            }
         }
-    }
-    else
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) );
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("reuse previously read message"));
         ssl->keep_current_message = 0;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= read record"));
 
-    return( 0 );
+    return 0;
 }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl )
+static int ssl_next_record_is_in_datagram(mbedtls_ssl_context *ssl)
 {
-    if( ssl->in_left > ssl->next_record_offset )
-        return( 1 );
+    if (ssl->in_left > ssl->next_record_offset) {
+        return 1;
+    }
 
-    return( 0 );
+    return 0;
 }
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_load_buffered_message( mbedtls_ssl_context *ssl )
+static int ssl_load_buffered_message(mbedtls_ssl_context *ssl)
 {
     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
-    mbedtls_ssl_hs_buffer * hs_buf;
+    mbedtls_ssl_hs_buffer *hs_buf;
     int ret = 0;
 
-    if( hs == NULL )
-        return( -1 );
+    if (hs == NULL) {
+        return -1;
+    }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_load_buffered_message"));
 
-    if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC ||
-        ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
-    {
+    if (ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC ||
+        ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC) {
         /* Check if we have seen a ChangeCipherSpec before.
          * If yes, synthesize a CCS record. */
-        if( !hs->buffering.seen_ccs )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "CCS not seen in the current flight" ) );
+        if (!hs->buffering.seen_ccs) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("CCS not seen in the current flight"));
             ret = -1;
             goto exit;
         }
 
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) );
+        MBEDTLS_SSL_DEBUG_MSG(2, ("Injecting buffered CCS message"));
         ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;
         ssl->in_msglen = 1;
         ssl->in_msg[0] = 1;
@@ -4068,14 +4012,12 @@
     /* Debug only */
     {
         unsigned offset;
-        for( offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ )
-        {
+        for (offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++) {
             hs_buf = &hs->buffering.hs[offset];
-            if( hs_buf->is_valid == 1 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.",
-                            hs->in_msg_seq + offset,
-                            hs_buf->is_complete ? "fully" : "partially" ) );
+            if (hs_buf->is_valid == 1) {
+                MBEDTLS_SSL_DEBUG_MSG(2, ("Future message with sequence number %u %s buffered.",
+                                          hs->in_msg_seq + offset,
+                                          hs_buf->is_complete ? "fully" : "partially"));
             }
         }
     }
@@ -4084,105 +4026,100 @@
     /* Check if we have buffered and/or fully reassembled the
      * next handshake message. */
     hs_buf = &hs->buffering.hs[0];
-    if( ( hs_buf->is_valid == 1 ) && ( hs_buf->is_complete == 1 ) )
-    {
+    if ((hs_buf->is_valid == 1) && (hs_buf->is_complete == 1)) {
         /* Synthesize a record containing the buffered HS message. */
-        size_t msg_len = ( hs_buf->data[1] << 16 ) |
-                         ( hs_buf->data[2] << 8  ) |
-                           hs_buf->data[3];
+        size_t msg_len = (hs_buf->data[1] << 16) |
+                         (hs_buf->data[2] << 8) |
+                         hs_buf->data[3];
 
         /* Double-check that we haven't accidentally buffered
          * a message that doesn't fit into the input buffer. */
-        if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        if (msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
         }
 
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message has been buffered - load" ) );
-        MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered handshake message (incl. header)",
-                               hs_buf->data, msg_len + 12 );
+        MBEDTLS_SSL_DEBUG_MSG(2, ("Next handshake message has been buffered - load"));
+        MBEDTLS_SSL_DEBUG_BUF(3, "Buffered handshake message (incl. header)",
+                              hs_buf->data, msg_len + 12);
 
         ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
         ssl->in_hslen   = msg_len + 12;
         ssl->in_msglen  = msg_len + 12;
-        memcpy( ssl->in_msg, hs_buf->data, ssl->in_hslen );
+        memcpy(ssl->in_msg, hs_buf->data, ssl->in_hslen);
 
         ret = 0;
         goto exit;
-    }
-    else
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message %u not or only partially bufffered",
-                                    hs->in_msg_seq ) );
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("Next handshake message %u not or only partially bufffered",
+                                  hs->in_msg_seq));
     }
 
     ret = -1;
 
 exit:
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_message" ) );
-    return( ret );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_load_buffered_message"));
+    return ret;
 }
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_buffer_make_space( mbedtls_ssl_context *ssl,
-                                  size_t desired )
+static int ssl_buffer_make_space(mbedtls_ssl_context *ssl,
+                                 size_t desired)
 {
     int offset;
     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "Attempt to free buffered messages to have %u bytes available",
-                                (unsigned) desired ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("Attempt to free buffered messages to have %u bytes available",
+                              (unsigned) desired));
 
     /* Get rid of future records epoch first, if such exist. */
-    ssl_free_buffered_record( ssl );
+    ssl_free_buffered_record(ssl);
 
     /* Check if we have enough space available now. */
-    if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
-                     hs->buffering.total_bytes_buffered ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing future epoch record" ) );
-        return( 0 );
+    if (desired <= (MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+                    hs->buffering.total_bytes_buffered)) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("Enough space available after freeing future epoch record"));
+        return 0;
     }
 
     /* We don't have enough space to buffer the next expected handshake
      * message. Remove buffers used for future messages to gain space,
      * starting with the most distant one. */
-    for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1;
-         offset >= 0; offset-- )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Free buffering slot %d to make space for reassembly of next handshake message",
-                                    offset ) );
+    for (offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1;
+         offset >= 0; offset--) {
+        MBEDTLS_SSL_DEBUG_MSG(2,
+                              (
+                                  "Free buffering slot %d to make space for reassembly of next handshake message",
+                                  offset));
 
-        ssl_buffering_free_slot( ssl, (uint8_t) offset );
+        ssl_buffering_free_slot(ssl, (uint8_t) offset);
 
         /* Check if we have enough space available now. */
-        if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
-                         hs->buffering.total_bytes_buffered ) )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing buffered HS messages" ) );
-            return( 0 );
+        if (desired <= (MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+                        hs->buffering.total_bytes_buffered)) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("Enough space available after freeing buffered HS messages"));
+            return 0;
         }
     }
 
-    return( -1 );
+    return -1;
 }
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_buffer_message( mbedtls_ssl_context *ssl )
+static int ssl_buffer_message(mbedtls_ssl_context *ssl)
 {
     int ret = 0;
     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
 
-    if( hs == NULL )
-        return( 0 );
+    if (hs == NULL) {
+        return 0;
+    }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_buffer_message" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_buffer_message"));
 
-    switch( ssl->in_msgtype )
-    {
+    switch (ssl->in_msgtype) {
         case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC:
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "Remember CCS message" ) );
+            MBEDTLS_SSL_DEBUG_MSG(2, ("Remember CCS message"));
 
             hs->buffering.seen_ccs = 1;
             break;
@@ -4190,113 +4127,115 @@
         case MBEDTLS_SSL_MSG_HANDSHAKE:
         {
             unsigned recv_msg_seq_offset;
-            unsigned recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
+            unsigned recv_msg_seq = (ssl->in_msg[4] << 8) | ssl->in_msg[5];
             mbedtls_ssl_hs_buffer *hs_buf;
             size_t msg_len = ssl->in_hslen - 12;
 
             /* We should never receive an old handshake
              * message - double-check nonetheless. */
-            if( recv_msg_seq < ssl->handshake->in_msg_seq )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-                return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+            if (recv_msg_seq < ssl->handshake->in_msg_seq) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+                return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
             }
 
             recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq;
-            if( recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS )
-            {
+            if (recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS) {
                 /* Silently ignore -- message too far in the future */
-                MBEDTLS_SSL_DEBUG_MSG( 2,
-                 ( "Ignore future HS message with sequence number %u, "
-                   "buffering window %u - %u",
-                   recv_msg_seq, ssl->handshake->in_msg_seq,
-                   ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1 ) );
+                MBEDTLS_SSL_DEBUG_MSG(2,
+                                      ("Ignore future HS message with sequence number %u, "
+                                       "buffering window %u - %u",
+                                       recv_msg_seq, ssl->handshake->in_msg_seq,
+                                       ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS -
+                                       1));
 
                 goto exit;
             }
 
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering HS message with sequence number %u, offset %u ",
-                                        recv_msg_seq, recv_msg_seq_offset ) );
+            MBEDTLS_SSL_DEBUG_MSG(2, ("Buffering HS message with sequence number %u, offset %u ",
+                                      recv_msg_seq, recv_msg_seq_offset));
 
-            hs_buf = &hs->buffering.hs[ recv_msg_seq_offset ];
+            hs_buf = &hs->buffering.hs[recv_msg_seq_offset];
 
             /* Check if the buffering for this seq nr has already commenced. */
-            if( !hs_buf->is_valid )
-            {
+            if (!hs_buf->is_valid) {
                 size_t reassembly_buf_sz;
 
                 hs_buf->is_fragmented =
-                    ( ssl_hs_is_proper_fragment( ssl ) == 1 );
+                    (ssl_hs_is_proper_fragment(ssl) == 1);
 
                 /* We copy the message back into the input buffer
                  * after reassembly, so check that it's not too large.
                  * This is an implementation-specific limitation
                  * and not one from the standard, hence it is not
                  * checked in ssl_check_hs_header(). */
-                if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN )
-                {
+                if (msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN) {
                     /* Ignore message */
                     goto exit;
                 }
 
                 /* Check if we have enough space to buffer the message. */
-                if( hs->buffering.total_bytes_buffered >
-                    MBEDTLS_SSL_DTLS_MAX_BUFFERING )
-                {
-                    MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-                    return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+                if (hs->buffering.total_bytes_buffered >
+                    MBEDTLS_SSL_DTLS_MAX_BUFFERING) {
+                    MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+                    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
                 }
 
-                reassembly_buf_sz = ssl_get_reassembly_buffer_size( msg_len,
-                                                       hs_buf->is_fragmented );
+                reassembly_buf_sz = ssl_get_reassembly_buffer_size(msg_len,
+                                                                   hs_buf->is_fragmented);
 
-                if( reassembly_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
-                                          hs->buffering.total_bytes_buffered ) )
-                {
-                    if( recv_msg_seq_offset > 0 )
-                    {
+                if (reassembly_buf_sz > (MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+                                         hs->buffering.total_bytes_buffered)) {
+                    if (recv_msg_seq_offset > 0) {
                         /* If we can't buffer a future message because
                          * of space limitations -- ignore. */
-                        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %" MBEDTLS_PRINTF_SIZET
-                                                    " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET
-                                                    " (already %" MBEDTLS_PRINTF_SIZET
-                                                    " bytes buffered) -- ignore\n",
-                             msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
-                             hs->buffering.total_bytes_buffered ) );
+                        MBEDTLS_SSL_DEBUG_MSG(2,
+                                              ("Buffering of future message of size %"
+                                               MBEDTLS_PRINTF_SIZET
+                                               " would exceed the compile-time limit %"
+                                               MBEDTLS_PRINTF_SIZET
+                                               " (already %" MBEDTLS_PRINTF_SIZET
+                                               " bytes buffered) -- ignore\n",
+                                               msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+                                               hs->buffering.total_bytes_buffered));
                         goto exit;
-                    }
-                    else
-                    {
-                        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %" MBEDTLS_PRINTF_SIZET
-                                                    " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET
-                                                    " (already %" MBEDTLS_PRINTF_SIZET
-                                                    " bytes buffered) -- attempt to make space by freeing buffered future messages\n",
-                             msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
-                             hs->buffering.total_bytes_buffered ) );
+                    } else {
+                        MBEDTLS_SSL_DEBUG_MSG(2,
+                                              ("Buffering of future message of size %"
+                                               MBEDTLS_PRINTF_SIZET
+                                               " would exceed the compile-time limit %"
+                                               MBEDTLS_PRINTF_SIZET
+                                               " (already %" MBEDTLS_PRINTF_SIZET
+                                               " bytes buffered) -- attempt to make space by freeing buffered future messages\n",
+                                               msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+                                               hs->buffering.total_bytes_buffered));
                     }
 
-                    if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 )
-                    {
-                        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %" MBEDTLS_PRINTF_SIZET
-                                                    " (%" MBEDTLS_PRINTF_SIZET " with bitmap) would exceed"
-                                                    " the compile-time limit %" MBEDTLS_PRINTF_SIZET
-                                                    " (already %" MBEDTLS_PRINTF_SIZET
-                                                    " bytes buffered) -- fail\n",
-                             msg_len,
-                             reassembly_buf_sz,
-                             (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
-                             hs->buffering.total_bytes_buffered ) );
+                    if (ssl_buffer_make_space(ssl, reassembly_buf_sz) != 0) {
+                        MBEDTLS_SSL_DEBUG_MSG(2,
+                                              ("Reassembly of next message of size %"
+                                               MBEDTLS_PRINTF_SIZET
+                                               " (%" MBEDTLS_PRINTF_SIZET
+                                               " with bitmap) would exceed"
+                                               " the compile-time limit %"
+                                               MBEDTLS_PRINTF_SIZET
+                                               " (already %" MBEDTLS_PRINTF_SIZET
+                                               " bytes buffered) -- fail\n",
+                                               msg_len,
+                                               reassembly_buf_sz,
+                                               (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+                                               hs->buffering.total_bytes_buffered));
                         ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
                         goto exit;
                     }
                 }
 
-                MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %" MBEDTLS_PRINTF_SIZET,
-                                            msg_len ) );
+                MBEDTLS_SSL_DEBUG_MSG(2,
+                                      ("initialize reassembly, total length = %"
+                                       MBEDTLS_PRINTF_SIZET,
+                                       msg_len));
 
-                hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz );
-                if( hs_buf->data == NULL )
-                {
+                hs_buf->data = mbedtls_calloc(1, reassembly_buf_sz);
+                if (hs_buf->data == NULL) {
                     ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
                     goto exit;
                 }
@@ -4304,27 +4243,23 @@
 
                 /* Prepare final header: copy msg_type, length and message_seq,
                  * then add standardised fragment_offset and fragment_length */
-                memcpy( hs_buf->data, ssl->in_msg, 6 );
-                memset( hs_buf->data + 6, 0, 3 );
-                memcpy( hs_buf->data + 9, hs_buf->data + 1, 3 );
+                memcpy(hs_buf->data, ssl->in_msg, 6);
+                memset(hs_buf->data + 6, 0, 3);
+                memcpy(hs_buf->data + 9, hs_buf->data + 1, 3);
 
                 hs_buf->is_valid = 1;
 
                 hs->buffering.total_bytes_buffered += reassembly_buf_sz;
-            }
-            else
-            {
+            } else {
                 /* Make sure msg_type and length are consistent */
-                if( memcmp( hs_buf->data, ssl->in_msg, 4 ) != 0 )
-                {
-                    MBEDTLS_SSL_DEBUG_MSG( 1, ( "Fragment header mismatch - ignore" ) );
+                if (memcmp(hs_buf->data, ssl->in_msg, 4) != 0) {
+                    MBEDTLS_SSL_DEBUG_MSG(1, ("Fragment header mismatch - ignore"));
                     /* Ignore */
                     goto exit;
                 }
             }
 
-            if( !hs_buf->is_complete )
-            {
+            if (!hs_buf->is_complete) {
                 size_t frag_len, frag_off;
                 unsigned char * const msg = hs_buf->data + 12;
 
@@ -4334,28 +4269,25 @@
 
                 /* Validation of header fields already done in
                  * mbedtls_ssl_prepare_handshake_record(). */
-                frag_off = ssl_get_hs_frag_off( ssl );
-                frag_len = ssl_get_hs_frag_len( ssl );
+                frag_off = ssl_get_hs_frag_off(ssl);
+                frag_len = ssl_get_hs_frag_len(ssl);
 
-                MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %" MBEDTLS_PRINTF_SIZET
-                                            ", length = %" MBEDTLS_PRINTF_SIZET,
-                                            frag_off, frag_len ) );
-                memcpy( msg + frag_off, ssl->in_msg + 12, frag_len );
+                MBEDTLS_SSL_DEBUG_MSG(2, ("adding fragment, offset = %" MBEDTLS_PRINTF_SIZET
+                                          ", length = %" MBEDTLS_PRINTF_SIZET,
+                                          frag_off, frag_len));
+                memcpy(msg + frag_off, ssl->in_msg + 12, frag_len);
 
-                if( hs_buf->is_fragmented )
-                {
+                if (hs_buf->is_fragmented) {
                     unsigned char * const bitmask = msg + msg_len;
-                    ssl_bitmask_set( bitmask, frag_off, frag_len );
-                    hs_buf->is_complete = ( ssl_bitmask_check( bitmask,
-                                                               msg_len ) == 0 );
-                }
-                else
-                {
+                    ssl_bitmask_set(bitmask, frag_off, frag_len);
+                    hs_buf->is_complete = (ssl_bitmask_check(bitmask,
+                                                             msg_len) == 0);
+                } else {
                     hs_buf->is_complete = 1;
                 }
 
-                MBEDTLS_SSL_DEBUG_MSG( 2, ( "message %scomplete",
-                                   hs_buf->is_complete ? "" : "not yet " ) );
+                MBEDTLS_SSL_DEBUG_MSG(2, ("message %scomplete",
+                                          hs_buf->is_complete ? "" : "not yet "));
             }
 
             break;
@@ -4368,13 +4300,13 @@
 
 exit:
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_buffer_message" ) );
-    return( ret );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_buffer_message"));
+    return ret;
 }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_consume_current_message( mbedtls_ssl_context *ssl )
+static int ssl_consume_current_message(mbedtls_ssl_context *ssl)
 {
     /*
      * Consume last content-layer message and potentially
@@ -4399,15 +4331,13 @@
      */
 
     /* Case (1): Handshake messages */
-    if( ssl->in_hslen != 0 )
-    {
+    if (ssl->in_hslen != 0) {
         /* Hard assertion to be sure that no application data
          * is in flight, as corrupting ssl->in_msglen during
          * ssl->in_offt != NULL is fatal. */
-        if( ssl->in_offt != NULL )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        if (ssl->in_offt != NULL) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
         }
 
         /*
@@ -4431,68 +4361,64 @@
          *     bounds after handling a DTLS message with an unexpected
          *     sequence number, see mbedtls_ssl_prepare_handshake_record.
          */
-        if( ssl->in_hslen < ssl->in_msglen )
-        {
+        if (ssl->in_hslen < ssl->in_msglen) {
             ssl->in_msglen -= ssl->in_hslen;
-            memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen,
-                     ssl->in_msglen );
+            memmove(ssl->in_msg, ssl->in_msg + ssl->in_hslen,
+                    ssl->in_msglen);
 
-            MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record",
-                                   ssl->in_msg, ssl->in_msglen );
-        }
-        else
-        {
+            MBEDTLS_SSL_DEBUG_BUF(4, "remaining content in record",
+                                  ssl->in_msg, ssl->in_msglen);
+        } else {
             ssl->in_msglen = 0;
         }
 
         ssl->in_hslen   = 0;
     }
     /* Case (4): Application data */
-    else if( ssl->in_offt != NULL )
-    {
-        return( 0 );
+    else if (ssl->in_offt != NULL) {
+        return 0;
     }
     /* Everything else (CCS & Alerts) */
-    else
-    {
+    else {
         ssl->in_msglen = 0;
     }
 
-    return( 0 );
+    return 0;
 }
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl )
+static int ssl_record_is_in_progress(mbedtls_ssl_context *ssl)
 {
-    if( ssl->in_msglen > 0 )
-        return( 1 );
+    if (ssl->in_msglen > 0) {
+        return 1;
+    }
 
-    return( 0 );
+    return 0;
 }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
 
-static void ssl_free_buffered_record( mbedtls_ssl_context *ssl )
+static void ssl_free_buffered_record(mbedtls_ssl_context *ssl)
 {
     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
-    if( hs == NULL )
+    if (hs == NULL) {
         return;
+    }
 
-    if( hs->buffering.future_record.data != NULL )
-    {
+    if (hs->buffering.future_record.data != NULL) {
         hs->buffering.total_bytes_buffered -=
             hs->buffering.future_record.len;
 
-        mbedtls_free( hs->buffering.future_record.data );
+        mbedtls_free(hs->buffering.future_record.data);
         hs->buffering.future_record.data = NULL;
     }
 }
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_load_buffered_record( mbedtls_ssl_context *ssl )
+static int ssl_load_buffered_record(mbedtls_ssl_context *ssl)
 {
     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
-    unsigned char * rec;
+    unsigned char *rec;
     size_t rec_len;
     unsigned rec_epoch;
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
@@ -4500,88 +4426,92 @@
 #else
     size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
 #endif
-    if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-        return( 0 );
+    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        return 0;
+    }
 
-    if( hs == NULL )
-        return( 0 );
+    if (hs == NULL) {
+        return 0;
+    }
 
     rec       = hs->buffering.future_record.data;
     rec_len   = hs->buffering.future_record.len;
     rec_epoch = hs->buffering.future_record.epoch;
 
-    if( rec == NULL )
-        return( 0 );
+    if (rec == NULL) {
+        return 0;
+    }
 
     /* Only consider loading future records if the
      * input buffer is empty. */
-    if( ssl_next_record_is_in_datagram( ssl ) == 1 )
-        return( 0 );
+    if (ssl_next_record_is_in_datagram(ssl) == 1) {
+        return 0;
+    }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_load_buffered_record"));
 
-    if( rec_epoch != ssl->in_epoch )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffered record not from current epoch." ) );
+    if (rec_epoch != ssl->in_epoch) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("Buffered record not from current epoch."));
         goto exit;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "Found buffered record from current epoch - load" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("Found buffered record from current epoch - load"));
 
     /* Double-check that the record is not too large */
-    if( rec_len > in_buf_len - (size_t)( ssl->in_hdr - ssl->in_buf ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    if (rec_len > in_buf_len - (size_t) (ssl->in_hdr - ssl->in_buf)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    memcpy( ssl->in_hdr, rec, rec_len );
+    memcpy(ssl->in_hdr, rec, rec_len);
     ssl->in_left = rec_len;
     ssl->next_record_offset = 0;
 
-    ssl_free_buffered_record( ssl );
+    ssl_free_buffered_record(ssl);
 
 exit:
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_record" ) );
-    return( 0 );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_load_buffered_record"));
+    return 0;
 }
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
-                                     mbedtls_record const *rec )
+static int ssl_buffer_future_record(mbedtls_ssl_context *ssl,
+                                    mbedtls_record const *rec)
 {
     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
 
     /* Don't buffer future records outside handshakes. */
-    if( hs == NULL )
-        return( 0 );
+    if (hs == NULL) {
+        return 0;
+    }
 
     /* Only buffer handshake records (we are only interested
      * in Finished messages). */
-    if( rec->type != MBEDTLS_SSL_MSG_HANDSHAKE )
-        return( 0 );
+    if (rec->type != MBEDTLS_SSL_MSG_HANDSHAKE) {
+        return 0;
+    }
 
     /* Don't buffer more than one future epoch record. */
-    if( hs->buffering.future_record.data != NULL )
-        return( 0 );
+    if (hs->buffering.future_record.data != NULL) {
+        return 0;
+    }
 
     /* Don't buffer record if there's not enough buffering space remaining. */
-    if( rec->buf_len > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
-                         hs->buffering.total_bytes_buffered ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %" MBEDTLS_PRINTF_SIZET
-                                    " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET
-                                    " (already %" MBEDTLS_PRINTF_SIZET
-                                    " bytes buffered) -- ignore\n",
-                        rec->buf_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
-                        hs->buffering.total_bytes_buffered ) );
-        return( 0 );
+    if (rec->buf_len > (MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+                        hs->buffering.total_bytes_buffered)) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("Buffering of future epoch record of size %" MBEDTLS_PRINTF_SIZET
+                                  " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET
+                                  " (already %" MBEDTLS_PRINTF_SIZET
+                                  " bytes buffered) -- ignore\n",
+                                  rec->buf_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+                                  hs->buffering.total_bytes_buffered));
+        return 0;
     }
 
     /* Buffer record */
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u",
-                                ssl->in_epoch + 1U ) );
-    MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", rec->buf, rec->buf_len );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("Buffer record from epoch %u",
+                              ssl->in_epoch + 1U));
+    MBEDTLS_SSL_DEBUG_BUF(3, "Buffered record", rec->buf, rec->buf_len);
 
     /* ssl_parse_record_header() only considers records
      * of the next epoch as candidates for buffering. */
@@ -4589,24 +4519,23 @@
     hs->buffering.future_record.len   = rec->buf_len;
 
     hs->buffering.future_record.data =
-        mbedtls_calloc( 1, hs->buffering.future_record.len );
-    if( hs->buffering.future_record.data == NULL )
-    {
+        mbedtls_calloc(1, hs->buffering.future_record.len);
+    if (hs->buffering.future_record.data == NULL) {
         /* If we run out of RAM trying to buffer a
          * record from the next epoch, just ignore. */
-        return( 0 );
+        return 0;
     }
 
-    memcpy( hs->buffering.future_record.data, rec->buf, rec->buf_len );
+    memcpy(hs->buffering.future_record.data, rec->buf, rec->buf_len);
 
     hs->buffering.total_bytes_buffered += rec->buf_len;
-    return( 0 );
+    return 0;
 }
 
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_get_next_record( mbedtls_ssl_context *ssl )
+static int ssl_get_next_record(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_record rec;
@@ -4618,44 +4547,41 @@
      * the length of the buffered record, so that
      * the calls to ssl_fetch_input() below will
      * essentially be no-ops. */
-    ret = ssl_load_buffered_record( ssl );
-    if( ret != 0 )
-        return( ret );
+    ret = ssl_load_buffered_record(ssl);
+    if (ret != 0) {
+        return ret;
+    }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
     /* Ensure that we have enough space available for the default form
      * of TLS / DTLS record headers (5 Bytes for TLS, 13 Bytes for DTLS,
      * with no space for CIDs counted in). */
-    ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_in_hdr_len( ssl ) );
-    if( ret != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
-        return( ret );
+    ret = mbedtls_ssl_fetch_input(ssl, mbedtls_ssl_in_hdr_len(ssl));
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret);
+        return ret;
     }
 
-    ret = ssl_parse_record_header( ssl, ssl->in_hdr, ssl->in_left, &rec );
-    if( ret != 0 )
-    {
+    ret = ssl_parse_record_header(ssl, ssl->in_hdr, ssl->in_left, &rec);
+    if (ret != 0) {
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-        if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-        {
-            if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
-            {
-                ret = ssl_buffer_future_record( ssl, &rec );
-                if( ret != 0 )
-                    return( ret );
+        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+            if (ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE) {
+                ret = ssl_buffer_future_record(ssl, &rec);
+                if (ret != 0) {
+                    return ret;
+                }
 
                 /* Fall through to handling of unexpected records */
                 ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
             }
 
-            if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD )
-            {
+            if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) {
 #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
                 /* Reset in pointers to default state for TLS/DTLS records,
                  * assuming no CID and no offset between record content and
                  * record plaintext. */
-                mbedtls_ssl_update_in_pointers( ssl );
+                mbedtls_ssl_update_in_pointers(ssl);
 
                 /* Setup internal message pointers from record structure. */
                 ssl->in_msgtype = rec.type;
@@ -4665,59 +4591,53 @@
                 ssl->in_iv  = ssl->in_msg = ssl->in_len + 2;
                 ssl->in_msglen = rec.data_len;
 
-                ret = ssl_check_client_reconnect( ssl );
-                MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_client_reconnect", ret );
-                if( ret != 0 )
-                    return( ret );
+                ret = ssl_check_client_reconnect(ssl);
+                MBEDTLS_SSL_DEBUG_RET(2, "ssl_check_client_reconnect", ret);
+                if (ret != 0) {
+                    return ret;
+                }
 #endif
 
                 /* Skip unexpected record (but not whole datagram) */
                 ssl->next_record_offset = rec.buf_len;
 
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record "
-                                            "(header)" ) );
-            }
-            else
-            {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("discarding unexpected record "
+                                          "(header)"));
+            } else {
                 /* Skip invalid record and the rest of the datagram */
                 ssl->next_record_offset = 0;
                 ssl->in_left = 0;
 
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record "
-                                            "(header)" ) );
+                MBEDTLS_SSL_DEBUG_MSG(1, ("discarding invalid record "
+                                          "(header)"));
             }
 
             /* Get next record */
-            return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
-        }
-        else
+            return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
+        } else
 #endif
         {
-            return( ret );
+            return ret;
         }
     }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
         /* Remember offset of next record within datagram. */
         ssl->next_record_offset = rec.buf_len;
-        if( ssl->next_record_offset < ssl->in_left )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) );
+        if (ssl->next_record_offset < ssl->in_left) {
+            MBEDTLS_SSL_DEBUG_MSG(3, ("more than one record within datagram"));
         }
-    }
-    else
+    } else
 #endif
     {
         /*
          * Fetch record contents from underlying transport.
          */
-        ret = mbedtls_ssl_fetch_input( ssl, rec.buf_len );
-        if( ret != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
-            return( ret );
+        ret = mbedtls_ssl_fetch_input(ssl, rec.buf_len);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret);
+            return ret;
         }
 
         ssl->in_left = 0;
@@ -4727,39 +4647,31 @@
      * Decrypt record contents.
      */
 
-    if( ( ret = ssl_prepare_record_content( ssl, &rec ) ) != 0 )
-    {
+    if ((ret = ssl_prepare_record_content(ssl, &rec)) != 0) {
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-        if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-        {
+        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
             /* Silently discard invalid records */
-            if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
-            {
+            if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) {
                 /* Except when waiting for Finished as a bad mac here
                  * probably means something went wrong in the handshake
                  * (eg wrong psk used, mitm downgrade attempt, etc.) */
-                if( ssl->state == MBEDTLS_SSL_CLIENT_FINISHED ||
-                    ssl->state == MBEDTLS_SSL_SERVER_FINISHED )
-                {
+                if (ssl->state == MBEDTLS_SSL_CLIENT_FINISHED ||
+                    ssl->state == MBEDTLS_SSL_SERVER_FINISHED) {
 #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)
-                    if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
-                    {
-                        mbedtls_ssl_send_alert_message( ssl,
-                                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC );
+                    if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) {
+                        mbedtls_ssl_send_alert_message(ssl,
+                                                       MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                                       MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC);
                     }
 #endif
-                    return( ret );
+                    return ret;
                 }
 
-#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
-                if( ssl->conf->badmac_limit != 0 &&
-                    ++ssl->badmac_seen >= ssl->conf->badmac_limit )
-                {
-                    MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) );
-                    return( MBEDTLS_ERR_SSL_INVALID_MAC );
+                if (ssl->conf->badmac_limit != 0 &&
+                    ++ssl->badmac_seen >= ssl->conf->badmac_limit) {
+                    MBEDTLS_SSL_DEBUG_MSG(1, ("too many records with bad MAC"));
+                    return MBEDTLS_ERR_SSL_INVALID_MAC;
                 }
-#endif
 
                 /* As above, invalid records cause
                  * dismissal of the whole datagram. */
@@ -4767,25 +4679,23 @@
                 ssl->next_record_offset = 0;
                 ssl->in_left = 0;
 
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) );
-                return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
+                MBEDTLS_SSL_DEBUG_MSG(1, ("discarding invalid record (mac)"));
+                return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
             }
 
-            return( ret );
-        }
-        else
+            return ret;
+        } else
 #endif
         {
             /* Error out (and send alert) on invalid records */
 #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)
-            if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
-            {
-                mbedtls_ssl_send_alert_message( ssl,
-                        MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                        MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC );
+            if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) {
+                mbedtls_ssl_send_alert_message(ssl,
+                                               MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                               MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC);
             }
 #endif
-            return( ret );
+            return ret;
         }
     }
 
@@ -4793,7 +4703,7 @@
     /* Reset in pointers to default state for TLS/DTLS records,
      * assuming no CID and no offset between record content and
      * record plaintext. */
-    mbedtls_ssl_update_in_pointers( ssl );
+    mbedtls_ssl_update_in_pointers(ssl);
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
     ssl->in_len = ssl->in_cid + rec.cid_len;
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
@@ -4809,207 +4719,174 @@
     ssl->in_hdr[0] = rec.type;
     ssl->in_msg    = rec.buf + rec.data_offset;
     ssl->in_msglen = rec.data_len;
-    MBEDTLS_PUT_UINT16_BE( rec.data_len, ssl->in_len, 0 );
+    MBEDTLS_PUT_UINT16_BE(rec.data_len, ssl->in_len, 0);
 
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-    if( ssl->transform_in != NULL &&
-        ssl->session_in->compression == MBEDTLS_SSL_COMPRESS_DEFLATE )
-    {
-        if( ( ret = ssl_decompress_buf( ssl ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret );
-            return( ret );
-        }
-
-        /* Check actual (decompress) record content length against
-         * configured maximum. */
-        if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
-            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
-        }
-    }
-#endif /* MBEDTLS_ZLIB_SUPPORT */
-
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     /*
      * Handle particular types of records
      */
-    if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
-    {
-        if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 )
-        {
-            return( ret );
+    if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) {
+        if ((ret = mbedtls_ssl_prepare_handshake_record(ssl)) != 0) {
+            return ret;
         }
     }
 
-    if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
-    {
-        if( ssl->in_msglen != 1 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %" MBEDTLS_PRINTF_SIZET,
-                           ssl->in_msglen ) );
-            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+    if (ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) {
+        if (ssl->in_msglen != 1) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("invalid CCS message, len: %" MBEDTLS_PRINTF_SIZET,
+                                      ssl->in_msglen));
+            return MBEDTLS_ERR_SSL_INVALID_RECORD;
         }
 
-        if( ssl->in_msg[0] != 1 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, content: %02x",
-                                        ssl->in_msg[0] ) );
-            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+        if (ssl->in_msg[0] != 1) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("invalid CCS message, content: %02x",
+                                      ssl->in_msg[0]));
+            return MBEDTLS_ERR_SSL_INVALID_RECORD;
         }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-        if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
             ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC    &&
-            ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
-        {
-            if( ssl->handshake == NULL )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping ChangeCipherSpec outside handshake" ) );
-                return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
+            ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC) {
+            if (ssl->handshake == NULL) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("dropping ChangeCipherSpec outside handshake"));
+                return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
             }
 
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "received out-of-order ChangeCipherSpec - remember" ) );
-            return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
+            MBEDTLS_SSL_DEBUG_MSG(1, ("received out-of-order ChangeCipherSpec - remember"));
+            return MBEDTLS_ERR_SSL_EARLY_MESSAGE;
         }
 #endif
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
+#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+            MBEDTLS_SSL_DEBUG_MSG(1,
+                                  ("Ignore ChangeCipherSpec in TLS 1.3 compatibility mode"));
+            return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
+#else
+            MBEDTLS_SSL_DEBUG_MSG(1,
+                                  ("ChangeCipherSpec invalid in TLS 1.3 without compatibility mode"));
+            return MBEDTLS_ERR_SSL_INVALID_RECORD;
+#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
+        }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
     }
 
-    if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT )
-    {
-        if( ssl->in_msglen != 2 )
-        {
+    if (ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT) {
+        if (ssl->in_msglen != 2) {
             /* Note: Standard allows for more than one 2 byte alert
                to be packed in a single message, but Mbed TLS doesn't
                currently support this. */
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %" MBEDTLS_PRINTF_SIZET,
-                           ssl->in_msglen ) );
-            return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+            MBEDTLS_SSL_DEBUG_MSG(1, ("invalid alert message, len: %" MBEDTLS_PRINTF_SIZET,
+                                      ssl->in_msglen));
+            return MBEDTLS_ERR_SSL_INVALID_RECORD;
         }
 
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%u:%u]",
-                       ssl->in_msg[0], ssl->in_msg[1] ) );
+        MBEDTLS_SSL_DEBUG_MSG(2, ("got an alert message, type: [%u:%u]",
+                                  ssl->in_msg[0], ssl->in_msg[1]));
 
         /*
          * Ignore non-fatal alerts, except close_notify and no_renegotiation
          */
-        if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)",
-                           ssl->in_msg[1] ) );
-            return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE );
+        if (ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("is a fatal alert message (msg %d)",
+                                      ssl->in_msg[1]));
+            return MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE;
         }
 
-        if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
-            ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a close notify message" ) );
-            return( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY );
+        if (ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
+            ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("is a close notify message"));
+            return MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY;
         }
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED)
-        if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
-            ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no renegotiation alert" ) );
+        if (ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
+            ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("is a no renegotiation alert"));
             /* Will be handled when trying to parse ServerHello */
-            return( 0 );
+            return 0;
         }
 #endif
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C)
-        if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
-            ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
-            ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
-            ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) );
-            /* Will be handled in mbedtls_ssl_parse_certificate() */
-            return( 0 );
-        }
-#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */
-
         /* Silently ignore: fetch new message */
         return MBEDTLS_ERR_SSL_NON_FATAL;
     }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
         /* Drop unexpected ApplicationData records,
          * except at the beginning of renegotiations */
-        if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA &&
-            ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER
+        if (ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA &&
+            mbedtls_ssl_is_handshake_over(ssl) == 0
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
-            && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
-                   ssl->state == MBEDTLS_SSL_SERVER_HELLO )
+            && !(ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
+                 ssl->state == MBEDTLS_SSL_SERVER_HELLO)
 #endif
-            )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) );
-            return( MBEDTLS_ERR_SSL_NON_FATAL );
+            ) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("dropping unexpected ApplicationData"));
+            return MBEDTLS_ERR_SSL_NON_FATAL;
         }
 
-        if( ssl->handshake != NULL &&
-            ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER  )
-        {
-            mbedtls_ssl_handshake_wrapup_free_hs_transform( ssl );
+        if (ssl->handshake != NULL &&
+            mbedtls_ssl_is_handshake_over(ssl) == 1) {
+            mbedtls_ssl_handshake_wrapup_free_hs_transform(ssl);
         }
     }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_send_fatal_handshake_failure(mbedtls_ssl_context *ssl)
 {
-    return( mbedtls_ssl_send_alert_message( ssl,
-                  MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                  MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) );
+    return mbedtls_ssl_send_alert_message(ssl,
+                                          MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                          MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
 }
 
-int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
-                            unsigned char level,
-                            unsigned char message )
+int mbedtls_ssl_send_alert_message(mbedtls_ssl_context *ssl,
+                                   unsigned char level,
+                                   unsigned char message)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( ssl == NULL || ssl->conf == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl == NULL || ssl->conf == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    if( ssl->out_left != 0 )
-        return( mbedtls_ssl_flush_output( ssl ) );
+    if (ssl->out_left != 0) {
+        return mbedtls_ssl_flush_output(ssl);
+    }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) );
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message ));
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> send alert message"));
+    MBEDTLS_SSL_DEBUG_MSG(3, ("send alert level=%u message=%u", level, message));
 
     ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT;
     ssl->out_msglen = 2;
     ssl->out_msg[0] = level;
     ssl->out_msg[1] = message;
 
-    if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
-        return( ret );
+    if ((ret = mbedtls_ssl_write_record(ssl, SSL_FORCE_FLUSH)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_record", ret);
+        return ret;
     }
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= send alert message"));
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_write_change_cipher_spec(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write change cipher spec"));
 
     ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;
     ssl->out_msglen  = 1;
@@ -5017,35 +4894,32 @@
 
     ssl->state++;
 
-    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
-        return( ret );
+    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret);
+        return ret;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write change cipher spec"));
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_parse_change_cipher_spec(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse change cipher spec"));
 
-    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
-        return( ret );
+    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
+        return ret;
     }
 
-    if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
-        return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad change cipher spec message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
     }
 
     /* CCS records are only accepted if they have length 1 and content '1',
@@ -5055,50 +4929,36 @@
      * Switch to our negotiated transform and session parameters for inbound
      * data.
      */
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) );
+    MBEDTLS_SSL_DEBUG_MSG(3, ("switching to new transform spec for inbound data"));
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
     ssl->transform_in = ssl->transform_negotiate;
+#endif
     ssl->session_in = ssl->session_negotiate;
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-        mbedtls_ssl_dtls_replay_reset( ssl );
+        mbedtls_ssl_dtls_replay_reset(ssl);
 #endif
 
         /* Increment epoch */
-        if( ++ssl->in_epoch == 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) );
+        if (++ssl->in_epoch == 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS epoch would wrap"));
             /* This is highly unlikely to happen for legitimate reasons, so
                treat it as an attack and don't send an alert. */
-            return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
+            return MBEDTLS_ERR_SSL_COUNTER_WRAPPING;
         }
-    }
-    else
+    } else
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
-    memset( ssl->in_ctr, 0, 8 );
+    memset(ssl->in_ctr, 0, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN);
 
-    mbedtls_ssl_update_in_pointers( ssl );
-
-#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
-    if( mbedtls_ssl_hw_record_activate != NULL )
-    {
-        if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
-            return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-        }
-    }
-#endif
+    mbedtls_ssl_update_in_pointers(ssl);
 
     ssl->state++;
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse change cipher spec"));
 
-    return( 0 );
+    return 0;
 }
 
 /* Once ssl->out_hdr as the address of the beginning of the
@@ -5110,35 +4970,30 @@
  */
 
 static size_t ssl_transform_get_explicit_iv_len(
-                        mbedtls_ssl_transform const *transform )
+    mbedtls_ssl_transform const *transform)
 {
-    if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 )
-        return( 0 );
-
-    return( transform->ivlen - transform->fixed_ivlen );
+    return transform->ivlen - transform->fixed_ivlen;
 }
 
-void mbedtls_ssl_update_out_pointers( mbedtls_ssl_context *ssl,
-                                      mbedtls_ssl_transform *transform )
+void mbedtls_ssl_update_out_pointers(mbedtls_ssl_context *ssl,
+                                     mbedtls_ssl_transform *transform)
 {
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
         ssl->out_ctr = ssl->out_hdr +  3;
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-        ssl->out_cid = ssl->out_ctr +  8;
+        ssl->out_cid = ssl->out_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
         ssl->out_len = ssl->out_cid;
-        if( transform != NULL )
+        if (transform != NULL) {
             ssl->out_len += transform->out_cid_len;
+        }
 #else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-        ssl->out_len = ssl->out_ctr + 8;
+        ssl->out_len = ssl->out_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
         ssl->out_iv  = ssl->out_len + 2;
-    }
-    else
+    } else
 #endif
     {
-        ssl->out_ctr = ssl->out_hdr - 8;
         ssl->out_len = ssl->out_hdr + 3;
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
         ssl->out_cid = ssl->out_len;
@@ -5148,8 +5003,9 @@
 
     ssl->out_msg = ssl->out_iv;
     /* Adjust out_msg to make space for explicit IV, if used. */
-    if( transform != NULL )
-        ssl->out_msg += ssl_transform_get_explicit_iv_len( transform );
+    if (transform != NULL) {
+        ssl->out_msg += ssl_transform_get_explicit_iv_len(transform);
+    }
 }
 
 /* Once ssl->in_hdr as the address of the beginning of the
@@ -5160,7 +5016,7 @@
  *       and the caller has to make sure there's space for this.
  */
 
-void mbedtls_ssl_update_in_pointers( mbedtls_ssl_context *ssl )
+void mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl)
 {
     /* This function sets the pointers to match the case
      * of unprotected TLS/DTLS records, with both  ssl->in_iv
@@ -5173,25 +5029,23 @@
      */
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
         /* This sets the header pointers to match records
          * without CID. When we receive a record containing
          * a CID, the fields are shifted accordingly in
          * ssl_parse_record_header(). */
         ssl->in_ctr = ssl->in_hdr +  3;
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-        ssl->in_cid = ssl->in_ctr +  8;
+        ssl->in_cid = ssl->in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
         ssl->in_len = ssl->in_cid; /* Default: no CID */
 #else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-        ssl->in_len = ssl->in_ctr + 8;
+        ssl->in_len = ssl->in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
         ssl->in_iv  = ssl->in_len + 2;
-    }
-    else
+    } else
 #endif
     {
-        ssl->in_ctr = ssl->in_hdr - 8;
+        ssl->in_ctr = ssl->in_hdr - MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
         ssl->in_len = ssl->in_hdr + 3;
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
         ssl->in_cid = ssl->in_len;
@@ -5207,46 +5061,44 @@
  * Setup an SSL context
  */
 
-void mbedtls_ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl )
+void mbedtls_ssl_reset_in_out_pointers(mbedtls_ssl_context *ssl)
 {
     /* Set the incoming and outgoing record pointers. */
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
         ssl->out_hdr = ssl->out_buf;
         ssl->in_hdr  = ssl->in_buf;
-    }
-    else
+    } else
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
     {
+        ssl->out_ctr = ssl->out_buf;
         ssl->out_hdr = ssl->out_buf + 8;
         ssl->in_hdr  = ssl->in_buf  + 8;
     }
 
     /* Derive other internal pointers. */
-    mbedtls_ssl_update_out_pointers( ssl, NULL /* no transform enabled */ );
-    mbedtls_ssl_update_in_pointers ( ssl );
+    mbedtls_ssl_update_out_pointers(ssl, NULL /* no transform enabled */);
+    mbedtls_ssl_update_in_pointers(ssl);
 }
 
 /*
  * SSL get accessors
  */
-size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl )
+size_t mbedtls_ssl_get_bytes_avail(const mbedtls_ssl_context *ssl)
 {
-    return( ssl->in_offt == NULL ? 0 : ssl->in_msglen );
+    return ssl->in_offt == NULL ? 0 : ssl->in_msglen;
 }
 
-int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl )
+int mbedtls_ssl_check_pending(const mbedtls_ssl_context *ssl)
 {
     /*
      * Case A: We're currently holding back
      * a message for further processing.
      */
 
-    if( ssl->keep_current_message == 1 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: record held back for processing" ) );
-        return( 1 );
+    if (ssl->keep_current_message == 1) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_check_pending: record held back for processing"));
+        return 1;
     }
 
     /*
@@ -5254,11 +5106,10 @@
      */
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ssl->in_left > ssl->next_record_offset )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more records within current datagram" ) );
-        return( 1 );
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        ssl->in_left > ssl->next_record_offset) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_check_pending: more records within current datagram"));
+        return 1;
     }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
@@ -5266,19 +5117,18 @@
      * Case C: A handshake message is being processed.
      */
 
-    if( ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more handshake messages within current record" ) );
-        return( 1 );
+    if (ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen) {
+        MBEDTLS_SSL_DEBUG_MSG(3,
+                              ("ssl_check_pending: more handshake messages within current record"));
+        return 1;
     }
 
     /*
      * Case D: An application data message is being processed
      */
-    if( ssl->in_offt != NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: application data record is being processed" ) );
-        return( 1 );
+    if (ssl->in_offt != NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_check_pending: application data record is being processed"));
+        return 1;
     }
 
     /*
@@ -5287,29 +5137,61 @@
      * we implement support for multiple alerts in single records.
      */
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: nothing pending" ) );
-    return( 0 );
+    MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_check_pending: nothing pending"));
+    return 0;
 }
 
 
-int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl )
+int mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl)
 {
     size_t transform_expansion = 0;
     const mbedtls_ssl_transform *transform = ssl->transform_out;
     unsigned block_size;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_type_t key_type;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-    size_t out_hdr_len = mbedtls_ssl_out_hdr_len( ssl );
+    size_t out_hdr_len = mbedtls_ssl_out_hdr_len(ssl);
 
-    if( transform == NULL )
-        return( (int) out_hdr_len );
+    if (transform == NULL) {
+        return (int) out_hdr_len;
+    }
 
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-    if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL )
-        return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
-#endif
 
-    switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) )
-    {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (transform->psa_alg == PSA_ALG_GCM ||
+        transform->psa_alg == PSA_ALG_CCM ||
+        transform->psa_alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 8) ||
+        transform->psa_alg == PSA_ALG_CHACHA20_POLY1305 ||
+        transform->psa_alg == MBEDTLS_SSL_NULL_CIPHER) {
+        transform_expansion = transform->minlen;
+    } else if (transform->psa_alg == PSA_ALG_CBC_NO_PADDING) {
+        (void) psa_get_key_attributes(transform->psa_key_enc, &attr);
+        key_type = psa_get_key_type(&attr);
+
+        block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type);
+
+        /* Expansion due to the addition of the MAC. */
+        transform_expansion += transform->maclen;
+
+        /* Expansion due to the addition of CBC padding;
+         * Theoretically up to 256 bytes, but we never use
+         * more than the block size of the underlying cipher. */
+        transform_expansion += block_size;
+
+        /* For TLS 1.2 or higher, an explicit IV is added
+         * after the record header. */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        transform_expansion += block_size;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("Unsupported psa_alg spotted in mbedtls_ssl_get_record_expansion()"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+#else
+    switch (mbedtls_cipher_get_cipher_mode(&transform->cipher_ctx_enc)) {
         case MBEDTLS_MODE_GCM:
         case MBEDTLS_MODE_CCM:
         case MBEDTLS_MODE_CHACHAPOLY:
@@ -5320,7 +5202,7 @@
         case MBEDTLS_MODE_CBC:
 
             block_size = mbedtls_cipher_get_block_size(
-                &transform->cipher_ctx_enc );
+                &transform->cipher_ctx_enc);
 
             /* Expansion due to the addition of the MAC. */
             transform_expansion += transform->maclen;
@@ -5330,26 +5212,27 @@
              * more than the block size of the underlying cipher. */
             transform_expansion += block_size;
 
-            /* For TLS 1.1 or higher, an explicit IV is added
+            /* For TLS 1.2 or higher, an explicit IV is added
              * after the record header. */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
-            if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
-                transform_expansion += block_size;
-#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+            transform_expansion += block_size;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
             break;
 
         default:
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+            MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    if( transform->out_cid_len != 0 )
+    if (transform->out_cid_len != 0) {
         transform_expansion += MBEDTLS_SSL_MAX_CID_EXPANSION;
+    }
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
-    return( (int)( out_hdr_len + transform_expansion ) );
+    return (int) (out_hdr_len + transform_expansion);
 }
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
@@ -5357,58 +5240,217 @@
  * Check record counters and renegotiate if they're above the limit.
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl )
+static int ssl_check_ctr_renegotiate(mbedtls_ssl_context *ssl)
 {
-    size_t ep_len = mbedtls_ssl_ep_len( ssl );
+    size_t ep_len = mbedtls_ssl_ep_len(ssl);
     int in_ctr_cmp;
     int out_ctr_cmp;
 
-    if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ||
+    if (mbedtls_ssl_is_handshake_over(ssl) == 0 ||
         ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ||
-        ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED )
-    {
-        return( 0 );
+        ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED) {
+        return 0;
     }
 
-    in_ctr_cmp = memcmp( ssl->in_ctr + ep_len,
-                        ssl->conf->renego_period + ep_len, 8 - ep_len );
-    out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len,
-                          ssl->conf->renego_period + ep_len, 8 - ep_len );
+    in_ctr_cmp = memcmp(ssl->in_ctr + ep_len,
+                        &ssl->conf->renego_period[ep_len],
+                        MBEDTLS_SSL_SEQUENCE_NUMBER_LEN - ep_len);
+    out_ctr_cmp = memcmp(&ssl->cur_out_ctr[ep_len],
+                         &ssl->conf->renego_period[ep_len],
+                         sizeof(ssl->cur_out_ctr) - ep_len);
 
-    if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 )
-    {
-        return( 0 );
+    if (in_ctr_cmp <= 0 && out_ctr_cmp <= 0) {
+        return 0;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) );
-    return( mbedtls_ssl_renegotiate( ssl ) );
+    MBEDTLS_SSL_DEBUG_MSG(1, ("record counter limit reached: renegotiate"));
+    return mbedtls_ssl_renegotiate(ssl);
 }
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
 
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_check_new_session_ticket(mbedtls_ssl_context *ssl)
+{
+
+    if ((ssl->in_hslen == mbedtls_ssl_hs_hdr_len(ssl)) ||
+        (ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET)) {
+        return 0;
+    }
+
+    ssl->keep_current_message = 1;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("NewSessionTicket received"));
+    mbedtls_ssl_handshake_set_state(ssl,
+                                    MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET);
+
+    return MBEDTLS_ERR_SSL_WANT_READ;
+}
+#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl)
+{
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("received post-handshake message"));
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        int ret = ssl_tls13_check_new_session_ticket(ssl);
+        if (ret != 0) {
+            return ret;
+        }
+    }
+#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
+
+    /* Fail in all other cases. */
+    return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+}
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+/* This function is called from mbedtls_ssl_read() when a handshake message is
+ * received after the initial handshake. In this context, handshake messages
+ * may only be sent for the purpose of initiating renegotiations.
+ *
+ * This function is introduced as a separate helper since the handling
+ * of post-handshake handshake messages changes significantly in TLS 1.3,
+ * and having a helper function allows to distinguish between TLS <= 1.2 and
+ * TLS 1.3 in the future without bloating the logic of mbedtls_ssl_read().
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls12_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    /*
+     * - For client-side, expect SERVER_HELLO_REQUEST.
+     * - For server-side, expect CLIENT_HELLO.
+     * - Fail (TLS) or silently drop record (DTLS) in other cases.
+     */
+
+#if defined(MBEDTLS_SSL_CLI_C)
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
+        (ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST ||
+         ssl->in_hslen  != mbedtls_ssl_hs_hdr_len(ssl))) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("handshake received (not HelloRequest)"));
+
+        /* With DTLS, drop the packet (probably from last handshake) */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+            return 0;
+        }
+#endif
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
+#endif /* MBEDTLS_SSL_CLI_C */
+
+#if defined(MBEDTLS_SSL_SRV_C)
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+        ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("handshake received (not ClientHello)"));
+
+        /* With DTLS, drop the packet (probably from last handshake) */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+            return 0;
+        }
+#endif
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
+#endif /* MBEDTLS_SSL_SRV_C */
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    /* Determine whether renegotiation attempt should be accepted */
+    if (!(ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
+          (ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
+           ssl->conf->allow_legacy_renegotiation ==
+           MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION))) {
+        /*
+         * Accept renegotiation request
+         */
+
+        /* DTLS clients need to know renego is server-initiated */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+            ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+            ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;
+        }
+#endif
+        ret = mbedtls_ssl_start_renegotiation(ssl);
+        if (ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
+            ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_start_renegotiation",
+                                  ret);
+            return ret;
+        }
+    } else
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+    {
+        /*
+         * Refuse renegotiation
+         */
+
+        MBEDTLS_SSL_DEBUG_MSG(3, ("refusing renegotiation, sending alert"));
+
+        if ((ret = mbedtls_ssl_send_alert_message(ssl,
+                                                  MBEDTLS_SSL_ALERT_LEVEL_WARNING,
+                                                  MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION)) != 0) {
+            return ret;
+        }
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl)
+{
+    /* Check protocol version and dispatch accordingly. */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
+        return ssl_tls13_handle_hs_message_post_handshake(ssl);
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    if (ssl->tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) {
+        return ssl_tls12_handle_hs_message_post_handshake(ssl);
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+    /* Should never happen */
+    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+}
+
 /*
  * Receive application data decrypted from the SSL layer
  */
-int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
+int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
 
-    if( ssl == NULL || ssl->conf == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl == NULL || ssl->conf == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> read"));
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
-            return( ret );
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) {
+            return ret;
+        }
 
-        if( ssl->handshake != NULL &&
-            ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
-        {
-            if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
-                return( ret );
+        if (ssl->handshake != NULL &&
+            ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) {
+            if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) {
+                return ret;
+            }
         }
     }
 #endif
@@ -5426,176 +5468,66 @@
      */
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
-    ret = ssl_check_ctr_renegotiate( ssl );
-    if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
-        ret != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret );
-        return( ret );
+    ret = ssl_check_ctr_renegotiate(ssl);
+    if (ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
+        ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_check_ctr_renegotiate", ret);
+        return ret;
     }
 #endif
 
-    if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
-    {
-        ret = mbedtls_ssl_handshake( ssl );
-        if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
-            ret != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret );
-            return( ret );
+    if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) {
+        ret = mbedtls_ssl_handshake(ssl);
+        if (ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
+            ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret);
+            return ret;
         }
     }
 
     /* Loop as long as no application data record is available */
-    while( ssl->in_offt == NULL )
-    {
+    while (ssl->in_offt == NULL) {
         /* Start timer if not already running */
-        if( ssl->f_get_timer != NULL &&
-            ssl->f_get_timer( ssl->p_timer ) == -1 )
-        {
-            mbedtls_ssl_set_timer( ssl, ssl->conf->read_timeout );
+        if (ssl->f_get_timer != NULL &&
+            ssl->f_get_timer(ssl->p_timer) == -1) {
+            mbedtls_ssl_set_timer(ssl, ssl->conf->read_timeout);
         }
 
-        if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
-        {
-            if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
-                return( 0 );
+        if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {
+            if (ret == MBEDTLS_ERR_SSL_CONN_EOF) {
+                return 0;
+            }
 
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
-            return( ret );
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
+            return ret;
         }
 
-        if( ssl->in_msglen  == 0 &&
-            ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA )
-        {
+        if (ssl->in_msglen  == 0 &&
+            ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA) {
             /*
              * OpenSSL sends empty messages to randomize the IV
              */
-            if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
-            {
-                if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
-                    return( 0 );
+            if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {
+                if (ret == MBEDTLS_ERR_SSL_CONN_EOF) {
+                    return 0;
+                }
 
-                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
-                return( ret );
+                MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
+                return ret;
             }
         }
 
-        if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) );
-
-            /*
-             * - For client-side, expect SERVER_HELLO_REQUEST.
-             * - For server-side, expect CLIENT_HELLO.
-             * - Fail (TLS) or silently drop record (DTLS) in other cases.
-             */
-
-#if defined(MBEDTLS_SSL_CLI_C)
-            if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
-                ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST ||
-                  ssl->in_hslen  != mbedtls_ssl_hs_hdr_len( ssl ) ) )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) );
-
-                /* With DTLS, drop the packet (probably from last handshake) */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-                if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-                {
-                    continue;
-                }
-#endif
-                return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
-            }
-#endif /* MBEDTLS_SSL_CLI_C */
-
-#if defined(MBEDTLS_SSL_SRV_C)
-            if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
-                ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) );
-
-                /* With DTLS, drop the packet (probably from last handshake) */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-                if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-                {
-                    continue;
-                }
-#endif
-                return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
-            }
-#endif /* MBEDTLS_SSL_SRV_C */
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-            /* Determine whether renegotiation attempt should be accepted */
-            if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
-                    ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-                      ssl->conf->allow_legacy_renegotiation ==
-                                                   MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) )
-            {
-                /*
-                 * Accept renegotiation request
-                 */
-
-                /* DTLS clients need to know renego is server-initiated */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-                if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-                    ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
-                {
-                    ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;
-                }
-#endif
-                ret = mbedtls_ssl_start_renegotiation( ssl );
-                if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
-                    ret != 0 )
-                {
-                    MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation",
-                                           ret );
-                    return( ret );
-                }
-            }
-            else
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
-            {
-                /*
-                 * Refuse renegotiation
-                 */
-
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) );
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-                if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
-                {
-                    /* SSLv3 does not have a "no_renegotiation" warning, so
-                       we send a fatal alert and abort the connection. */
-                    mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                                    MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
-                    return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
-                }
-                else
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_2)
-                if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 )
-                {
-                    if( ( ret = mbedtls_ssl_send_alert_message( ssl,
-                                    MBEDTLS_SSL_ALERT_LEVEL_WARNING,
-                                    MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 )
-                    {
-                        return( ret );
-                    }
-                }
-                else
-#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 ||
-          MBEDTLS_SSL_PROTO_TLS1_2 */
-                {
-                    MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-                    return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-                }
+        if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) {
+            ret = ssl_handle_hs_message_post_handshake(ssl);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "ssl_handle_hs_message_post_handshake",
+                                      ret);
+                return ret;
             }
 
-            /* At this point, we don't know whether the renegotiation has been
-             * completed or not. The cases to consider are the following:
+            /* At this point, we don't know whether the renegotiation triggered
+             * by the post-handshake message has been completed or not. The cases
+             * to consider are the following:
              * 1) The renegotiation is complete. In this case, no new record
              *    has been read yet.
              * 2) The renegotiation is incomplete because the client received
@@ -5603,7 +5535,8 @@
              * 3) The renegotiation is incomplete because the client received
              *    a non-handshake, non-application data message while awaiting
              *    the ServerHello.
-             * In each of these case, looping will be the proper action:
+             *
+             * In each of these cases, looping will be the proper action:
              * - For 1), the next iteration will read a new record and check
              *   if it's application data.
              * - For 2), the loop condition isn't satisfied as application data
@@ -5612,87 +5545,81 @@
              *   will re-deliver the message that was held back by the client
              *   when expecting the ServerHello.
              */
+
             continue;
         }
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
-        else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
-        {
-            if( ssl->conf->renego_max_records >= 0 )
-            {
-                if( ++ssl->renego_records_seen > ssl->conf->renego_max_records )
-                {
-                    MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, "
-                                        "but not honored by client" ) );
-                    return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+        else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) {
+            if (ssl->conf->renego_max_records >= 0) {
+                if (++ssl->renego_records_seen > ssl->conf->renego_max_records) {
+                    MBEDTLS_SSL_DEBUG_MSG(1, ("renegotiation requested, "
+                                              "but not honored by client"));
+                    return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
                 }
             }
         }
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
 
         /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */
-        if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) );
-            return( MBEDTLS_ERR_SSL_WANT_READ );
+        if (ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("ignoring non-fatal non-closure alert"));
+            return MBEDTLS_ERR_SSL_WANT_READ;
         }
 
-        if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) );
-            return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+        if (ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad application data message"));
+            return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
         }
 
         ssl->in_offt = ssl->in_msg;
 
         /* We're going to return something now, cancel timer,
          * except if handshake (renegotiation) is in progress */
-        if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
-            mbedtls_ssl_set_timer( ssl, 0 );
+        if (mbedtls_ssl_is_handshake_over(ssl) == 1) {
+            mbedtls_ssl_set_timer(ssl, 0);
+        }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
         /* If we requested renego but received AppData, resend HelloRequest.
          * Do it now, after setting in_offt, to avoid taking this branch
          * again if ssl_write_hello_request() returns WANT_WRITE */
 #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
-        if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
-            ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
-        {
-            if( ( ret = mbedtls_ssl_resend_hello_request( ssl ) ) != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend_hello_request",
-                                       ret );
-                return( ret );
+        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+            ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) {
+            if ((ret = mbedtls_ssl_resend_hello_request(ssl)) != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_resend_hello_request",
+                                      ret);
+                return ret;
             }
         }
 #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
     }
 
-    n = ( len < ssl->in_msglen )
+    n = (len < ssl->in_msglen)
         ? len : ssl->in_msglen;
 
-    memcpy( buf, ssl->in_offt, n );
-    ssl->in_msglen -= n;
+    if (len != 0) {
+        memcpy(buf, ssl->in_offt, n);
+        ssl->in_msglen -= n;
+    }
 
     /* Zeroising the plaintext buffer to erase unused application data
        from the memory. */
-    mbedtls_platform_zeroize( ssl->in_offt, n );
+    mbedtls_platform_zeroize(ssl->in_offt, n);
 
-    if( ssl->in_msglen == 0 )
-    {
+    if (ssl->in_msglen == 0) {
         /* all bytes consumed */
         ssl->in_offt = NULL;
         ssl->keep_current_message = 0;
-    }
-    else
-    {
+    } else {
         /* more data available */
         ssl->in_offt += n;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= read"));
 
-    return( (int) n );
+    return (int) n;
 }
 
 /*
@@ -5708,50 +5635,42 @@
  * corresponding return code is 0 on success.
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_real( mbedtls_ssl_context *ssl,
-                           const unsigned char *buf, size_t len )
+static int ssl_write_real(mbedtls_ssl_context *ssl,
+                          const unsigned char *buf, size_t len)
 {
-    int ret = mbedtls_ssl_get_max_out_record_payload( ssl );
+    int ret = mbedtls_ssl_get_max_out_record_payload(ssl);
     const size_t max_len = (size_t) ret;
 
-    if( ret < 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret );
-        return( ret );
+    if (ret < 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_max_out_record_payload", ret);
+        return ret;
     }
 
-    if( len > max_len )
-    {
+    if (len > max_len) {
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-        if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) "
-                                "maximum fragment length: %" MBEDTLS_PRINTF_SIZET
-                                " > %" MBEDTLS_PRINTF_SIZET,
-                                len, max_len ) );
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-        }
-        else
+        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("fragment larger than the (negotiated) "
+                                      "maximum fragment length: %" MBEDTLS_PRINTF_SIZET
+                                      " > %" MBEDTLS_PRINTF_SIZET,
+                                      len, max_len));
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        } else
 #endif
-            len = max_len;
+        len = max_len;
     }
 
-    if( ssl->out_left != 0 )
-    {
+    if (ssl->out_left != 0) {
         /*
          * The user has previously tried to send the data and
          * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially
          * written. In this case, we expect the high-level write function
          * (e.g. mbedtls_ssl_write()) to be called with the same parameters
          */
-        if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret );
-            return( ret );
+        if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flush_output", ret);
+            return ret;
         }
-    }
-    else
-    {
+    } else {
         /*
          * The user is trying to send a message the first time, so we need to
          * copy the data into the internal buffers and setup the data structure
@@ -5759,177 +5678,154 @@
          */
         ssl->out_msglen  = len;
         ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA;
-        memcpy( ssl->out_msg, buf, len );
+        if (len > 0) {
+            memcpy(ssl->out_msg, buf, len);
+        }
 
-        if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
-            return( ret );
+        if ((ret = mbedtls_ssl_write_record(ssl, SSL_FORCE_FLUSH)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_record", ret);
+            return ret;
         }
     }
 
-    return( (int) len );
+    return (int) len;
 }
 
 /*
- * Write application data, doing 1/n-1 splitting if necessary.
- *
- * With non-blocking I/O, ssl_write_real() may return WANT_WRITE,
- * then the caller will call us again with the same arguments, so
- * remember whether we already did the split or not.
- */
-#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_split( mbedtls_ssl_context *ssl,
-                            const unsigned char *buf, size_t len )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    if( ssl->conf->cbc_record_splitting ==
-            MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ||
-        len <= 1 ||
-        ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_1 ||
-        mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc )
-                                != MBEDTLS_MODE_CBC )
-    {
-        return( ssl_write_real( ssl, buf, len ) );
-    }
-
-    if( ssl->split_done == 0 )
-    {
-        if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 )
-            return( ret );
-        ssl->split_done = 1;
-    }
-
-    if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 )
-        return( ret );
-    ssl->split_done = 0;
-
-    return( ret + 1 );
-}
-#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */
-
-/*
  * Write application data (public-facing wrapper)
  */
-int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len )
+int mbedtls_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write"));
 
-    if( ssl == NULL || ssl->conf == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl == NULL || ssl->conf == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret );
-        return( ret );
+    if ((ret = ssl_check_ctr_renegotiate(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_check_ctr_renegotiate", ret);
+        return ret;
     }
 #endif
 
-    if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
-    {
-        if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret );
-            return( ret );
+    if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) {
+        if ((ret = mbedtls_ssl_handshake(ssl)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret);
+            return ret;
         }
     }
 
-#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
-    ret = ssl_write_split( ssl, buf, len );
-#else
-    ret = ssl_write_real( ssl, buf, len );
-#endif
+    ret = ssl_write_real(ssl, buf, len);
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write"));
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Notify the peer that the connection is being closed
  */
-int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( ssl == NULL || ssl->conf == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl == NULL || ssl->conf == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write close notify"));
 
-    if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
-    {
-        if( ( ret = mbedtls_ssl_send_alert_message( ssl,
-                        MBEDTLS_SSL_ALERT_LEVEL_WARNING,
-                        MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret );
-            return( ret );
+    if (mbedtls_ssl_is_handshake_over(ssl) == 1) {
+        if ((ret = mbedtls_ssl_send_alert_message(ssl,
+                                                  MBEDTLS_SSL_ALERT_LEVEL_WARNING,
+                                                  MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_send_alert_message", ret);
+            return ret;
         }
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write close notify" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write close notify"));
 
-    return( 0 );
+    return 0;
 }
 
-void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform )
+void mbedtls_ssl_transform_free(mbedtls_ssl_transform *transform)
 {
-    if( transform == NULL )
+    if (transform == NULL) {
         return;
+    }
 
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-    deflateEnd( &transform->ctx_deflate );
-    inflateEnd( &transform->ctx_inflate );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_destroy_key(transform->psa_key_enc);
+    psa_destroy_key(transform->psa_key_dec);
+#else
+    mbedtls_cipher_free(&transform->cipher_ctx_enc);
+    mbedtls_cipher_free(&transform->cipher_ctx_dec);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_destroy_key(transform->psa_mac_enc);
+    psa_destroy_key(transform->psa_mac_dec);
+#else
+    mbedtls_md_free(&transform->md_ctx_enc);
+    mbedtls_md_free(&transform->md_ctx_dec);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 #endif
 
-    mbedtls_cipher_free( &transform->cipher_ctx_enc );
-    mbedtls_cipher_free( &transform->cipher_ctx_dec );
+    mbedtls_platform_zeroize(transform, sizeof(mbedtls_ssl_transform));
+}
 
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
-    mbedtls_md_free( &transform->md_ctx_enc );
-    mbedtls_md_free( &transform->md_ctx_dec );
-#endif
+void mbedtls_ssl_set_inbound_transform(mbedtls_ssl_context *ssl,
+                                       mbedtls_ssl_transform *transform)
+{
+    ssl->transform_in = transform;
+    memset(ssl->in_ctr, 0, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN);
+}
 
-    mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) );
+void mbedtls_ssl_set_outbound_transform(mbedtls_ssl_context *ssl,
+                                        mbedtls_ssl_transform *transform)
+{
+    ssl->transform_out = transform;
+    memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr));
 }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
 
-void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl )
+void mbedtls_ssl_buffering_free(mbedtls_ssl_context *ssl)
 {
     unsigned offset;
     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
 
-    if( hs == NULL )
+    if (hs == NULL) {
         return;
+    }
 
-    ssl_free_buffered_record( ssl );
+    ssl_free_buffered_record(ssl);
 
-    for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ )
-        ssl_buffering_free_slot( ssl, offset );
+    for (offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++) {
+        ssl_buffering_free_slot(ssl, offset);
+    }
 }
 
-static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
-                                     uint8_t slot )
+static void ssl_buffering_free_slot(mbedtls_ssl_context *ssl,
+                                    uint8_t slot)
 {
     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
     mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot];
 
-    if( slot >= MBEDTLS_SSL_MAX_BUFFERED_HS )
+    if (slot >= MBEDTLS_SSL_MAX_BUFFERED_HS) {
         return;
+    }
 
-    if( hs_buf->is_valid == 1 )
-    {
+    if (hs_buf->is_valid == 1) {
         hs->buffering.total_bytes_buffered -= hs_buf->data_len;
-        mbedtls_platform_zeroize( hs_buf->data, hs_buf->data_len );
-        mbedtls_free( hs_buf->data );
-        memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
+        mbedtls_platform_zeroize(hs_buf->data, hs_buf->data_len);
+        mbedtls_free(hs_buf->data);
+        memset(hs_buf, 0, sizeof(mbedtls_ssl_hs_buffer));
     }
 }
 
@@ -5940,52 +5836,82 @@
  * and, for DTLS, to/from TLS equivalent.
  *
  * For TLS this is the identity.
- * For DTLS, use 1's complement (v -> 255 - v, and then map as follows:
- * 1.0 <-> 3.2      (DTLS 1.0 is based on TLS 1.1)
+ * For DTLS, map as follows, then use 1's complement (v -> ~v):
  * 1.x <-> 3.x+1    for x != 0 (DTLS 1.2 based on TLS 1.2)
+ *                  DTLS 1.0 is stored as TLS 1.1 internally
  */
-void mbedtls_ssl_write_version( int major, int minor, int transport,
-                        unsigned char ver[2] )
+void mbedtls_ssl_write_version(unsigned char version[2], int transport,
+                               mbedtls_ssl_protocol_version tls_version)
 {
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        if( minor == MBEDTLS_SSL_MINOR_VERSION_2 )
-            --minor; /* DTLS 1.0 stored as TLS 1.1 internally */
-
-        ver[0] = (unsigned char)( 255 - ( major - 2 ) );
-        ver[1] = (unsigned char)( 255 - ( minor - 1 ) );
+    if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        tls_version =
+            ~(tls_version - (tls_version == 0x0302 ? 0x0202 : 0x0201));
     }
-    else
 #else
     ((void) transport);
 #endif
-    {
-        ver[0] = (unsigned char) major;
-        ver[1] = (unsigned char) minor;
-    }
+    MBEDTLS_PUT_UINT16_BE(tls_version, version, 0);
 }
 
-void mbedtls_ssl_read_version( int *major, int *minor, int transport,
-                       const unsigned char ver[2] )
+uint16_t mbedtls_ssl_read_version(const unsigned char version[2],
+                                  int transport)
 {
+    uint16_t tls_version = MBEDTLS_GET_UINT16_BE(version, 0);
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        *major = 255 - ver[0] + 2;
-        *minor = 255 - ver[1] + 1;
-
-        if( *minor == MBEDTLS_SSL_MINOR_VERSION_1 )
-            ++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */
+    if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        tls_version =
+            ~(tls_version - (tls_version == 0xfeff ? 0x0202 : 0x0201));
     }
-    else
 #else
     ((void) transport);
 #endif
-    {
-        *major = ver[0];
-        *minor = ver[1];
+    return tls_version;
+}
+
+/*
+ * Send pending fatal alert.
+ * 0,   No alert message.
+ * !0,  if mbedtls_ssl_send_alert_message() returned in error, the error code it
+ *      returned, ssl->alert_reason otherwise.
+ */
+int mbedtls_ssl_handle_pending_alert(mbedtls_ssl_context *ssl)
+{
+    int ret;
+
+    /* No pending alert, return success*/
+    if (ssl->send_alert == 0) {
+        return 0;
     }
+
+    ret = mbedtls_ssl_send_alert_message(ssl,
+                                         MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                         ssl->alert_type);
+
+    /* If mbedtls_ssl_send_alert_message() returned with MBEDTLS_ERR_SSL_WANT_WRITE,
+     * do not clear the alert to be able to send it later.
+     */
+    if (ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
+        ssl->send_alert = 0;
+    }
+
+    if (ret != 0) {
+        return ret;
+    }
+
+    return ssl->alert_reason;
+}
+
+/*
+ * Set pending fatal alert flag.
+ */
+void mbedtls_ssl_pend_fatal_alert(mbedtls_ssl_context *ssl,
+                                  unsigned char alert_type,
+                                  int alert_reason)
+{
+    ssl->send_alert = 1;
+    ssl->alert_type = alert_type;
+    ssl->alert_reason = alert_reason;
 }
 
 #endif /* MBEDTLS_SSL_TLS_C */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_srv.c b/lib/libmbedtls/mbedtls/library/ssl_srv.c
deleted file mode 100644
index 2efb13c..0000000
--- a/lib/libmbedtls/mbedtls/library/ssl_srv.c
+++ /dev/null
@@ -1,4855 +0,0 @@
-/*
- *  SSLv3/TLSv1 server-side functions
- *
- *  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.
- */
-
-#include "common.h"
-
-#if defined(MBEDTLS_SSL_SRV_C)
-
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free      free
-#endif
-
-#include "mbedtls/ssl.h"
-#include "mbedtls/ssl_internal.h"
-#include "mbedtls/debug.h"
-#include "mbedtls/error.h"
-#include "mbedtls/platform_util.h"
-#include "constant_time_internal.h"
-#include "mbedtls/constant_time.h"
-
-#include <string.h>
-
-#if defined(MBEDTLS_ECP_C)
-#include "mbedtls/ecp.h"
-#endif
-
-#if defined(MBEDTLS_HAVE_TIME)
-#include "mbedtls/platform_time.h"
-#endif
-
-#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
-int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl,
-                                 const unsigned char *info,
-                                 size_t ilen )
-{
-    if( ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    mbedtls_free( ssl->cli_id );
-
-    if( ( ssl->cli_id = mbedtls_calloc( 1, ilen ) ) == NULL )
-        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
-
-    memcpy( ssl->cli_id, info, ilen );
-    ssl->cli_id_len = ilen;
-
-    return( 0 );
-}
-
-void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf,
-                           mbedtls_ssl_cookie_write_t *f_cookie_write,
-                           mbedtls_ssl_cookie_check_t *f_cookie_check,
-                           void *p_cookie )
-{
-    conf->f_cookie_write = f_cookie_write;
-    conf->f_cookie_check = f_cookie_check;
-    conf->p_cookie       = p_cookie;
-}
-#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
-
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
-                                     const unsigned char *buf,
-                                     size_t len )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t servername_list_size, hostname_len;
-    const unsigned char *p;
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) );
-
-    if( len < 2 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-    servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
-    if( servername_list_size + 2 != len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    p = buf + 2;
-    while( servername_list_size > 2 )
-    {
-        hostname_len = ( ( p[1] << 8 ) | p[2] );
-        if( hostname_len + 3 > servername_list_size )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-        }
-
-        if( p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME )
-        {
-            ret = ssl->conf->f_sni( ssl->conf->p_sni,
-                                    ssl, p + 3, hostname_len );
-            if( ret != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret );
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                        MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME );
-                return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-            }
-            return( 0 );
-        }
-
-        servername_list_size -= hostname_len + 3;
-        p += hostname_len + 3;
-    }
-
-    if( servername_list_size != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_conf_has_psk_or_cb( mbedtls_ssl_config const *conf )
-{
-    if( conf->f_psk != NULL )
-        return( 1 );
-
-    if( conf->psk_identity_len == 0 || conf->psk_identity == NULL )
-        return( 0 );
-
-    if( conf->psk != NULL && conf->psk_len != 0 )
-        return( 1 );
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ! mbedtls_svc_key_id_is_null( conf->psk_opaque ) )
-        return( 1 );
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-    return( 0 );
-}
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl )
-{
-    if( ssl->conf->f_psk != NULL )
-    {
-        /* If we've used a callback to select the PSK,
-         * the static configuration is irrelevant. */
-
-        if( ! mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) )
-            return( 1 );
-
-        return( 0 );
-    }
-
-    if( ! mbedtls_svc_key_id_is_null( ssl->conf->psk_opaque ) )
-        return( 1 );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
-                                         const unsigned char *buf,
-                                         size_t len )
-{
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
-    {
-        /* Check verify-data in constant-time. The length OTOH is no secret */
-        if( len    != 1 + ssl->verify_data_len ||
-            buf[0] !=     ssl->verify_data_len ||
-            mbedtls_ct_memcmp( buf + 1, ssl->peer_verify_data,
-                          ssl->verify_data_len ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-        }
-    }
-    else
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
-    {
-        if( len != 1 || buf[0] != 0x0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-        }
-
-        ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION;
-    }
-
-    return( 0 );
-}
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
-    defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-
-/*
- * Status of the implementation of signature-algorithms extension:
- *
- * Currently, we are only considering the signature-algorithm extension
- * to pick a ciphersuite which allows us to send the ServerKeyExchange
- * message with a signature-hash combination that the user allows.
- *
- * We do *not* check whether all certificates in our certificate
- * chain are signed with an allowed signature-hash pair.
- * This needs to be done at a later stage.
- *
- */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl,
-                                               const unsigned char *buf,
-                                               size_t len )
-{
-    size_t sig_alg_list_size;
-
-    const unsigned char *p;
-    const unsigned char *end = buf + len;
-
-    mbedtls_md_type_t md_cur;
-    mbedtls_pk_type_t sig_cur;
-
-    if ( len < 2 ) {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-    sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
-    if( sig_alg_list_size + 2 != len ||
-        sig_alg_list_size % 2 != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    /* Currently we only guarantee signing the ServerKeyExchange message according
-     * to the constraints specified in this extension (see above), so it suffices
-     * to remember only one suitable hash for each possible signature algorithm.
-     *
-     * This will change when we also consider certificate signatures,
-     * in which case we will need to remember the whole signature-hash
-     * pair list from the extension.
-     */
-
-    for( p = buf + 2; p < end; p += 2 )
-    {
-        /* Silently ignore unknown signature or hash algorithms. */
-
-        if( ( sig_cur = mbedtls_ssl_pk_alg_from_sig( p[1] ) ) == MBEDTLS_PK_NONE )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext"
-                                        " unknown sig alg encoding %d", p[1] ) );
-            continue;
-        }
-
-        /* Check if we support the hash the user proposes */
-        md_cur = mbedtls_ssl_md_alg_from_hash( p[0] );
-        if( md_cur == MBEDTLS_MD_NONE )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:"
-                                        " unknown hash alg encoding %d", p[0] ) );
-            continue;
-        }
-
-        if( mbedtls_ssl_check_sig_hash( ssl, md_cur ) == 0 )
-        {
-            mbedtls_ssl_sig_hash_set_add( &ssl->handshake->hash_algs, sig_cur, md_cur );
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:"
-                                        " match sig %u and hash %u",
-                                        (unsigned) sig_cur, (unsigned) md_cur ) );
-        }
-        else
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: "
-                                        "hash alg %u not supported", (unsigned) md_cur ) );
-        }
-    }
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
-          MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
-
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl,
-                                                const unsigned char *buf,
-                                                size_t len )
-{
-    size_t list_size, our_size;
-    const unsigned char *p;
-    const mbedtls_ecp_curve_info *curve_info, **curves;
-
-    if ( len < 2 ) {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-    list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
-    if( list_size + 2 != len ||
-        list_size % 2 != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    /* Should never happen unless client duplicates the extension */
-    if( ssl->handshake->curves != NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    /* Don't allow our peer to make us allocate too much memory,
-     * and leave room for a final 0 */
-    our_size = list_size / 2 + 1;
-    if( our_size > MBEDTLS_ECP_DP_MAX )
-        our_size = MBEDTLS_ECP_DP_MAX;
-
-    if( ( curves = mbedtls_calloc( our_size, sizeof( *curves ) ) ) == NULL )
-    {
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
-        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
-    }
-
-    ssl->handshake->curves = curves;
-
-    p = buf + 2;
-    while( list_size > 0 && our_size > 1 )
-    {
-        curve_info = mbedtls_ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] );
-
-        if( curve_info != NULL )
-        {
-            *curves++ = curve_info;
-            our_size--;
-        }
-
-        list_size -= 2;
-        p += 2;
-    }
-
-    return( 0 );
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl,
-                                              const unsigned char *buf,
-                                              size_t len )
-{
-    size_t list_size;
-    const unsigned char *p;
-
-    if( len == 0 || (size_t)( buf[0] + 1 ) != len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-    list_size = buf[0];
-
-    p = buf + 1;
-    while( list_size > 0 )
-    {
-        if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED ||
-            p[0] == MBEDTLS_ECP_PF_COMPRESSED )
-        {
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
-            ssl->handshake->ecdh_ctx.point_format = p[0];
-#endif
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-            ssl->handshake->ecjpake_ctx.point_format = p[0];
-#endif
-            MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) );
-            return( 0 );
-        }
-
-        list_size--;
-        p++;
-    }
-
-    return( 0 );
-}
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
-          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
-                                   const unsigned char *buf,
-                                   size_t len )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) );
-        return( 0 );
-    }
-
-    if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx,
-                                                buf, len ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-        return( ret );
-    }
-
-    /* Only mark the extension as OK when we're sure it is */
-    ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl,
-                                              const unsigned char *buf,
-                                              size_t len )
-{
-    if( len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    ssl->session_negotiate->mfl_code = buf[0];
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl,
-                              const unsigned char *buf,
-                              size_t len )
-{
-    size_t peer_cid_len;
-
-    /* CID extension only makes sense in DTLS */
-    if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    /*
-     * Quoting draft-ietf-tls-dtls-connection-id-05
-     * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05
-     *
-     *   struct {
-     *      opaque cid<0..2^8-1>;
-     *   } ConnectionId;
-    */
-
-    if( len < 1 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    peer_cid_len = *buf++;
-    len--;
-
-    if( len != peer_cid_len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    /* Ignore CID if the user has disabled its use. */
-    if( ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED )
-    {
-        /* Leave ssl->handshake->cid_in_use in its default
-         * value of MBEDTLS_SSL_CID_DISABLED. */
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "Client sent CID extension, but CID disabled" ) );
-        return( 0 );
-    }
-
-    if( peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED;
-    ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len;
-    memcpy( ssl->handshake->peer_cid, buf, peer_cid_len );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use of CID extension negotiated" ) );
-    MBEDTLS_SSL_DEBUG_BUF( 3, "Client CID", buf, peer_cid_len );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl,
-                                         const unsigned char *buf,
-                                         size_t len )
-{
-    if( len != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    ((void) buf);
-
-    if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED )
-        ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
-
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
-                                      const unsigned char *buf,
-                                      size_t len )
-{
-    if( len != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    ((void) buf);
-
-    if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED &&
-        ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 )
-    {
-        ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED;
-    }
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
-
-#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl,
-                                      const unsigned char *buf,
-                                      size_t len )
-{
-    if( len != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    ((void) buf);
-
-    if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED &&
-        ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 )
-    {
-        ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED;
-    }
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
-                                         unsigned char *buf,
-                                         size_t len )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_ssl_session session;
-
-    mbedtls_ssl_session_init( &session );
-
-    if( ssl->conf->f_ticket_parse == NULL ||
-        ssl->conf->f_ticket_write == NULL )
-    {
-        return( 0 );
-    }
-
-    /* Remember the client asked us to send a new ticket */
-    ssl->handshake->new_session_ticket = 1;
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %" MBEDTLS_PRINTF_SIZET, len ) );
-
-    if( len == 0 )
-        return( 0 );
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket rejected: renegotiating" ) );
-        return( 0 );
-    }
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
-
-    /*
-     * Failures are ok: just ignore the ticket and proceed.
-     */
-    if( ( ret = ssl->conf->f_ticket_parse( ssl->conf->p_ticket, &session,
-                                           buf, len ) ) != 0 )
-    {
-        mbedtls_ssl_session_free( &session );
-
-        if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is not authentic" ) );
-        else if( ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED )
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is expired" ) );
-        else
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_parse", ret );
-
-        return( 0 );
-    }
-
-    /*
-     * Keep the session ID sent by the client, since we MUST send it back to
-     * inform them we're accepting the ticket  (RFC 5077 section 3.4)
-     */
-    session.id_len = ssl->session_negotiate->id_len;
-    memcpy( &session.id, ssl->session_negotiate->id, session.id_len );
-
-    mbedtls_ssl_session_free( ssl->session_negotiate );
-    memcpy( ssl->session_negotiate, &session, sizeof( mbedtls_ssl_session ) );
-
-    /* Zeroize instead of free as we copied the content */
-    mbedtls_platform_zeroize( &session, sizeof( mbedtls_ssl_session ) );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from ticket" ) );
-
-    ssl->handshake->resume = 1;
-
-    /* Don't send a new ticket after all, this one is OK */
-    ssl->handshake->new_session_ticket = 0;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_SESSION_TICKETS */
-
-#if defined(MBEDTLS_SSL_ALPN)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
-                               const unsigned char *buf, size_t len )
-{
-    size_t list_len, cur_len, ours_len;
-    const unsigned char *theirs, *start, *end;
-    const char **ours;
-
-    /* If ALPN not configured, just ignore the extension */
-    if( ssl->conf->alpn_list == NULL )
-        return( 0 );
-
-    /*
-     * opaque ProtocolName<1..2^8-1>;
-     *
-     * struct {
-     *     ProtocolName protocol_name_list<2..2^16-1>
-     * } ProtocolNameList;
-     */
-
-    /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */
-    if( len < 4 )
-    {
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    list_len = ( buf[0] << 8 ) | buf[1];
-    if( list_len != len - 2 )
-    {
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    /*
-     * Validate peer's list (lengths)
-     */
-    start = buf + 2;
-    end = buf + len;
-    for( theirs = start; theirs != end; theirs += cur_len )
-    {
-        cur_len = *theirs++;
-
-        /* Current identifier must fit in list */
-        if( cur_len > (size_t)( end - theirs ) )
-        {
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-        }
-
-        /* Empty strings MUST NOT be included */
-        if( cur_len == 0 )
-        {
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-        }
-    }
-
-    /*
-     * Use our order of preference
-     */
-    for( ours = ssl->conf->alpn_list; *ours != NULL; ours++ )
-    {
-        ours_len = strlen( *ours );
-        for( theirs = start; theirs != end; theirs += cur_len )
-        {
-            cur_len = *theirs++;
-
-            if( cur_len == ours_len &&
-                memcmp( theirs, *ours, cur_len ) == 0 )
-            {
-                ssl->alpn_chosen = *ours;
-                return( 0 );
-            }
-        }
-    }
-
-    /* If we get there, no match was found */
-    mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                            MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL );
-    return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-}
-#endif /* MBEDTLS_SSL_ALPN */
-
-#if defined(MBEDTLS_SSL_DTLS_SRTP)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl,
-                                   const unsigned char *buf,
-                                   size_t len )
-{
-    mbedtls_ssl_srtp_profile client_protection = MBEDTLS_TLS_SRTP_UNSET;
-    size_t i,j;
-    size_t profile_length;
-    uint16_t mki_length;
-    /*! 2 bytes for profile length and 1 byte for mki len */
-    const size_t size_of_lengths = 3;
-
-    /* If use_srtp is not configured, just ignore the extension */
-    if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) ||
-        ( ssl->conf->dtls_srtp_profile_list == NULL ) ||
-        ( ssl->conf->dtls_srtp_profile_list_len == 0 ) )
-    {
-        return( 0 );
-    }
-
-    /* RFC5764 section 4.1.1
-     * uint8 SRTPProtectionProfile[2];
-     *
-     * struct {
-     *   SRTPProtectionProfiles SRTPProtectionProfiles;
-     *   opaque srtp_mki<0..255>;
-     * } UseSRTPData;
-
-     * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>;
-     */
-
-    /*
-     * Min length is 5: at least one protection profile(2 bytes)
-     *                  and length(2 bytes) + srtp_mki length(1 byte)
-     * Check here that we have at least 2 bytes of protection profiles length
-     * and one of srtp_mki length
-     */
-    if( len < size_of_lengths )
-    {
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-   ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET;
-
-    /* first 2 bytes are protection profile length(in bytes) */
-    profile_length = ( buf[0] << 8 ) | buf[1];
-    buf += 2;
-
-    /* The profile length cannot be bigger than input buffer size - lengths fields */
-    if( profile_length > len - size_of_lengths ||
-        profile_length % 2 != 0 ) /* profiles are 2 bytes long, so the length must be even */
-    {
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-    /*
-     * parse the extension list values are defined in
-     * http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml
-     */
-    for( j = 0; j < profile_length; j += 2 )
-    {
-        uint16_t protection_profile_value = buf[j] << 8 | buf[j + 1];
-        client_protection = mbedtls_ssl_check_srtp_profile_value( protection_profile_value );
-
-        if( client_protection != MBEDTLS_TLS_SRTP_UNSET )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "found srtp profile: %s",
-                                    mbedtls_ssl_get_srtp_profile_as_string(
-                                            client_protection ) ) );
-        }
-        else
-        {
-            continue;
-        }
-        /* check if suggested profile is in our list */
-        for( i = 0; i < ssl->conf->dtls_srtp_profile_list_len; i++)
-        {
-            if( client_protection == ssl->conf->dtls_srtp_profile_list[i] )
-            {
-                ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i];
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "selected srtp profile: %s",
-                                            mbedtls_ssl_get_srtp_profile_as_string(
-                                                    client_protection ) ) );
-                break;
-            }
-        }
-        if( ssl->dtls_srtp_info.chosen_dtls_srtp_profile != MBEDTLS_TLS_SRTP_UNSET )
-            break;
-    }
-    buf += profile_length; /* buf points to the mki length */
-    mki_length = *buf;
-    buf++;
-
-    if( mki_length > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH ||
-        mki_length + profile_length + size_of_lengths != len )
-    {
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    /* Parse the mki only if present and mki is supported locally */
-    if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED &&
-          mki_length > 0 )
-    {
-        ssl->dtls_srtp_info.mki_len = mki_length;
-
-        memcpy( ssl->dtls_srtp_info.mki_value, buf, mki_length );
-
-        MBEDTLS_SSL_DEBUG_BUF( 3, "using mki",  ssl->dtls_srtp_info.mki_value,
-                                                ssl->dtls_srtp_info.mki_len );
-    }
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_DTLS_SRTP */
-
-/*
- * Auxiliary functions for ServerHello parsing and related actions
- */
-
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-/*
- * Return 0 if the given key uses one of the acceptable curves, -1 otherwise
- */
-#if defined(MBEDTLS_ECDSA_C)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_check_key_curve( mbedtls_pk_context *pk,
-                                const mbedtls_ecp_curve_info **curves )
-{
-    const mbedtls_ecp_curve_info **crv = curves;
-    mbedtls_ecp_group_id grp_id = mbedtls_pk_ec( *pk )->grp.id;
-
-    while( *crv != NULL )
-    {
-        if( (*crv)->grp_id == grp_id )
-            return( 0 );
-        crv++;
-    }
-
-    return( -1 );
-}
-#endif /* MBEDTLS_ECDSA_C */
-
-/*
- * Try picking a certificate for this ciphersuite,
- * return 0 on success and -1 on failure.
- */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_pick_cert( mbedtls_ssl_context *ssl,
-                          const mbedtls_ssl_ciphersuite_t * ciphersuite_info )
-{
-    mbedtls_ssl_key_cert *cur, *list, *fallback = NULL;
-    mbedtls_pk_type_t pk_alg =
-        mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
-    uint32_t flags;
-
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-    if( ssl->handshake->sni_key_cert != NULL )
-        list = ssl->handshake->sni_key_cert;
-    else
-#endif
-        list = ssl->conf->key_cert;
-
-    if( pk_alg == MBEDTLS_PK_NONE )
-        return( 0 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite requires certificate" ) );
-
-    if( list == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "server has no certificate" ) );
-        return( -1 );
-    }
-
-    for( cur = list; cur != NULL; cur = cur->next )
-    {
-        flags = 0;
-        MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate",
-                          cur->cert );
-
-        if( ! mbedtls_pk_can_do( &cur->cert->pk, pk_alg ) )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) );
-            continue;
-        }
-
-        /*
-         * This avoids sending the client a cert it'll reject based on
-         * keyUsage or other extensions.
-         *
-         * It also allows the user to provision different certificates for
-         * different uses based on keyUsage, eg if they want to avoid signing
-         * and decrypting with the same RSA key.
-         */
-        if( mbedtls_ssl_check_cert_usage( cur->cert, ciphersuite_info,
-                                  MBEDTLS_SSL_IS_SERVER, &flags ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: "
-                                "(extended) key usage extension" ) );
-            continue;
-        }
-
-#if defined(MBEDTLS_ECDSA_C)
-        if( pk_alg == MBEDTLS_PK_ECDSA &&
-            ssl_check_key_curve( &cur->cert->pk, ssl->handshake->curves ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) );
-            continue;
-        }
-#endif
-
-        /*
-         * Try to select a SHA-1 certificate for pre-1.2 clients, but still
-         * present them a SHA-higher cert rather than failing if it's the only
-         * one we got that satisfies the other conditions.
-         */
-        if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 &&
-            cur->cert->sig_md != MBEDTLS_MD_SHA1 )
-        {
-            if( fallback == NULL )
-                fallback = cur;
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate not preferred: "
-                                    "sha-2 with pre-TLS 1.2 client" ) );
-            continue;
-            }
-        }
-
-        /* If we get there, we got a winner */
-        break;
-    }
-
-    if( cur == NULL )
-        cur = fallback;
-
-    /* Do not update ssl->handshake->key_cert unless there is a match */
-    if( cur != NULL )
-    {
-        ssl->handshake->key_cert = cur;
-        MBEDTLS_SSL_DEBUG_CRT( 3, "selected certificate chain, certificate",
-                          ssl->handshake->key_cert->cert );
-        return( 0 );
-    }
-
-    return( -1 );
-}
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
-
-/*
- * Check if a given ciphersuite is suitable for use with our config/keys/etc
- * Sets ciphersuite_info only if the suite matches.
- */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id,
-                                  const mbedtls_ssl_ciphersuite_t **ciphersuite_info )
-{
-    const mbedtls_ssl_ciphersuite_t *suite_info;
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
-    defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-    mbedtls_pk_type_t sig_type;
-#endif
-
-    suite_info = mbedtls_ssl_ciphersuite_from_id( suite_id );
-    if( suite_info == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "trying ciphersuite: %#04x (%s)",
-                                (unsigned int) suite_id, suite_info->name ) );
-
-    if( suite_info->min_minor_ver > ssl->minor_ver ||
-        suite_info->max_minor_ver < ssl->minor_ver )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: version" ) );
-        return( 0 );
-    }
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) )
-        return( 0 );
-#endif
-
-#if defined(MBEDTLS_ARC4_C)
-    if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED &&
-            suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: rc4" ) );
-        return( 0 );
-    }
-#endif
-
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE &&
-        ( ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK ) == 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: ecjpake "
-                                    "not configured or ext missing" ) );
-        return( 0 );
-    }
-#endif
-
-
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
-    if( mbedtls_ssl_ciphersuite_uses_ec( suite_info ) &&
-        ( ssl->handshake->curves == NULL ||
-          ssl->handshake->curves[0] == NULL ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: "
-                            "no common elliptic curve" ) );
-        return( 0 );
-    }
-#endif
-
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
-    /* If the ciphersuite requires a pre-shared key and we don't
-     * have one, skip it now rather than failing later */
-    if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) &&
-        ssl_conf_has_psk_or_cb( ssl->conf ) == 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) );
-        return( 0 );
-    }
-#endif
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
-    defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-    /* If the ciphersuite requires signing, check whether
-     * a suitable hash algorithm is present. */
-    if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
-    {
-        sig_type = mbedtls_ssl_get_ciphersuite_sig_alg( suite_info );
-        if( sig_type != MBEDTLS_PK_NONE &&
-            mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, sig_type ) == MBEDTLS_MD_NONE )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no suitable hash algorithm "
-                                        "for signature algorithm %u", (unsigned) sig_type ) );
-            return( 0 );
-        }
-    }
-
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
-          MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
-
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-    /*
-     * Final check: if ciphersuite requires us to have a
-     * certificate/key of a particular type:
-     * - select the appropriate certificate if we have one, or
-     * - try the next ciphersuite if we don't
-     * This must be done last since we modify the key_cert list.
-     */
-    if( ssl_pick_cert( ssl, suite_info ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: "
-                            "no suitable certificate" ) );
-        return( 0 );
-    }
-#endif
-
-    *ciphersuite_info = suite_info;
-    return( 0 );
-}
-
-#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl )
-{
-    int ret, got_common_suite;
-    unsigned int i, j;
-    size_t n;
-    unsigned int ciph_len, sess_len, chal_len;
-    unsigned char *buf, *p;
-    const int *ciphersuites;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello v2" ) );
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
-
-    buf = ssl->in_hdr;
-
-    MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, 5 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d",
-                   buf[2] ) );
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d",
-                   ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) );
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]",
-                   buf[3], buf[4] ) );
-
-    /*
-     * SSLv2 Client Hello
-     *
-     * Record layer:
-     *     0  .   1   message length
-     *
-     * SSL layer:
-     *     2  .   2   message type
-     *     3  .   4   protocol version
-     */
-    if( buf[2] != MBEDTLS_SSL_HS_CLIENT_HELLO ||
-        buf[3] != MBEDTLS_SSL_MAJOR_VERSION_3 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF;
-
-    if( n < 17 || n > 512 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3;
-    ssl->minor_ver = ( buf[4] <= ssl->conf->max_minor_ver )
-                     ? buf[4]  : ssl->conf->max_minor_ver;
-
-    if( ssl->minor_ver < ssl->conf->min_minor_ver )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum"
-                            " [%d:%d] < [%d:%d]",
-                            ssl->major_ver, ssl->minor_ver,
-                            ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) );
-
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                     MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION );
-        return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
-    }
-
-    ssl->handshake->max_major_ver = buf[3];
-    ssl->handshake->max_minor_ver = buf[4];
-
-    if( ( ret = mbedtls_ssl_fetch_input( ssl, 2 + n ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
-        return( ret );
-    }
-
-    ssl->handshake->update_checksum( ssl, buf + 2, n );
-
-    buf = ssl->in_msg;
-    n = ssl->in_left - 5;
-
-    /*
-     *    0  .   1   ciphersuitelist length
-     *    2  .   3   session id length
-     *    4  .   5   challenge length
-     *    6  .  ..   ciphersuitelist
-     *   ..  .  ..   session id
-     *   ..  .  ..   challenge
-     */
-    MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, n );
-
-    ciph_len = ( buf[0] << 8 ) | buf[1];
-    sess_len = ( buf[2] << 8 ) | buf[3];
-    chal_len = ( buf[4] << 8 ) | buf[5];
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciph_len: %u, sess_len: %u, chal_len: %u",
-                   ciph_len, sess_len, chal_len ) );
-
-    /*
-     * Make sure each parameter length is valid
-     */
-    if( ciph_len < 3 || ( ciph_len % 3 ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    if( sess_len > 32 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    if( chal_len < 8 || chal_len > 32 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    if( n != 6 + ciph_len + sess_len + chal_len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist",
-                   buf + 6, ciph_len );
-    MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id",
-                   buf + 6 + ciph_len, sess_len );
-    MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, challenge",
-                   buf + 6 + ciph_len + sess_len, chal_len );
-
-    p = buf + 6 + ciph_len;
-    ssl->session_negotiate->id_len = sess_len;
-    memset( ssl->session_negotiate->id, 0,
-            sizeof( ssl->session_negotiate->id ) );
-    memcpy( ssl->session_negotiate->id, p, ssl->session_negotiate->id_len );
-
-    p += sess_len;
-    memset( ssl->handshake->randbytes, 0, 64 );
-    memcpy( ssl->handshake->randbytes + 32 - chal_len, p, chal_len );
-
-    /*
-     * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
-     */
-    for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 )
-    {
-        if( p[0] == 0 && p[1] == 0 && p[2] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) );
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-            if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV "
-                                    "during renegotiation" ) );
-
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-                return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-            }
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
-            ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION;
-            break;
-        }
-    }
-
-#if defined(MBEDTLS_SSL_FALLBACK_SCSV)
-    for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 )
-    {
-        if( p[0] == 0 &&
-            MBEDTLS_GET_UINT16_BE(p, 1) != MBEDTLS_SSL_FALLBACK_SCSV_VALUE )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "received FALLBACK_SCSV" ) );
-
-            if( ssl->minor_ver < ssl->conf->max_minor_ver )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) );
-
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK );
-
-                return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-            }
-
-            break;
-        }
-    }
-#endif /* MBEDTLS_SSL_FALLBACK_SCSV */
-
-    got_common_suite = 0;
-    ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver];
-    ciphersuite_info = NULL;
-#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE)
-    for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
-        for( i = 0; ciphersuites[i] != 0; i++ )
-#else
-    for( i = 0; ciphersuites[i] != 0; i++ )
-        for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
-#endif
-        {
-            if( p[0] != 0 ||
-                MBEDTLS_GET_UINT16_BE(p, 1) != ciphersuites[i] )
-                continue;
-
-            got_common_suite = 1;
-
-            if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i],
-                                               &ciphersuite_info ) ) != 0 )
-                return( ret );
-
-            if( ciphersuite_info != NULL )
-                goto have_ciphersuite_v2;
-        }
-
-    if( got_common_suite )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, "
-                            "but none of them usable" ) );
-        return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE );
-    }
-    else
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) );
-        return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN );
-    }
-
-have_ciphersuite_v2:
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) );
-
-    ssl->session_negotiate->ciphersuite = ciphersuites[i];
-    ssl->handshake->ciphersuite_info = ciphersuite_info;
-
-    /*
-     * SSLv2 Client Hello relevant renegotiation security checks
-     */
-    if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-        ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    ssl->in_left = 0;
-    ssl->state++;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello v2" ) );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */
-
-/* This function doesn't alert on errors that happen early during
-   ClientHello parsing because they might indicate that the client is
-   not talking SSL/TLS at all and would not understand our alert. */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_client_hello( mbedtls_ssl_context *ssl )
-{
-    int ret, got_common_suite;
-    size_t i, j;
-    size_t ciph_offset, comp_offset, ext_offset;
-    size_t msg_len, ciph_len, sess_len, comp_len, ext_len;
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    size_t cookie_offset, cookie_len;
-#endif
-    unsigned char *buf, *p, *ext;
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    int renegotiation_info_seen = 0;
-#endif
-    int handshake_failure = 0;
-    const int *ciphersuites;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
-    int major, minor;
-
-    /* If there is no signature-algorithm extension present,
-     * we need to fall back to the default values for allowed
-     * signature-hash pairs. */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
-    defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-    int sig_hash_alg_ext_present = 0;
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
-          MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) );
-
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-read_record_header:
-#endif
-    /*
-     * If renegotiating, then the input was read with mbedtls_ssl_read_record(),
-     * otherwise read it ourselves manually in order to support SSLv2
-     * ClientHello, which doesn't use the same record layer format.
-     */
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE )
-#endif
-    {
-        if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 )
-        {
-            /* No alert on a read error. */
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
-            return( ret );
-        }
-    }
-
-    buf = ssl->in_hdr;
-
-#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM )
-#endif
-        if( ( buf[0] & 0x80 ) != 0 )
-            return( ssl_parse_client_hello_v2( ssl ) );
-#endif
-
-    MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_in_hdr_len( ssl ) );
-
-    /*
-     * SSLv3/TLS Client Hello
-     *
-     * Record layer:
-     *     0  .   0   message type
-     *     1  .   2   protocol version
-     *     3  .   11  DTLS: epoch + record sequence number
-     *     3  .   4   message length
-     */
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d",
-                   buf[0] ) );
-
-    if( buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d",
-                   ( ssl->in_len[0] << 8 ) | ssl->in_len[1] ) );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, protocol version: [%d:%d]",
-                   buf[1], buf[2] ) );
-
-    mbedtls_ssl_read_version( &major, &minor, ssl->conf->transport, buf + 1 );
-
-    /* According to RFC 5246 Appendix E.1, the version here is typically
-     * "{03,00}, the lowest version number supported by the client, [or] the
-     * value of ClientHello.client_version", so the only meaningful check here
-     * is the major version shouldn't be less than 3 */
-    if( major < MBEDTLS_SSL_MAJOR_VERSION_3 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    /* For DTLS if this is the initial handshake, remember the client sequence
-     * number to use it in our next message (RFC 6347 4.2.1) */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-        && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE
-#endif
-        )
-    {
-        /* Epoch should be 0 for initial handshakes */
-        if( ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-        }
-
-        memcpy( ssl->cur_out_ctr + 2, ssl->in_ctr + 2, 6 );
-
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-        if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record, discarding" ) );
-            ssl->next_record_offset = 0;
-            ssl->in_left = 0;
-            goto read_record_header;
-        }
-
-        /* No MAC to check yet, so we can update right now */
-        mbedtls_ssl_dtls_replay_update( ssl );
-#endif
-    }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-    msg_len = ( ssl->in_len[0] << 8 ) | ssl->in_len[1];
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
-    {
-        /* Set by mbedtls_ssl_read_record() */
-        msg_len = ssl->in_hslen;
-    }
-    else
-#endif
-    {
-        if( msg_len > MBEDTLS_SSL_IN_CONTENT_LEN )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-        }
-
-        if( ( ret = mbedtls_ssl_fetch_input( ssl,
-                       mbedtls_ssl_in_hdr_len( ssl ) + msg_len ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
-            return( ret );
-        }
-
-    /* Done reading this record, get ready for the next one */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-        if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-            ssl->next_record_offset = msg_len + mbedtls_ssl_in_hdr_len( ssl );
-        else
-#endif
-            ssl->in_left = 0;
-    }
-
-    buf = ssl->in_msg;
-
-    MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, msg_len );
-
-    ssl->handshake->update_checksum( ssl, buf, msg_len );
-
-    /*
-     * Handshake layer:
-     *     0  .   0   handshake type
-     *     1  .   3   handshake length
-     *     4  .   5   DTLS only: message sequence number
-     *     6  .   8   DTLS only: fragment offset
-     *     9  .  11   DTLS only: fragment length
-     */
-    if( msg_len < mbedtls_ssl_hs_hdr_len( ssl ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d", buf[0] ) );
-
-    if( buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d",
-                   ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) );
-
-    if( buf[1] != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message: %u != 0",
-                                    (unsigned) buf[1] ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-    /* We don't support fragmentation of ClientHello (yet?) */
-    if( msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message: %u != %u + %u",
-                                    (unsigned) msg_len,
-                                    (unsigned) mbedtls_ssl_hs_hdr_len( ssl ),
-                                    (unsigned) ( buf[2] << 8 ) | buf[3] ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        /*
-         * Copy the client's handshake message_seq on initial handshakes,
-         * check sequence number on renego.
-         */
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-        if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
-        {
-            /* This couldn't be done in ssl_prepare_handshake_record() */
-            unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) |
-                                         ssl->in_msg[5];
-
-            if( cli_msg_seq != ssl->handshake->in_msg_seq )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message_seq: "
-                                    "%u (expected %u)", cli_msg_seq,
-                                    ssl->handshake->in_msg_seq ) );
-                return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-            }
-
-            ssl->handshake->in_msg_seq++;
-        }
-        else
-#endif
-        {
-            unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) |
-                                         ssl->in_msg[5];
-            ssl->handshake->out_msg_seq = cli_msg_seq;
-            ssl->handshake->in_msg_seq  = cli_msg_seq + 1;
-        }
-
-        /*
-         * For now we don't support fragmentation, so make sure
-         * fragment_offset == 0 and fragment_length == length
-         */
-        MBEDTLS_SSL_DEBUG_MSG(
-            4, ( "fragment_offset=%u fragment_length=%u length=%u",
-                 (unsigned) ( ssl->in_msg[6] << 16 | ssl->in_msg[7] << 8 | ssl->in_msg[8] ),
-                 (unsigned) ( ssl->in_msg[9] << 16 | ssl->in_msg[10] << 8 | ssl->in_msg[11] ),
-                 (unsigned) ( ssl->in_msg[1] << 16 | ssl->in_msg[2] << 8 | ssl->in_msg[3] ) ) );
-        if( ssl->in_msg[6] != 0 || ssl->in_msg[7] != 0 || ssl->in_msg[8] != 0 ||
-            memcmp( ssl->in_msg + 1, ssl->in_msg + 9, 3 ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "ClientHello fragmentation not supported" ) );
-            return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
-        }
-    }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-    buf += mbedtls_ssl_hs_hdr_len( ssl );
-    msg_len -= mbedtls_ssl_hs_hdr_len( ssl );
-
-    /*
-     * ClientHello layer:
-     *     0  .   1   protocol version
-     *     2  .  33   random bytes (starting with 4 bytes of Unix time)
-     *    34  .  35   session id length (1 byte)
-     *    35  . 34+x  session id
-     *   35+x . 35+x  DTLS only: cookie length (1 byte)
-     *   36+x .  ..   DTLS only: cookie
-     *    ..  .  ..   ciphersuite list length (2 bytes)
-     *    ..  .  ..   ciphersuite list
-     *    ..  .  ..   compression alg. list length (1 byte)
-     *    ..  .  ..   compression alg. list
-     *    ..  .  ..   extensions length (2 bytes, optional)
-     *    ..  .  ..   extensions (optional)
-     */
-
-    /*
-     * Minimal length (with everything empty and extensions omitted) is
-     * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can
-     * read at least up to session id length without worrying.
-     */
-    if( msg_len < 38 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    /*
-     * Check and save the protocol version
-     */
-    MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, version", buf, 2 );
-
-    mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver,
-                      ssl->conf->transport, buf );
-
-    ssl->handshake->max_major_ver = ssl->major_ver;
-    ssl->handshake->max_minor_ver = ssl->minor_ver;
-
-    if( ssl->major_ver < ssl->conf->min_major_ver ||
-        ssl->minor_ver < ssl->conf->min_minor_ver )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum"
-                            " [%d:%d] < [%d:%d]",
-                            ssl->major_ver, ssl->minor_ver,
-                            ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                     MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION );
-        return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
-    }
-
-    if( ssl->major_ver > ssl->conf->max_major_ver )
-    {
-        ssl->major_ver = ssl->conf->max_major_ver;
-        ssl->minor_ver = ssl->conf->max_minor_ver;
-    }
-    else if( ssl->minor_ver > ssl->conf->max_minor_ver )
-        ssl->minor_ver = ssl->conf->max_minor_ver;
-
-    /*
-     * Save client random (inc. Unix time)
-     */
-    MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 2, 32 );
-
-    memcpy( ssl->handshake->randbytes, buf + 2, 32 );
-
-    /*
-     * Check the session ID length and save session ID
-     */
-    sess_len = buf[34];
-
-    if( sess_len > sizeof( ssl->session_negotiate->id ) ||
-        sess_len + 34 + 2 > msg_len ) /* 2 for cipherlist length field */
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 35, sess_len );
-
-    ssl->session_negotiate->id_len = sess_len;
-    memset( ssl->session_negotiate->id, 0,
-            sizeof( ssl->session_negotiate->id ) );
-    memcpy( ssl->session_negotiate->id, buf + 35,
-            ssl->session_negotiate->id_len );
-
-    /*
-     * Check the cookie length and content
-     */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        cookie_offset = 35 + sess_len;
-        cookie_len = buf[cookie_offset];
-
-        if( cookie_offset + 1 + cookie_len + 2 > msg_len )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-        }
-
-        MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie",
-                       buf + cookie_offset + 1, cookie_len );
-
-#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
-        if( ssl->conf->f_cookie_check != NULL
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-            && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE
-#endif
-            )
-        {
-            if( ssl->conf->f_cookie_check( ssl->conf->p_cookie,
-                                     buf + cookie_offset + 1, cookie_len,
-                                     ssl->cli_id, ssl->cli_id_len ) != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification failed" ) );
-                ssl->handshake->verify_cookie_len = 1;
-            }
-            else
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification passed" ) );
-                ssl->handshake->verify_cookie_len = 0;
-            }
-        }
-        else
-#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
-        {
-            /* We know we didn't send a cookie, so it should be empty */
-            if( cookie_len != 0 )
-            {
-                /* This may be an attacker's probe, so don't send an alert */
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-                return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-            }
-
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification skipped" ) );
-        }
-
-    /*
-     * Check the ciphersuitelist length (will be parsed later)
-     */
-        ciph_offset = cookie_offset + 1 + cookie_len;
-    }
-    else
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-        ciph_offset = 35 + sess_len;
-
-    ciph_len = ( buf[ciph_offset + 0] << 8 )
-             | ( buf[ciph_offset + 1]      );
-
-    if( ciph_len < 2 ||
-        ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */
-        ( ciph_len % 2 ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist",
-                   buf + ciph_offset + 2,  ciph_len );
-
-    /*
-     * Check the compression algorithms length and pick one
-     */
-    comp_offset = ciph_offset + 2 + ciph_len;
-
-    comp_len = buf[comp_offset];
-
-    if( comp_len < 1 ||
-        comp_len > 16 ||
-        comp_len + comp_offset + 1 > msg_len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, compression",
-                      buf + comp_offset + 1, comp_len );
-
-    ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL;
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-    for( i = 0; i < comp_len; ++i )
-    {
-        if( buf[comp_offset + 1 + i] == MBEDTLS_SSL_COMPRESS_DEFLATE )
-        {
-            ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_DEFLATE;
-            break;
-        }
-    }
-#endif
-
-    /* See comments in ssl_write_client_hello() */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-        ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL;
-#endif
-
-    /* Do not parse the extensions if the protocol is SSLv3 */
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-    if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) )
-    {
-#endif
-        /*
-         * Check the extension length
-         */
-        ext_offset = comp_offset + 1 + comp_len;
-        if( msg_len > ext_offset )
-        {
-            if( msg_len < ext_offset + 2 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-                return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-            }
-
-            ext_len = ( buf[ext_offset + 0] << 8 )
-                    | ( buf[ext_offset + 1]      );
-
-            if( msg_len != ext_offset + 2 + ext_len )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-                return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-            }
-        }
-        else
-            ext_len = 0;
-
-        ext = buf + ext_offset + 2;
-        MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", ext, ext_len );
-
-        while( ext_len != 0 )
-        {
-            unsigned int ext_id;
-            unsigned int ext_size;
-            if ( ext_len < 4 ) {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                               MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-                return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-            }
-            ext_id   = ( ( ext[0] <<  8 ) | ( ext[1] ) );
-            ext_size = ( ( ext[2] <<  8 ) | ( ext[3] ) );
-
-            if( ext_size + 4 > ext_len )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-                return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-            }
-            switch( ext_id )
-            {
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-            case MBEDTLS_TLS_EXT_SERVERNAME:
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) );
-                if( ssl->conf->f_sni == NULL )
-                    break;
-
-                ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size );
-                if( ret != 0 )
-                    return( ret );
-                break;
-#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
-
-            case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO:
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) );
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-                renegotiation_info_seen = 1;
-#endif
-
-                ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size );
-                if( ret != 0 )
-                    return( ret );
-                break;
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
-    defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-            case MBEDTLS_TLS_EXT_SIG_ALG:
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) );
-
-                ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size );
-                if( ret != 0 )
-                    return( ret );
-
-                sig_hash_alg_ext_present = 1;
-                break;
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
-          MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
-
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-            case MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES:
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) );
-
-                ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size );
-                if( ret != 0 )
-                    return( ret );
-                break;
-
-            case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS:
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) );
-                ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT;
-
-                ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size );
-                if( ret != 0 )
-                    return( ret );
-                break;
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
-          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-            case MBEDTLS_TLS_EXT_ECJPAKE_KKPP:
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake kkpp extension" ) );
-
-                ret = ssl_parse_ecjpake_kkpp( ssl, ext + 4, ext_size );
-                if( ret != 0 )
-                    return( ret );
-                break;
-#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-            case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH:
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) );
-
-                ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size );
-                if( ret != 0 )
-                    return( ret );
-                break;
-#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
-
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-            case MBEDTLS_TLS_EXT_TRUNCATED_HMAC:
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) );
-
-                ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size );
-                if( ret != 0 )
-                    return( ret );
-                break;
-#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-            case MBEDTLS_TLS_EXT_CID:
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found CID extension" ) );
-
-                ret = ssl_parse_cid_ext( ssl, ext + 4, ext_size );
-                if( ret != 0 )
-                    return( ret );
-                break;
-#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
-
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-            case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC:
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) );
-
-                ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size );
-                if( ret != 0 )
-                    return( ret );
-                break;
-#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
-
-#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-            case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET:
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) );
-
-                ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size );
-                if( ret != 0 )
-                    return( ret );
-                break;
-#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-            case MBEDTLS_TLS_EXT_SESSION_TICKET:
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) );
-
-                ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size );
-                if( ret != 0 )
-                    return( ret );
-                break;
-#endif /* MBEDTLS_SSL_SESSION_TICKETS */
-
-#if defined(MBEDTLS_SSL_ALPN)
-            case MBEDTLS_TLS_EXT_ALPN:
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) );
-
-                ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size );
-                if( ret != 0 )
-                    return( ret );
-                break;
-#endif /* MBEDTLS_SSL_SESSION_TICKETS */
-
-#if defined(MBEDTLS_SSL_DTLS_SRTP)
-            case MBEDTLS_TLS_EXT_USE_SRTP:
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found use_srtp extension" ) );
-
-                ret = ssl_parse_use_srtp_ext( ssl, ext + 4, ext_size );
-                if( ret != 0 )
-                    return( ret );
-                break;
-#endif /* MBEDTLS_SSL_DTLS_SRTP */
-
-            default:
-                MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %u (ignoring)",
-                               ext_id ) );
-            }
-
-            ext_len -= 4 + ext_size;
-            ext += 4 + ext_size;
-        }
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-    }
-#endif
-
-#if defined(MBEDTLS_SSL_FALLBACK_SCSV)
-    for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 )
-    {
-        if( MBEDTLS_GET_UINT16_BE( p, 0 ) == MBEDTLS_SSL_FALLBACK_SCSV_VALUE )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "received FALLBACK_SCSV" ) );
-
-            if( ssl->minor_ver < ssl->conf->max_minor_ver )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) );
-
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK );
-
-                return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-            }
-
-            break;
-        }
-    }
-#endif /* MBEDTLS_SSL_FALLBACK_SCSV */
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
-    defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-
-    /*
-     * Try to fall back to default hash SHA1 if the client
-     * hasn't provided any preferred signature-hash combinations.
-     */
-    if( sig_hash_alg_ext_present == 0 )
-    {
-        mbedtls_md_type_t md_default = MBEDTLS_MD_SHA1;
-
-        if( mbedtls_ssl_check_sig_hash( ssl, md_default ) != 0 )
-            md_default = MBEDTLS_MD_NONE;
-
-        mbedtls_ssl_sig_hash_set_const_hash( &ssl->handshake->hash_algs, md_default );
-    }
-
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 &&
-          MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
-
-    /*
-     * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
-     */
-    for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 )
-    {
-        if( p[0] == 0 && p[1] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) );
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-            if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV "
-                                            "during renegotiation" ) );
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-                return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-            }
-#endif
-            ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION;
-            break;
-        }
-    }
-
-    /*
-     * Renegotiation security checks
-     */
-    if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION &&
-        ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
-        handshake_failure = 1;
-    }
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
-             ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION &&
-             renegotiation_info_seen == 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) );
-        handshake_failure = 1;
-    }
-    else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
-             ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-             ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) );
-        handshake_failure = 1;
-    }
-    else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
-             ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-             renegotiation_info_seen == 1 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) );
-        handshake_failure = 1;
-    }
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
-
-    if( handshake_failure == 1 )
-    {
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-    }
-
-    /*
-     * Search for a matching ciphersuite
-     * (At the end because we need information from the EC-based extensions
-     * and certificate from the SNI callback triggered by the SNI extension.)
-     */
-    got_common_suite = 0;
-    ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver];
-    ciphersuite_info = NULL;
-#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE)
-    for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 )
-        for( i = 0; ciphersuites[i] != 0; i++ )
-#else
-    for( i = 0; ciphersuites[i] != 0; i++ )
-        for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 )
-#endif
-        {
-            if( MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i] )
-                continue;
-
-            got_common_suite = 1;
-
-            if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i],
-                                               &ciphersuite_info ) ) != 0 )
-                return( ret );
-
-            if( ciphersuite_info != NULL )
-                goto have_ciphersuite;
-        }
-
-    if( got_common_suite )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, "
-                            "but none of them usable" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-        return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE );
-    }
-    else
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
-        return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN );
-    }
-
-have_ciphersuite:
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) );
-
-    ssl->session_negotiate->ciphersuite = ciphersuites[i];
-    ssl->handshake->ciphersuite_info = ciphersuite_info;
-
-    ssl->state++;
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-        mbedtls_ssl_recv_flight_completed( ssl );
-#endif
-
-    /* Debugging-only output for testsuite */
-#if defined(MBEDTLS_DEBUG_C)                         && \
-    defined(MBEDTLS_SSL_PROTO_TLS1_2)                && \
-    defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-    if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
-    {
-        mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg( ciphersuite_info );
-        if( sig_alg != MBEDTLS_PK_NONE )
-        {
-            mbedtls_md_type_t md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs,
-                                                                  sig_alg );
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d",
-                                        mbedtls_ssl_hash_from_md_alg( md_alg ) ) );
-        }
-        else
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "no hash algorithm for signature algorithm "
-                                        "%u - should not happen", (unsigned) sig_alg ) );
-        }
-    }
-#endif
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) );
-
-    return( 0 );
-}
-
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl,
-                                          unsigned char *buf,
-                                          size_t *olen )
-{
-    unsigned char *p = buf;
-
-    if( ssl->session_negotiate->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED )
-    {
-        *olen = 0;
-        return;
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding truncated hmac extension" ) );
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_TRUNCATED_HMAC, p, 0 );
-    p += 2;
-
-    *p++ = 0x00;
-    *p++ = 0x00;
-
-    *olen = 4;
-}
-#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-static void ssl_write_cid_ext( mbedtls_ssl_context *ssl,
-                               unsigned char *buf,
-                               size_t *olen )
-{
-    unsigned char *p = buf;
-    size_t ext_len;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
-
-    *olen = 0;
-
-    /* Skip writing the extension if we don't want to use it or if
-     * the client hasn't offered it. */
-    if( ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_DISABLED )
-        return;
-
-    /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX
-     * which is at most 255, so the increment cannot overflow. */
-    if( end < p || (size_t)( end - p ) < (unsigned)( ssl->own_cid_len + 5 ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
-        return;
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding CID extension" ) );
-
-    /*
-     * Quoting draft-ietf-tls-dtls-connection-id-05
-     * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05
-     *
-     *   struct {
-     *      opaque cid<0..2^8-1>;
-     *   } ConnectionId;
-    */
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_CID, p, 0 );
-    p += 2;
-    ext_len = (size_t) ssl->own_cid_len + 1;
-    MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 );
-    p += 2;
-
-    *p++ = (uint8_t) ssl->own_cid_len;
-    memcpy( p, ssl->own_cid, ssl->own_cid_len );
-
-    *olen = ssl->own_cid_len + 5;
-}
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
-                                            unsigned char *buf,
-                                            size_t *olen )
-{
-    unsigned char *p = buf;
-    const mbedtls_ssl_ciphersuite_t *suite = NULL;
-    const mbedtls_cipher_info_t *cipher = NULL;
-
-    if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
-        ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED;
-
-    /*
-     * RFC 7366: "If a server receives an encrypt-then-MAC request extension
-     * from a client and then selects a stream or Authenticated Encryption
-     * with Associated Data (AEAD) ciphersuite, it MUST NOT send an
-     * encrypt-then-MAC response extension back to the client."
-     */
-    if( ( suite = mbedtls_ssl_ciphersuite_from_id(
-                    ssl->session_negotiate->ciphersuite ) ) == NULL ||
-        ( cipher = mbedtls_cipher_info_from_type( suite->cipher ) ) == NULL ||
-        cipher->mode != MBEDTLS_MODE_CBC )
-    {
-        ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED;
-    }
-
-    if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED )
-    {
-        *olen = 0;
-        return;
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding encrypt then mac extension" ) );
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, p, 0 );
-    p += 2;
-
-    *p++ = 0x00;
-    *p++ = 0x00;
-
-    *olen = 4;
-}
-#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
-
-#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl,
-                                       unsigned char *buf,
-                                       size_t *olen )
-{
-    unsigned char *p = buf;
-
-    if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED ||
-        ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
-    {
-        *olen = 0;
-        return;
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding extended master secret "
-                        "extension" ) );
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, p, 0 );
-    p += 2;
-
-    *p++ = 0x00;
-    *p++ = 0x00;
-
-    *olen = 4;
-}
-#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl,
-                                          unsigned char *buf,
-                                          size_t *olen )
-{
-    unsigned char *p = buf;
-
-    if( ssl->handshake->new_session_ticket == 0 )
-    {
-        *olen = 0;
-        return;
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding session ticket extension" ) );
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SESSION_TICKET, p, 0 );
-    p += 2;
-
-    *p++ = 0x00;
-    *p++ = 0x00;
-
-    *olen = 4;
-}
-#endif /* MBEDTLS_SSL_SESSION_TICKETS */
-
-static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
-                                         unsigned char *buf,
-                                         size_t *olen )
-{
-    unsigned char *p = buf;
-
-    if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION )
-    {
-        *olen = 0;
-        return;
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) );
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO, p, 0 );
-    p += 2;
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
-    {
-        *p++ = 0x00;
-        *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF;
-        *p++ = ssl->verify_data_len * 2 & 0xFF;
-
-        memcpy( p, ssl->peer_verify_data, ssl->verify_data_len );
-        p += ssl->verify_data_len;
-        memcpy( p, ssl->own_verify_data, ssl->verify_data_len );
-        p += ssl->verify_data_len;
-    }
-    else
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
-    {
-        *p++ = 0x00;
-        *p++ = 0x01;
-        *p++ = 0x00;
-    }
-
-    *olen = p - buf;
-}
-
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl,
-                                               unsigned char *buf,
-                                               size_t *olen )
-{
-    unsigned char *p = buf;
-
-    if( ssl->session_negotiate->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE )
-    {
-        *olen = 0;
-        return;
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) );
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, p, 0 );
-    p += 2;
-
-    *p++ = 0x00;
-    *p++ = 1;
-
-    *p++ = ssl->session_negotiate->mfl_code;
-
-    *olen = 5;
-}
-#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
-
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl,
-                                                   unsigned char *buf,
-                                                   size_t *olen )
-{
-    unsigned char *p = buf;
-    ((void) ssl);
-
-    if( ( ssl->handshake->cli_exts &
-          MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT ) == 0 )
-    {
-        *olen = 0;
-        return;
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, supported_point_formats extension" ) );
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, p, 0 );
-    p += 2;
-
-    *p++ = 0x00;
-    *p++ = 2;
-
-    *p++ = 1;
-    *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED;
-
-    *olen = 6;
-}
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
-                                        unsigned char *buf,
-                                        size_t *olen )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char *p = buf;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
-    size_t kkpp_len;
-
-    *olen = 0;
-
-    /* Skip costly computation if not needed */
-    if( ssl->handshake->ciphersuite_info->key_exchange !=
-        MBEDTLS_KEY_EXCHANGE_ECJPAKE )
-        return;
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, ecjpake kkpp extension" ) );
-
-    if( end - p < 4 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
-        return;
-    }
-
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0 );
-    p += 2;
-
-    ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx,
-                                        p + 2, end - p - 2, &kkpp_len,
-                                        ssl->conf->f_rng, ssl->conf->p_rng );
-    if( ret != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret );
-        return;
-    }
-
-    MBEDTLS_PUT_UINT16_BE( kkpp_len, p, 0 );
-    p += 2;
-
-    *olen = kkpp_len + 4;
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-
-#if defined(MBEDTLS_SSL_ALPN )
-static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
-                                unsigned char *buf, size_t *olen )
-{
-    if( ssl->alpn_chosen == NULL )
-    {
-        *olen = 0;
-        return;
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding alpn extension" ) );
-
-    /*
-     * 0 . 1    ext identifier
-     * 2 . 3    ext length
-     * 4 . 5    protocol list length
-     * 6 . 6    protocol name length
-     * 7 . 7+n  protocol name
-     */
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ALPN, buf, 0);
-
-    *olen = 7 + strlen( ssl->alpn_chosen );
-
-    MBEDTLS_PUT_UINT16_BE( *olen - 4, buf, 2 );
-
-    MBEDTLS_PUT_UINT16_BE( *olen - 6, buf, 4 );
-
-    buf[6] = MBEDTLS_BYTE_0( *olen - 7 );
-
-    memcpy( buf + 7, ssl->alpn_chosen, *olen - 7 );
-}
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */
-
-#if defined(MBEDTLS_SSL_DTLS_SRTP ) && defined(MBEDTLS_SSL_PROTO_DTLS)
-static void ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl,
-                                    unsigned char *buf,
-                                    size_t *olen )
-{
-    size_t mki_len = 0, ext_len = 0;
-    uint16_t profile_value = 0;
-    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
-
-    *olen = 0;
-
-    if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) ||
-        ( ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET ) )
-    {
-        return;
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding use_srtp extension" ) );
-
-    if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED )
-    {
-        mki_len = ssl->dtls_srtp_info.mki_len;
-    }
-
-    /* The extension total size is 9 bytes :
-     * - 2 bytes for the extension tag
-     * - 2 bytes for the total size
-     * - 2 bytes for the protection profile length
-     * - 2 bytes for the protection profile
-     * - 1 byte for the mki length
-     * +  the actual mki length
-     * Check we have enough room in the output buffer */
-    if( (size_t)( end - buf ) < mki_len + 9 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
-        return;
-    }
-
-    /* extension */
-    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_USE_SRTP, buf, 0 );
-    /*
-     * total length 5 and mki value: only one profile(2 bytes)
-     *              and length(2 bytes) and srtp_mki  )
-     */
-    ext_len = 5 + mki_len;
-    MBEDTLS_PUT_UINT16_BE( ext_len, buf, 2 );
-
-    /* protection profile length: 2 */
-    buf[4] = 0x00;
-    buf[5] = 0x02;
-    profile_value = mbedtls_ssl_check_srtp_profile_value(
-                                ssl->dtls_srtp_info.chosen_dtls_srtp_profile );
-    if( profile_value != MBEDTLS_TLS_SRTP_UNSET )
-    {
-        MBEDTLS_PUT_UINT16_BE( profile_value, buf, 6 );
-    }
-    else
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "use_srtp extension invalid profile" ) );
-        return;
-    }
-
-    buf[8] = mki_len & 0xFF;
-    memcpy( &buf[9], ssl->dtls_srtp_info.mki_value, mki_len );
-
-    *olen = 9 + mki_len;
-}
-#endif /* MBEDTLS_SSL_DTLS_SRTP */
-
-#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char *p = ssl->out_msg + 4;
-    unsigned char *cookie_len_byte;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello verify request" ) );
-
-    /*
-     * struct {
-     *   ProtocolVersion server_version;
-     *   opaque cookie<0..2^8-1>;
-     * } HelloVerifyRequest;
-     */
-
-    /* The RFC is not clear on this point, but sending the actual negotiated
-     * version looks like the most interoperable thing to do. */
-    mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
-                       ssl->conf->transport, p );
-    MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 );
-    p += 2;
-
-    /* If we get here, f_cookie_check is not null */
-    if( ssl->conf->f_cookie_write == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "inconsistent cookie callbacks" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-
-    /* Skip length byte until we know the length */
-    cookie_len_byte = p++;
-
-    if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie,
-                                     &p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN,
-                                     ssl->cli_id, ssl->cli_id_len ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret );
-        return( ret );
-    }
-
-    *cookie_len_byte = (unsigned char)( p - ( cookie_len_byte + 1 ) );
-
-    MBEDTLS_SSL_DEBUG_BUF( 3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte );
-
-    ssl->out_msglen  = p - ssl->out_msg;
-    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
-    ssl->out_msg[0]  = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST;
-
-    ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT;
-
-    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
-        return( ret );
-    }
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
-        return( ret );
-    }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
-
-static void ssl_handle_id_based_session_resumption( mbedtls_ssl_context *ssl )
-{
-    int ret;
-    mbedtls_ssl_session session_tmp;
-    mbedtls_ssl_session * const session = ssl->session_negotiate;
-
-    /* Resume is 0  by default, see ssl_handshake_init().
-     * It may be already set to 1 by ssl_parse_session_ticket_ext(). */
-    if( ssl->handshake->resume == 1 )
-        return;
-    if( session->id_len == 0 )
-        return;
-    if( ssl->conf->f_get_cache == NULL )
-        return;
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE )
-        return;
-#endif
-
-    mbedtls_ssl_session_init( &session_tmp );
-
-    session_tmp.id_len = session->id_len;
-    memcpy( session_tmp.id, session->id, session->id_len );
-
-    ret = ssl->conf->f_get_cache( ssl->conf->p_cache,
-                                  &session_tmp );
-    if( ret != 0 )
-        goto exit;
-
-    if( session->ciphersuite != session_tmp.ciphersuite ||
-        session->compression != session_tmp.compression )
-    {
-        /* Mismatch between cached and negotiated session */
-        goto exit;
-    }
-
-    /* Move semantics */
-    mbedtls_ssl_session_free( session );
-    *session = session_tmp;
-    memset( &session_tmp, 0, sizeof( session_tmp ) );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) );
-    ssl->handshake->resume = 1;
-
-exit:
-
-    mbedtls_ssl_session_free( &session_tmp );
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
-{
-#if defined(MBEDTLS_HAVE_TIME)
-    mbedtls_time_t t;
-#endif
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t olen, ext_len = 0, n;
-    unsigned char *buf, *p;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello" ) );
-
-#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ssl->handshake->verify_cookie_len != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "client hello was not authenticated" ) );
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) );
-
-        return( ssl_write_hello_verify_request( ssl ) );
-    }
-#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
-
-    if( ssl->conf->f_rng == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") );
-        return( MBEDTLS_ERR_SSL_NO_RNG );
-    }
-
-    /*
-     *     0  .   0   handshake type
-     *     1  .   3   handshake length
-     *     4  .   5   protocol version
-     *     6  .   9   UNIX time()
-     *    10  .  37   random bytes
-     */
-    buf = ssl->out_msg;
-    p = buf + 4;
-
-    mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
-                       ssl->conf->transport, p );
-    p += 2;
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]",
-                        buf[4], buf[5] ) );
-
-#if defined(MBEDTLS_HAVE_TIME)
-    t = mbedtls_time( NULL );
-    MBEDTLS_PUT_UINT32_BE( t, p, 0 );
-    p += 4;
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %" MBEDTLS_PRINTF_LONGLONG,
-                                (long long) t ) );
-#else
-    if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 )
-        return( ret );
-
-    p += 4;
-#endif /* MBEDTLS_HAVE_TIME */
-
-    if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 )
-        return( ret );
-
-    p += 28;
-
-    memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 );
-
-    MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 );
-
-    ssl_handle_id_based_session_resumption( ssl );
-
-    if( ssl->handshake->resume == 0 )
-    {
-        /*
-         * New session, create a new session id,
-         * unless we're about to issue a session ticket
-         */
-        ssl->state++;
-
-#if defined(MBEDTLS_HAVE_TIME)
-        ssl->session_negotiate->start = mbedtls_time( NULL );
-#endif
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-        if( ssl->handshake->new_session_ticket != 0 )
-        {
-            ssl->session_negotiate->id_len = n = 0;
-            memset( ssl->session_negotiate->id, 0, 32 );
-        }
-        else
-#endif /* MBEDTLS_SSL_SESSION_TICKETS */
-        {
-            ssl->session_negotiate->id_len = n = 32;
-            if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id,
-                                    n ) ) != 0 )
-                return( ret );
-        }
-    }
-    else
-    {
-        /*
-         * Resuming a session
-         */
-        n = ssl->session_negotiate->id_len;
-        ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC;
-
-        if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
-            return( ret );
-        }
-    }
-
-    /*
-     *    38  .  38     session id length
-     *    39  . 38+n    session id
-     *   39+n . 40+n    chosen ciphersuite
-     *   41+n . 41+n    chosen compression alg.
-     *   42+n . 43+n    extensions length
-     *   44+n . 43+n+m  extensions
-     */
-    *p++ = (unsigned char) ssl->session_negotiate->id_len;
-    memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len );
-    p += ssl->session_negotiate->id_len;
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n ) );
-    MBEDTLS_SSL_DEBUG_BUF( 3,   "server hello, session id", buf + 39, n );
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
-                   ssl->handshake->resume ? "a" : "no" ) );
-
-    MBEDTLS_PUT_UINT16_BE( ssl->session_negotiate->ciphersuite, p, 0 );
-    p += 2;
-    *p++ = MBEDTLS_BYTE_0( ssl->session_negotiate->compression );
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s",
-           mbedtls_ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite ) ) );
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X",
-                   (unsigned int) ssl->session_negotiate->compression ) );
-
-    /* Do not write the extensions if the protocol is SSLv3 */
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-    if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) )
-    {
-#endif
-
-    /*
-     *  First write extensions, then the total length
-     */
-    ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen );
-    ext_len += olen;
-
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-    ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen );
-    ext_len += olen;
-#endif
-
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-    ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen );
-    ext_len += olen;
-#endif
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    ssl_write_cid_ext( ssl, p + 2 + ext_len, &olen );
-    ext_len += olen;
-#endif
-
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-    ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen );
-    ext_len += olen;
-#endif
-
-#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-    ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen );
-    ext_len += olen;
-#endif
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen );
-    ext_len += olen;
-#endif
-
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    if ( mbedtls_ssl_ciphersuite_uses_ec(
-         mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ) ) )
-    {
-        ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen );
-        ext_len += olen;
-    }
-#endif
-
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen );
-    ext_len += olen;
-#endif
-
-#if defined(MBEDTLS_SSL_ALPN)
-    ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen );
-    ext_len += olen;
-#endif
-
-#if defined(MBEDTLS_SSL_DTLS_SRTP)
-    ssl_write_use_srtp_ext( ssl, p + 2 + ext_len, &olen );
-    ext_len += olen;
-#endif
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %" MBEDTLS_PRINTF_SIZET,
-                                ext_len ) );
-
-    if( ext_len > 0 )
-    {
-        MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 );
-        p += 2 + ext_len;
-    }
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-    }
-#endif
-
-    ssl->out_msglen  = p - buf;
-    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
-    ssl->out_msg[0]  = MBEDTLS_SSL_HS_SERVER_HELLO;
-
-    ret = mbedtls_ssl_write_handshake_msg( ssl );
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) );
-
-    return( ret );
-}
-
-#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
-{
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
-
-    if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) );
-        ssl->state++;
-        return( 0 );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-    return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-}
-#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-    uint16_t dn_size, total_dn_size; /* excluding length bytes */
-    size_t ct_len, sa_len; /* including length bytes */
-    unsigned char *buf, *p;
-    const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
-    const mbedtls_x509_crt *crt;
-    int authmode;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
-
-    ssl->state++;
-
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-    if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET )
-        authmode = ssl->handshake->sni_authmode;
-    else
-#endif
-        authmode = ssl->conf->authmode;
-
-    if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ||
-        authmode == MBEDTLS_SSL_VERIFY_NONE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) );
-        return( 0 );
-    }
-
-    /*
-     *     0  .   0   handshake type
-     *     1  .   3   handshake length
-     *     4  .   4   cert type count
-     *     5  .. m-1  cert types
-     *     m  .. m+1  sig alg length (TLS 1.2 only)
-     *    m+1 .. n-1  SignatureAndHashAlgorithms (TLS 1.2 only)
-     *     n  .. n+1  length of all DNs
-     *    n+2 .. n+3  length of DN 1
-     *    n+4 .. ...  Distinguished Name #1
-     *    ... .. ...  length of DN 2, etc.
-     */
-    buf = ssl->out_msg;
-    p = buf + 4;
-
-    /*
-     * Supported certificate types
-     *
-     *     ClientCertificateType certificate_types<1..2^8-1>;
-     *     enum { (255) } ClientCertificateType;
-     */
-    ct_len = 0;
-
-#if defined(MBEDTLS_RSA_C)
-    p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN;
-#endif
-#if defined(MBEDTLS_ECDSA_C)
-    p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN;
-#endif
-
-    p[0] = (unsigned char) ct_len++;
-    p += ct_len;
-
-    sa_len = 0;
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    /*
-     * Add signature_algorithms for verify (TLS 1.2)
-     *
-     *     SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>;
-     *
-     *     struct {
-     *           HashAlgorithm hash;
-     *           SignatureAlgorithm signature;
-     *     } SignatureAndHashAlgorithm;
-     *
-     *     enum { (255) } HashAlgorithm;
-     *     enum { (255) } SignatureAlgorithm;
-     */
-    if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
-    {
-        const int *cur;
-
-        /*
-         * Supported signature algorithms
-         */
-        for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ )
-        {
-            unsigned char hash = mbedtls_ssl_hash_from_md_alg( *cur );
-
-            if( MBEDTLS_SSL_HASH_NONE == hash || mbedtls_ssl_set_calc_verify_md( ssl, hash ) )
-                continue;
-
-#if defined(MBEDTLS_RSA_C)
-            p[2 + sa_len++] = hash;
-            p[2 + sa_len++] = MBEDTLS_SSL_SIG_RSA;
-#endif
-#if defined(MBEDTLS_ECDSA_C)
-            p[2 + sa_len++] = hash;
-            p[2 + sa_len++] = MBEDTLS_SSL_SIG_ECDSA;
-#endif
-        }
-
-        MBEDTLS_PUT_UINT16_BE( sa_len, p, 0 );
-        sa_len += 2;
-        p += sa_len;
-    }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-
-    /*
-     * DistinguishedName certificate_authorities<0..2^16-1>;
-     * opaque DistinguishedName<1..2^16-1>;
-     */
-    p += 2;
-
-    total_dn_size = 0;
-
-    if( ssl->conf->cert_req_ca_list ==  MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED )
-    {
-        /* NOTE: If trusted certificates are provisioned
-         *       via a CA callback (configured through
-         *       `mbedtls_ssl_conf_ca_cb()`, then the
-         *       CertificateRequest is currently left empty. */
-
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-        if( ssl->handshake->sni_ca_chain != NULL )
-            crt = ssl->handshake->sni_ca_chain;
-        else
-#endif
-            crt = ssl->conf->ca_chain;
-
-        while( crt != NULL && crt->version != 0 )
-        {
-            /* It follows from RFC 5280 A.1 that this length
-             * can be represented in at most 11 bits. */
-            dn_size = (uint16_t) crt->subject_raw.len;
-
-            if( end < p || (size_t)( end - p ) < 2 + (size_t) dn_size )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) );
-                break;
-            }
-
-            MBEDTLS_PUT_UINT16_BE( dn_size, p, 0 );
-            p += 2;
-            memcpy( p, crt->subject_raw.p, dn_size );
-            p += dn_size;
-
-            MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size );
-
-            total_dn_size += 2 + dn_size;
-            crt = crt->next;
-        }
-    }
-
-    ssl->out_msglen  = p - buf;
-    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
-    ssl->out_msg[0]  = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST;
-    MBEDTLS_PUT_UINT16_BE( total_dn_size, ssl->out_msg, 4 + ct_len + sa_len );
-
-    ret = mbedtls_ssl_write_handshake_msg( ssl );
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) );
-
-    return( ret );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_pk_context *own_key = mbedtls_ssl_own_key( ssl );
-
-    /* Check if the key is a transparent ECDH key.
-     * This also ensures that it is safe to call mbedtls_pk_ec(). */
-    if( mbedtls_pk_get_type( own_key ) != MBEDTLS_PK_ECKEY &&
-        mbedtls_pk_get_type( own_key ) != MBEDTLS_PK_ECKEY_DH )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
-        return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
-    }
-
-    if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx,
-                                 mbedtls_pk_ec( *own_key ),
-                                 MBEDTLS_ECDH_OURS ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret );
-        return( ret );
-    }
-
-    return( 0 );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
-          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \
-    defined(MBEDTLS_SSL_ASYNC_PRIVATE)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl,
-                                           size_t *signature_len )
-{
-    /* Append the signature to ssl->out_msg, leaving 2 bytes for the
-     * signature length which will be added in ssl_write_server_key_exchange
-     * after the call to ssl_prepare_server_key_exchange.
-     * ssl_write_server_key_exchange also takes care of incrementing
-     * ssl->out_msglen. */
-    unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2;
-    size_t sig_max_len = ( ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN
-                           - sig_start );
-    int ret = ssl->conf->f_async_resume( ssl,
-                                         sig_start, signature_len, sig_max_len );
-    if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
-    {
-        ssl->handshake->async_in_progress = 0;
-        mbedtls_ssl_set_async_operation_data( ssl, NULL );
-    }
-    MBEDTLS_SSL_DEBUG_RET( 2, "ssl_resume_server_key_exchange", ret );
-    return( ret );
-}
-#endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) &&
-          defined(MBEDTLS_SSL_ASYNC_PRIVATE) */
-
-/* Prepare the ServerKeyExchange message, up to and including
- * calculating the signature if any, but excluding formatting the
- * signature and sending the message. */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl,
-                                            size_t *signature_len )
-{
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED)
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
-    unsigned char *dig_signed = NULL;
-#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */
-
-    (void) ciphersuite_info; /* unused in some configurations */
-#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
-    (void) signature_len;
-#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */
-
-    ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */
-
-    /*
-     *
-     * Part 1: Provide key exchange parameters for chosen ciphersuite.
-     *
-     */
-
-    /*
-     * - ECJPAKE key exchanges
-     */
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
-    {
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        size_t len = 0;
-
-        ret = mbedtls_ecjpake_write_round_two(
-            &ssl->handshake->ecjpake_ctx,
-            ssl->out_msg + ssl->out_msglen,
-            MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, &len,
-            ssl->conf->f_rng, ssl->conf->p_rng );
-        if( ret != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret );
-            return( ret );
-        }
-
-        ssl->out_msglen += len;
-    }
-#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-
-    /*
-     * For (EC)DHE key exchanges with PSK, parameters are prefixed by support
-     * identity hint (RFC 4279, Sec. 3). Until someone needs this feature,
-     * we use empty support identity hints here.
-     **/
-#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)   || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
-    {
-        ssl->out_msg[ssl->out_msglen++] = 0x00;
-        ssl->out_msg[ssl->out_msglen++] = 0x00;
-    }
-#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
-
-    /*
-     * - DHE key exchanges
-     */
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED)
-    if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) )
-    {
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        size_t len = 0;
-
-        if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) );
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-        }
-
-        /*
-         * Ephemeral DH parameters:
-         *
-         * struct {
-         *     opaque dh_p<1..2^16-1>;
-         *     opaque dh_g<1..2^16-1>;
-         *     opaque dh_Ys<1..2^16-1>;
-         * } ServerDHParams;
-         */
-        if( ( ret = mbedtls_dhm_set_group( &ssl->handshake->dhm_ctx,
-                                           &ssl->conf->dhm_P,
-                                           &ssl->conf->dhm_G ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_set_group", ret );
-            return( ret );
-        }
-
-        if( ( ret = mbedtls_dhm_make_params(
-                  &ssl->handshake->dhm_ctx,
-                  (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
-                  ssl->out_msg + ssl->out_msglen, &len,
-                  ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret );
-            return( ret );
-        }
-
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
-        dig_signed = ssl->out_msg + ssl->out_msglen;
-#endif
-
-        ssl->out_msglen += len;
-
-        MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X  );
-        MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P  );
-        MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G  );
-        MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX );
-    }
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED */
-
-    /*
-     * - ECDHE key exchanges
-     */
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)
-    if( mbedtls_ssl_ciphersuite_uses_ecdhe( ciphersuite_info ) )
-    {
-        /*
-         * Ephemeral ECDH parameters:
-         *
-         * struct {
-         *     ECParameters curve_params;
-         *     ECPoint      public;
-         * } ServerECDHParams;
-         */
-        const mbedtls_ecp_curve_info **curve = NULL;
-        const mbedtls_ecp_group_id *gid;
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        size_t len = 0;
-
-        /* Match our preference list against the offered curves */
-        for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ )
-            for( curve = ssl->handshake->curves; *curve != NULL; curve++ )
-                if( (*curve)->grp_id == *gid )
-                    goto curve_matching_done;
-
-curve_matching_done:
-        if( curve == NULL || *curve == NULL )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "no matching curve for ECDHE" ) );
-            return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN );
-        }
-
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) );
-
-        if( ( ret = mbedtls_ecdh_setup( &ssl->handshake->ecdh_ctx,
-                                        (*curve)->grp_id ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret );
-            return( ret );
-        }
-
-        if( ( ret = mbedtls_ecdh_make_params(
-                  &ssl->handshake->ecdh_ctx, &len,
-                  ssl->out_msg + ssl->out_msglen,
-                  MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen,
-                  ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret );
-            return( ret );
-        }
-
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
-        dig_signed = ssl->out_msg + ssl->out_msglen;
-#endif
-
-        ssl->out_msglen += len;
-
-        MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
-                                MBEDTLS_DEBUG_ECDH_Q );
-    }
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */
-
-    /*
-     *
-     * Part 2: For key exchanges involving the server signing the
-     *         exchange parameters, compute and add the signature here.
-     *
-     */
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
-    if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) )
-    {
-        size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed;
-        size_t hashlen = 0;
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-        unsigned char hash[PSA_HASH_MAX_SIZE];
-#else
-        unsigned char hash[MBEDTLS_MD_MAX_SIZE];
-#endif
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-        /*
-         * 2.1: Choose hash algorithm:
-         * A: For TLS 1.2, obey signature-hash-algorithm extension
-         *    to choose appropriate hash.
-         * B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1
-         *    (RFC 4492, Sec. 5.4)
-         * C: Otherwise, use MD5 + SHA1 (RFC 4346, Sec. 7.4.3)
-         */
-
-        mbedtls_md_type_t md_alg;
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        mbedtls_pk_type_t sig_alg =
-            mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
-        if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
-        {
-            /* A: For TLS 1.2, obey signature-hash-algorithm extension
-             *    (RFC 5246, Sec. 7.4.1.4.1). */
-            if( sig_alg == MBEDTLS_PK_NONE ||
-                ( md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs,
-                                                          sig_alg ) ) == MBEDTLS_MD_NONE )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-                /* (... because we choose a cipher suite
-                 *      only if there is a matching hash.) */
-                return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-            }
-        }
-        else
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_1)
-        if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA )
-        {
-            /* B: Default hash SHA1 */
-            md_alg = MBEDTLS_MD_SHA1;
-        }
-        else
-#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \
-          MBEDTLS_SSL_PROTO_TLS1_1 */
-        {
-            /* C: MD5 + SHA1 */
-            md_alg = MBEDTLS_MD_NONE;
-        }
-
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %u for signing", (unsigned) md_alg ) );
-
-        /*
-         * 2.2: Compute the hash to be signed
-         */
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_1)
-        if( md_alg == MBEDTLS_MD_NONE )
-        {
-            hashlen = 36;
-            ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash,
-                                                           dig_signed,
-                                                           dig_signed_len );
-            if( ret != 0 )
-                return( ret );
-        }
-        else
-#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \
-          MBEDTLS_SSL_PROTO_TLS1_1 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        if( md_alg != MBEDTLS_MD_NONE )
-        {
-            ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen,
-                                                          dig_signed,
-                                                          dig_signed_len,
-                                                          md_alg );
-            if( ret != 0 )
-                return( ret );
-        }
-        else
-#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
-          MBEDTLS_SSL_PROTO_TLS1_2 */
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-        }
-
-        MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
-
-        /*
-         * 2.3: Compute and add the signature
-         */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
-        {
-            /*
-             * For TLS 1.2, we need to specify signature and hash algorithm
-             * explicitly through a prefix to the signature.
-             *
-             * struct {
-             *    HashAlgorithm hash;
-             *    SignatureAlgorithm signature;
-             * } SignatureAndHashAlgorithm;
-             *
-             * struct {
-             *    SignatureAndHashAlgorithm algorithm;
-             *    opaque signature<0..2^16-1>;
-             * } DigitallySigned;
-             *
-             */
-
-            ssl->out_msg[ssl->out_msglen++] =
-                mbedtls_ssl_hash_from_md_alg( md_alg );
-            ssl->out_msg[ssl->out_msglen++] =
-                mbedtls_ssl_sig_from_pk_alg( sig_alg );
-        }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-
-#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
-        if( ssl->conf->f_async_sign_start != NULL )
-        {
-            ret = ssl->conf->f_async_sign_start( ssl,
-                                                 mbedtls_ssl_own_cert( ssl ),
-                                                 md_alg, hash, hashlen );
-            switch( ret )
-            {
-            case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH:
-                /* act as if f_async_sign was null */
-                break;
-            case 0:
-                ssl->handshake->async_in_progress = 1;
-                return( ssl_resume_server_key_exchange( ssl, signature_len ) );
-            case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
-                ssl->handshake->async_in_progress = 1;
-                return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS );
-            default:
-                MBEDTLS_SSL_DEBUG_RET( 1, "f_async_sign_start", ret );
-                return( ret );
-            }
-        }
-#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
-
-        if( mbedtls_ssl_own_key( ssl ) == NULL )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) );
-            return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
-        }
-
-        /* Append the signature to ssl->out_msg, leaving 2 bytes for the
-         * signature length which will be added in ssl_write_server_key_exchange
-         * after the call to ssl_prepare_server_key_exchange.
-         * ssl_write_server_key_exchange also takes care of incrementing
-         * ssl->out_msglen. */
-        if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ),
-                                     md_alg, hash, hashlen,
-                                     ssl->out_msg + ssl->out_msglen + 2,
-                                     signature_len,
-                                     ssl->conf->f_rng,
-                                     ssl->conf->p_rng ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret );
-            return( ret );
-        }
-    }
-#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */
-
-    return( 0 );
-}
-
-/* Prepare the ServerKeyExchange message and send it. For ciphersuites
- * that do not include a ServerKeyExchange message, do nothing. Either
- * way, if successful, move on to the next step in the SSL state
- * machine. */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t signature_len = 0;
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED)
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-                            ssl->handshake->ciphersuite_info;
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
-
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED)
-    /* Extract static ECDH parameters and abort if ServerKeyExchange
-     * is not needed. */
-    if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) )
-    {
-        /* For suites involving ECDH, extract DH parameters
-         * from certificate at this point. */
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED)
-        if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) )
-        {
-            ret = ssl_get_ecdh_params_from_cert( ssl );
-            if( ret != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret );
-                return( ret );
-            }
-        }
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */
-
-        /* Key exchanges not involving ephemeral keys don't use
-         * ServerKeyExchange, so end here. */
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
-        ssl->state++;
-        return( 0 );
-    }
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \
-    defined(MBEDTLS_SSL_ASYNC_PRIVATE)
-    /* If we have already prepared the message and there is an ongoing
-     * signature operation, resume signing. */
-    if( ssl->handshake->async_in_progress != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming signature operation" ) );
-        ret = ssl_resume_server_key_exchange( ssl, &signature_len );
-    }
-    else
-#endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) &&
-          defined(MBEDTLS_SSL_ASYNC_PRIVATE) */
-    {
-        /* ServerKeyExchange is needed. Prepare the message. */
-        ret = ssl_prepare_server_key_exchange( ssl, &signature_len );
-    }
-
-    if( ret != 0 )
-    {
-        /* If we're starting to write a new message, set ssl->out_msglen
-         * to 0. But if we're resuming after an asynchronous message,
-         * out_msglen is the amount of data written so far and mst be
-         * preserved. */
-        if( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange (pending)" ) );
-        else
-            ssl->out_msglen = 0;
-        return( ret );
-    }
-
-    /* If there is a signature, write its length.
-     * ssl_prepare_server_key_exchange already wrote the signature
-     * itself at its proper place in the output buffer. */
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
-    if( signature_len != 0 )
-    {
-        ssl->out_msg[ssl->out_msglen++] = MBEDTLS_BYTE_1( signature_len );
-        ssl->out_msg[ssl->out_msglen++] = MBEDTLS_BYTE_0( signature_len );
-
-        MBEDTLS_SSL_DEBUG_BUF( 3, "my signature",
-                               ssl->out_msg + ssl->out_msglen,
-                               signature_len );
-
-        /* Skip over the already-written signature */
-        ssl->out_msglen += signature_len;
-    }
-#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */
-
-    /* Add header and send. */
-    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
-    ssl->out_msg[0]  = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE;
-
-    ssl->state++;
-
-    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
-        return( ret );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) );
-    return( 0 );
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) );
-
-    ssl->out_msglen  = 4;
-    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
-    ssl->out_msg[0]  = MBEDTLS_SSL_HS_SERVER_HELLO_DONE;
-
-    ssl->state++;
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-        mbedtls_ssl_send_flight_completed( ssl );
-#endif
-
-    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
-        return( ret );
-    }
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
-        return( ret );
-    }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) );
-
-    return( 0 );
-}
-
-#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
-    defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char **p,
-                                       const unsigned char *end )
-{
-    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-    size_t n;
-
-    /*
-     * Receive G^Y mod P, premaster = (G^Y)^X mod P
-     */
-    if( *p + 2 > end )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
-    }
-
-    n = ( (*p)[0] << 8 ) | (*p)[1];
-    *p += 2;
-
-    if( *p + n > end )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
-    }
-
-    if( ( ret = mbedtls_dhm_read_public( &ssl->handshake->dhm_ctx, *p, n ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_read_public", ret );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP );
-    }
-
-    *p += n;
-
-    MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY );
-
-    return( ret );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) ||                           \
-    defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
-
-#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl,
-                                   unsigned char *peer_pms,
-                                   size_t *peer_pmslen,
-                                   size_t peer_pmssize )
-{
-    int ret = ssl->conf->f_async_resume( ssl,
-                                         peer_pms, peer_pmslen, peer_pmssize );
-    if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
-    {
-        ssl->handshake->async_in_progress = 0;
-        mbedtls_ssl_set_async_operation_data( ssl, NULL );
-    }
-    MBEDTLS_SSL_DEBUG_RET( 2, "ssl_decrypt_encrypted_pms", ret );
-    return( ret );
-}
-#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl,
-                                      const unsigned char *p,
-                                      const unsigned char *end,
-                                      unsigned char *peer_pms,
-                                      size_t *peer_pmslen,
-                                      size_t peer_pmssize )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl );
-    mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk;
-    size_t len = mbedtls_pk_get_len( public_key );
-
-#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
-    /* If we have already started decoding the message and there is an ongoing
-     * decryption operation, resume signing. */
-    if( ssl->handshake->async_in_progress != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming decryption operation" ) );
-        return( ssl_resume_decrypt_pms( ssl,
-                                        peer_pms, peer_pmslen, peer_pmssize ) );
-    }
-#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
-
-    /*
-     * Prepare to decrypt the premaster using own private RSA key
-     */
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 )
-    {
-        if ( p + 2 > end )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
-        }
-        if( *p++ != MBEDTLS_BYTE_1( len ) ||
-            *p++ != MBEDTLS_BYTE_0( len ) )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
-        }
-    }
-#endif
-
-    if( p + len != end )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
-    }
-
-    /*
-     * Decrypt the premaster secret
-     */
-#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
-    if( ssl->conf->f_async_decrypt_start != NULL )
-    {
-        ret = ssl->conf->f_async_decrypt_start( ssl,
-                                                mbedtls_ssl_own_cert( ssl ),
-                                                p, len );
-        switch( ret )
-        {
-        case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH:
-            /* act as if f_async_decrypt_start was null */
-            break;
-        case 0:
-            ssl->handshake->async_in_progress = 1;
-            return( ssl_resume_decrypt_pms( ssl,
-                                            peer_pms,
-                                            peer_pmslen,
-                                            peer_pmssize ) );
-        case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
-            ssl->handshake->async_in_progress = 1;
-            return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS );
-        default:
-            MBEDTLS_SSL_DEBUG_RET( 1, "f_async_decrypt_start", ret );
-            return( ret );
-        }
-    }
-#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
-
-    if( ! mbedtls_pk_can_do( private_key, MBEDTLS_PK_RSA ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) );
-        return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
-    }
-
-    ret = mbedtls_pk_decrypt( private_key, p, len,
-                              peer_pms, peer_pmslen, peer_pmssize,
-                              ssl->conf->f_rng, ssl->conf->p_rng );
-    return( ret );
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
-                                    const unsigned char *p,
-                                    const unsigned char *end,
-                                    size_t pms_offset )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char *pms = ssl->handshake->premaster + pms_offset;
-    unsigned char ver[2];
-    unsigned char fake_pms[48], peer_pms[48];
-    unsigned char mask;
-    size_t i, peer_pmslen;
-    unsigned int diff;
-
-    /* In case of a failure in decryption, the decryption may write less than
-     * 2 bytes of output, but we always read the first two bytes. It doesn't
-     * matter in the end because diff will be nonzero in that case due to
-     * ret being nonzero, and we only care whether diff is 0.
-     * But do initialize peer_pms and peer_pmslen for robustness anyway. This
-     * also makes memory analyzers happy (don't access uninitialized memory,
-     * even if it's an unsigned char). */
-    peer_pms[0] = peer_pms[1] = ~0;
-    peer_pmslen = 0;
-
-    ret = ssl_decrypt_encrypted_pms( ssl, p, end,
-                                     peer_pms,
-                                     &peer_pmslen,
-                                     sizeof( peer_pms ) );
-
-#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
-    if ( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
-        return( ret );
-#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
-
-    mbedtls_ssl_write_version( ssl->handshake->max_major_ver,
-                               ssl->handshake->max_minor_ver,
-                               ssl->conf->transport, ver );
-
-    /* Avoid data-dependent branches while checking for invalid
-     * padding, to protect against timing-based Bleichenbacher-type
-     * attacks. */
-    diff  = (unsigned int) ret;
-    diff |= peer_pmslen ^ 48;
-    diff |= peer_pms[0] ^ ver[0];
-    diff |= peer_pms[1] ^ ver[1];
-
-    /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */
-    mask = mbedtls_ct_uint_mask( diff );
-
-    /*
-     * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding
-     * must not cause the connection to end immediately; instead, send a
-     * bad_record_mac later in the handshake.
-     * To protect against timing-based variants of the attack, we must
-     * not have any branch that depends on whether the decryption was
-     * successful. In particular, always generate the fake premaster secret,
-     * regardless of whether it will ultimately influence the output or not.
-     */
-    ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) );
-    if( ret != 0 )
-    {
-        /* It's ok to abort on an RNG failure, since this does not reveal
-         * anything about the RSA decryption. */
-        return( ret );
-    }
-
-#if defined(MBEDTLS_SSL_DEBUG_ALL)
-    if( diff != 0 )
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
-#endif
-
-    if( sizeof( ssl->handshake->premaster ) < pms_offset ||
-        sizeof( ssl->handshake->premaster ) - pms_offset < 48 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-    ssl->handshake->pmslen = 48;
-
-    /* Set pms to either the true or the fake PMS, without
-     * data-dependent branches. */
-    for( i = 0; i < ssl->handshake->pmslen; i++ )
-        pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned char **p,
-                                          const unsigned char *end )
-{
-    int ret = 0;
-    uint16_t n;
-
-    if( ssl_conf_has_psk_or_cb( ssl->conf ) == 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) );
-        return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
-    }
-
-    /*
-     * Receive client pre-shared key identity name
-     */
-    if( end - *p < 2 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
-    }
-
-    n = ( (*p)[0] << 8 ) | (*p)[1];
-    *p += 2;
-
-    if( n == 0 || n > end - *p )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
-    }
-
-    if( ssl->conf->f_psk != NULL )
-    {
-        if( ssl->conf->f_psk( ssl->conf->p_psk, ssl, *p, n ) != 0 )
-            ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;
-    }
-    else
-    {
-        /* Identity is not a big secret since clients send it in the clear,
-         * but treat it carefully anyway, just in case */
-        if( n != ssl->conf->psk_identity_len ||
-            mbedtls_ct_memcmp( ssl->conf->psk_identity, *p, n ) != 0 )
-        {
-            ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;
-        }
-    }
-
-    if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY )
-    {
-        MBEDTLS_SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY );
-        return( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY );
-    }
-
-    *p += n;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
-    unsigned char *p, *end;
-
-    ciphersuite_info = ssl->handshake->ciphersuite_info;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) );
-
-#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && \
-    ( defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
-      defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) )
-    if( ( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
-          ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) &&
-        ( ssl->handshake->async_in_progress != 0 ) )
-    {
-        /* We've already read a record and there is an asynchronous
-         * operation in progress to decrypt it. So skip reading the
-         * record. */
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "will resume decryption of previously-read record" ) );
-    }
-    else
-#endif
-    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
-        return( ret );
-    }
-
-    p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
-    end = ssl->in_msg + ssl->in_hslen;
-
-    if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
-    }
-
-    if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
-    }
-
-#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA )
-    {
-        if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret );
-            return( ret );
-        }
-
-        if( p != end )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
-        }
-
-        if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx,
-                                      ssl->handshake->premaster,
-                                      MBEDTLS_PREMASTER_SIZE,
-                                     &ssl->handshake->pmslen,
-                                      ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS );
-        }
-
-        MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K  );
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA ||
-        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA )
-    {
-        if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx,
-                                      p, end - p) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP );
-        }
-
-        MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
-                                MBEDTLS_DEBUG_ECDH_QP );
-
-        if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
-                                      &ssl->handshake->pmslen,
-                                       ssl->handshake->premaster,
-                                       MBEDTLS_MPI_MAX_SIZE,
-                                       ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS );
-        }
-
-        MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
-                                MBEDTLS_DEBUG_ECDH_Z );
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
-          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK )
-    {
-        if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );
-            return( ret );
-        }
-
-        if( p != end )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
-        }
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-        /* For opaque PSKs, we perform the PSK-to-MS derivation automatically
-         * and skip the intermediate PMS. */
-        if( ssl_use_opaque_psk( ssl ) == 1 )
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "skip PMS generation for opaque PSK" ) );
-        else
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-        if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,
-                        ciphersuite_info->key_exchange ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret );
-            return( ret );
-        }
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
-    {
-#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
-        if ( ssl->handshake->async_in_progress != 0 )
-        {
-            /* There is an asynchronous operation in progress to
-             * decrypt the encrypted premaster secret, so skip
-             * directly to resuming this operation. */
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "PSK identity already parsed" ) );
-            /* Update p to skip the PSK identity. ssl_parse_encrypted_pms
-             * won't actually use it, but maintain p anyway for robustness. */
-            p += ssl->conf->psk_identity_len + 2;
-        }
-        else
-#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
-        if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );
-            return( ret );
-        }
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-        /* Opaque PSKs are currently only supported for PSK-only. */
-        if( ssl_use_opaque_psk( ssl ) == 1 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with RSA-PSK" ) );
-            return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
-        }
-#endif
-
-        if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret );
-            return( ret );
-        }
-
-        if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,
-                        ciphersuite_info->key_exchange ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret );
-            return( ret );
-        }
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK )
-    {
-        if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );
-            return( ret );
-        }
-        if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret );
-            return( ret );
-        }
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-        /* Opaque PSKs are currently only supported for PSK-only. */
-        if( ssl_use_opaque_psk( ssl ) == 1 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with DHE-PSK" ) );
-            return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
-        }
-#endif
-
-        if( p != end )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
-        }
-
-        if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,
-                        ciphersuite_info->key_exchange ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret );
-            return( ret );
-        }
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
-    {
-        if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );
-            return( ret );
-        }
-
-        if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx,
-                                       p, end - p ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP );
-        }
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-        /* Opaque PSKs are currently only supported for PSK-only. */
-        if( ssl_use_opaque_psk( ssl ) == 1 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with ECDHE-PSK" ) );
-            return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
-        }
-#endif
-
-        MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
-                                MBEDTLS_DEBUG_ECDH_QP );
-
-        if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,
-                        ciphersuite_info->key_exchange ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret );
-            return( ret );
-        }
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA )
-    {
-        if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 0 ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_parse_encrypted_pms_secret" ), ret );
-            return( ret );
-        }
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
-    {
-        ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx,
-                                              p, end - p );
-        if( ret != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret );
-            return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
-        }
-
-        ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx,
-                ssl->handshake->premaster, 32, &ssl->handshake->pmslen,
-                ssl->conf->f_rng, ssl->conf->p_rng );
-        if( ret != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret );
-            return( ret );
-        }
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-
-    if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
-        return( ret );
-    }
-
-    ssl->state++;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) );
-
-    return( 0 );
-}
-
-#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
-{
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
-
-    if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
-        ssl->state++;
-        return( 0 );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-    return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-}
-#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-    size_t i, sig_len;
-    unsigned char hash[48];
-    unsigned char *hash_start = hash;
-    size_t hashlen;
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    mbedtls_pk_type_t pk_alg;
-#endif
-    mbedtls_md_type_t md_alg;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-    mbedtls_pk_context * peer_pk;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
-
-    if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
-        ssl->state++;
-        return( 0 );
-    }
-
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    if( ssl->session_negotiate->peer_cert == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
-        ssl->state++;
-        return( 0 );
-    }
-#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-    if( ssl->session_negotiate->peer_cert_digest == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
-        ssl->state++;
-        return( 0 );
-    }
-#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-
-    /* Read the message without adding it to the checksum */
-    ret = mbedtls_ssl_read_record( ssl, 0 /* no checksum update */ );
-    if( 0 != ret )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record" ), ret );
-        return( ret );
-    }
-
-    ssl->state++;
-
-    /* Process the message contents */
-    if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ||
-        ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
-    }
-
-    i = mbedtls_ssl_hs_hdr_len( ssl );
-
-#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    peer_pk = &ssl->handshake->peer_pubkey;
-#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-    if( ssl->session_negotiate->peer_cert == NULL )
-    {
-        /* Should never happen */
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-    peer_pk = &ssl->session_negotiate->peer_cert->pk;
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-
-    /*
-     *  struct {
-     *     SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only
-     *     opaque signature<0..2^16-1>;
-     *  } DigitallySigned;
-     */
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_1)
-    if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 )
-    {
-        md_alg = MBEDTLS_MD_NONE;
-        hashlen = 36;
-
-        /* For ECDSA, use SHA-1, not MD-5 + SHA-1 */
-        if( mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_ECDSA ) )
-        {
-            hash_start += 16;
-            hashlen -= 16;
-            md_alg = MBEDTLS_MD_SHA1;
-        }
-    }
-    else
-#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 ||
-          MBEDTLS_SSL_PROTO_TLS1_1 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
-    {
-        if( i + 2 > ssl->in_hslen )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
-        }
-
-        /*
-         * Hash
-         */
-        md_alg = mbedtls_ssl_md_alg_from_hash( ssl->in_msg[i] );
-
-        if( md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md( ssl, ssl->in_msg[i] ) )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg"
-                                " for verify message" ) );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
-        }
-
-#if !defined(MBEDTLS_MD_SHA1)
-        if( MBEDTLS_MD_SHA1 == md_alg )
-            hash_start += 16;
-#endif
-
-        /* Info from md_alg will be used instead */
-        hashlen = 0;
-
-        i++;
-
-        /*
-         * Signature
-         */
-        if( ( pk_alg = mbedtls_ssl_pk_alg_from_sig( ssl->in_msg[i] ) )
-                        == MBEDTLS_PK_NONE )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg"
-                                " for verify message" ) );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
-        }
-
-        /*
-         * Check the certificate's key type matches the signature alg
-         */
-        if( !mbedtls_pk_can_do( peer_pk, pk_alg ) )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
-        }
-
-        i++;
-    }
-    else
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-
-    if( i + 2 > ssl->in_hslen )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
-    }
-
-    sig_len = ( ssl->in_msg[i] << 8 ) | ssl->in_msg[i+1];
-    i += 2;
-
-    if( i + sig_len != ssl->in_hslen )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
-    }
-
-    /* Calculate hash and verify signature */
-    {
-        size_t dummy_hlen;
-        ssl->handshake->calc_verify( ssl, hash, &dummy_hlen );
-    }
-
-    if( ( ret = mbedtls_pk_verify( peer_pk,
-                           md_alg, hash_start, hashlen,
-                           ssl->in_msg + i, sig_len ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret );
-        return( ret );
-    }
-
-    mbedtls_ssl_update_handshake_status( ssl );
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) );
-
-    return( ret );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t tlen;
-    uint32_t lifetime;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write new session ticket" ) );
-
-    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
-    ssl->out_msg[0]  = MBEDTLS_SSL_HS_NEW_SESSION_TICKET;
-
-    /*
-     * struct {
-     *     uint32 ticket_lifetime_hint;
-     *     opaque ticket<0..2^16-1>;
-     * } NewSessionTicket;
-     *
-     * 4  .  7   ticket_lifetime_hint (0 = unspecified)
-     * 8  .  9   ticket_len (n)
-     * 10 .  9+n ticket content
-     */
-
-    if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket,
-                                ssl->session_negotiate,
-                                ssl->out_msg + 10,
-                                ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN,
-                                &tlen, &lifetime ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret );
-        tlen = 0;
-    }
-
-    MBEDTLS_PUT_UINT32_BE( lifetime, ssl->out_msg, 4 );
-    MBEDTLS_PUT_UINT16_BE( tlen, ssl->out_msg, 8 );
-    ssl->out_msglen = 10 + tlen;
-
-    /*
-     * Morally equivalent to updating ssl->state, but NewSessionTicket and
-     * ChangeCipherSpec share the same state.
-     */
-    ssl->handshake->new_session_ticket = 0;
-
-    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
-        return( ret );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_SSL_SESSION_TICKETS */
-
-/*
- * SSL handshake -- server side -- single step
- */
-int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl )
-{
-    int ret = 0;
-
-    if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) );
-
-    if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
-        return( ret );
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
-    {
-        if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
-            return( ret );
-    }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-    switch( ssl->state )
-    {
-        case MBEDTLS_SSL_HELLO_REQUEST:
-            ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
-            break;
-
-        /*
-         *  <==   ClientHello
-         */
-        case MBEDTLS_SSL_CLIENT_HELLO:
-            ret = ssl_parse_client_hello( ssl );
-            break;
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-        case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT:
-            return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED );
-#endif
-
-        /*
-         *  ==>   ServerHello
-         *        Certificate
-         *      ( ServerKeyExchange  )
-         *      ( CertificateRequest )
-         *        ServerHelloDone
-         */
-        case MBEDTLS_SSL_SERVER_HELLO:
-            ret = ssl_write_server_hello( ssl );
-            break;
-
-        case MBEDTLS_SSL_SERVER_CERTIFICATE:
-            ret = mbedtls_ssl_write_certificate( ssl );
-            break;
-
-        case MBEDTLS_SSL_SERVER_KEY_EXCHANGE:
-            ret = ssl_write_server_key_exchange( ssl );
-            break;
-
-        case MBEDTLS_SSL_CERTIFICATE_REQUEST:
-            ret = ssl_write_certificate_request( ssl );
-            break;
-
-        case MBEDTLS_SSL_SERVER_HELLO_DONE:
-            ret = ssl_write_server_hello_done( ssl );
-            break;
-
-        /*
-         *  <== ( Certificate/Alert  )
-         *        ClientKeyExchange
-         *      ( CertificateVerify  )
-         *        ChangeCipherSpec
-         *        Finished
-         */
-        case MBEDTLS_SSL_CLIENT_CERTIFICATE:
-            ret = mbedtls_ssl_parse_certificate( ssl );
-            break;
-
-        case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:
-            ret = ssl_parse_client_key_exchange( ssl );
-            break;
-
-        case MBEDTLS_SSL_CERTIFICATE_VERIFY:
-            ret = ssl_parse_certificate_verify( ssl );
-            break;
-
-        case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC:
-            ret = mbedtls_ssl_parse_change_cipher_spec( ssl );
-            break;
-
-        case MBEDTLS_SSL_CLIENT_FINISHED:
-            ret = mbedtls_ssl_parse_finished( ssl );
-            break;
-
-        /*
-         *  ==> ( NewSessionTicket )
-         *        ChangeCipherSpec
-         *        Finished
-         */
-        case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC:
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-            if( ssl->handshake->new_session_ticket != 0 )
-                ret = ssl_write_new_session_ticket( ssl );
-            else
-#endif
-                ret = mbedtls_ssl_write_change_cipher_spec( ssl );
-            break;
-
-        case MBEDTLS_SSL_SERVER_FINISHED:
-            ret = mbedtls_ssl_write_finished( ssl );
-            break;
-
-        case MBEDTLS_SSL_FLUSH_BUFFERS:
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
-            ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
-            break;
-
-        case MBEDTLS_SSL_HANDSHAKE_WRAPUP:
-            mbedtls_ssl_handshake_wrapup( ssl );
-            break;
-
-        default:
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-    }
-
-    return( ret );
-}
-#endif /* MBEDTLS_SSL_SRV_C */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_ticket.c b/lib/libmbedtls/mbedtls/library/ssl_ticket.c
index e0126cc..7d07d19 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_ticket.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_ticket.c
@@ -21,166 +21,264 @@
 
 #if defined(MBEDTLS_SSL_TICKET_C)
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free      free
-#endif
 
-#include "mbedtls/ssl_internal.h"
+#include "ssl_misc.h"
 #include "mbedtls/ssl_ticket.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
 
 #include <string.h>
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_ssl_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+#endif
+
 /*
  * Initialize context
  */
-void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx )
+void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx)
 {
-    memset( ctx, 0, sizeof( mbedtls_ssl_ticket_context ) );
+    memset(ctx, 0, sizeof(mbedtls_ssl_ticket_context));
 
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_init( &ctx->mutex );
+    mbedtls_mutex_init(&ctx->mutex);
 #endif
 }
 
-#define MAX_KEY_BYTES 32    /* 256 bits */
+#define MAX_KEY_BYTES           MBEDTLS_SSL_TICKET_MAX_KEY_BYTES
 
-#define TICKET_KEY_NAME_BYTES    4
+#define TICKET_KEY_NAME_BYTES   MBEDTLS_SSL_TICKET_KEY_NAME_BYTES
 #define TICKET_IV_BYTES         12
 #define TICKET_CRYPT_LEN_BYTES   2
 #define TICKET_AUTH_TAG_BYTES   16
 
-#define TICKET_MIN_LEN ( TICKET_KEY_NAME_BYTES  +        \
-                         TICKET_IV_BYTES        +        \
-                         TICKET_CRYPT_LEN_BYTES +        \
-                         TICKET_AUTH_TAG_BYTES )
-#define TICKET_ADD_DATA_LEN ( TICKET_KEY_NAME_BYTES  +        \
-                              TICKET_IV_BYTES        +        \
-                              TICKET_CRYPT_LEN_BYTES )
+#define TICKET_MIN_LEN (TICKET_KEY_NAME_BYTES  +        \
+                        TICKET_IV_BYTES        +        \
+                        TICKET_CRYPT_LEN_BYTES +        \
+                        TICKET_AUTH_TAG_BYTES)
+#define TICKET_ADD_DATA_LEN (TICKET_KEY_NAME_BYTES  +        \
+                             TICKET_IV_BYTES        +        \
+                             TICKET_CRYPT_LEN_BYTES)
 
 /*
  * Generate/update a key
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx,
-                               unsigned char index )
+static int ssl_ticket_gen_key(mbedtls_ssl_ticket_context *ctx,
+                              unsigned char index)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char buf[MAX_KEY_BYTES];
+    unsigned char buf[MAX_KEY_BYTES] = { 0 };
     mbedtls_ssl_ticket_key *key = ctx->keys + index;
 
-#if defined(MBEDTLS_HAVE_TIME)
-    key->generation_time = (uint32_t) mbedtls_time( NULL );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 #endif
 
-    if( ( ret = ctx->f_rng( ctx->p_rng, key->name, sizeof( key->name ) ) ) != 0 )
-        return( ret );
+#if defined(MBEDTLS_HAVE_TIME)
+    key->generation_time = mbedtls_time(NULL);
+#endif
 
-    if( ( ret = ctx->f_rng( ctx->p_rng, buf, sizeof( buf ) ) ) != 0 )
-        return( ret );
+    if ((ret = ctx->f_rng(ctx->p_rng, key->name, sizeof(key->name))) != 0) {
+        return ret;
+    }
 
+    if ((ret = ctx->f_rng(ctx->p_rng, buf, sizeof(buf))) != 0) {
+        return ret;
+    }
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_set_key_usage_flags(&attributes,
+                            PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
+    psa_set_key_algorithm(&attributes, key->alg);
+    psa_set_key_type(&attributes, key->key_type);
+    psa_set_key_bits(&attributes, key->key_bits);
+
+    ret = PSA_TO_MBEDTLS_ERR(
+        psa_import_key(&attributes, buf,
+                       PSA_BITS_TO_BYTES(key->key_bits),
+                       &key->key));
+#else
     /* With GCM and CCM, same context can encrypt & decrypt */
-    ret = mbedtls_cipher_setkey( &key->ctx, buf,
-                                 mbedtls_cipher_get_key_bitlen( &key->ctx ),
-                                 MBEDTLS_ENCRYPT );
+    ret = mbedtls_cipher_setkey(&key->ctx, buf,
+                                mbedtls_cipher_get_key_bitlen(&key->ctx),
+                                MBEDTLS_ENCRYPT);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-    mbedtls_platform_zeroize( buf, sizeof( buf ) );
+    mbedtls_platform_zeroize(buf, sizeof(buf));
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Rotate/generate keys if necessary
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx )
+static int ssl_ticket_update_keys(mbedtls_ssl_ticket_context *ctx)
 {
 #if !defined(MBEDTLS_HAVE_TIME)
     ((void) ctx);
 #else
-    if( ctx->ticket_lifetime != 0 )
-    {
-        uint32_t current_time = (uint32_t) mbedtls_time( NULL );
-        uint32_t key_time = ctx->keys[ctx->active].generation_time;
+    if (ctx->ticket_lifetime != 0) {
+        mbedtls_time_t current_time = mbedtls_time(NULL);
+        mbedtls_time_t key_time = ctx->keys[ctx->active].generation_time;
 
-        if( current_time >= key_time &&
-            current_time - key_time < ctx->ticket_lifetime )
-        {
-            return( 0 );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+#endif
+
+        if (current_time >= key_time &&
+            (uint64_t) (current_time - key_time) < ctx->ticket_lifetime) {
+            return 0;
         }
 
         ctx->active = 1 - ctx->active;
 
-        return( ssl_ticket_gen_key( ctx, ctx->active ) );
-    }
-    else
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        if ((status = psa_destroy_key(ctx->keys[ctx->active].key)) != PSA_SUCCESS) {
+            return PSA_TO_MBEDTLS_ERR(status);
+        }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+        return ssl_ticket_gen_key(ctx, ctx->active);
+    } else
 #endif /* MBEDTLS_HAVE_TIME */
-        return( 0 );
+    return 0;
+}
+
+/*
+ * Rotate active session ticket encryption key
+ */
+int mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context *ctx,
+                              const unsigned char *name, size_t nlength,
+                              const unsigned char *k, size_t klength,
+                              uint32_t lifetime)
+{
+    const unsigned char idx = 1 - ctx->active;
+    mbedtls_ssl_ticket_key * const key = ctx->keys + idx;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    const size_t bitlen = key->key_bits;
+#else
+    const int bitlen = mbedtls_cipher_get_key_bitlen(&key->ctx);
+#endif
+
+    if (nlength < TICKET_KEY_NAME_BYTES || klength * 8 < (size_t) bitlen) {
+        return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if ((status = psa_destroy_key(key->key)) != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        return ret;
+    }
+
+    psa_set_key_usage_flags(&attributes,
+                            PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
+    psa_set_key_algorithm(&attributes, key->alg);
+    psa_set_key_type(&attributes, key->key_type);
+    psa_set_key_bits(&attributes, key->key_bits);
+
+    if ((status = psa_import_key(&attributes, k,
+                                 PSA_BITS_TO_BYTES(key->key_bits),
+                                 &key->key)) != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        return ret;
+    }
+#else
+    ret = mbedtls_cipher_setkey(&key->ctx, k, bitlen, MBEDTLS_ENCRYPT);
+    if (ret != 0) {
+        return ret;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    ctx->active = idx;
+    ctx->ticket_lifetime = lifetime;
+    memcpy(key->name, name, TICKET_KEY_NAME_BYTES);
+#if defined(MBEDTLS_HAVE_TIME)
+    key->generation_time = mbedtls_time(NULL);
+#endif
+    return 0;
 }
 
 /*
  * Setup context for actual use
  */
-int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx,
-    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
-    mbedtls_cipher_type_t cipher,
-    uint32_t lifetime )
+int mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context *ctx,
+                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+                             mbedtls_cipher_type_t cipher,
+                             uint32_t lifetime)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t key_bits;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_algorithm_t alg;
+    psa_key_type_t key_type;
+#else
     const mbedtls_cipher_info_t *cipher_info;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (mbedtls_ssl_cipher_to_psa(cipher, TICKET_AUTH_TAG_BYTES,
+                                  &alg, &key_type, &key_bits) != PSA_SUCCESS) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    if (PSA_ALG_IS_AEAD(alg) == 0) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+#else
+    cipher_info = mbedtls_cipher_info_from_type(cipher);
+
+    if (mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_GCM &&
+        mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CCM &&
+        mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CHACHAPOLY) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    key_bits = mbedtls_cipher_info_get_key_bitlen(cipher_info);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    if (key_bits > 8 * MAX_KEY_BYTES) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
     ctx->f_rng = f_rng;
     ctx->p_rng = p_rng;
 
     ctx->ticket_lifetime = lifetime;
 
-    cipher_info = mbedtls_cipher_info_from_type( cipher);
-    if( cipher_info == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    ctx->keys[0].alg = alg;
+    ctx->keys[0].key_type = key_type;
+    ctx->keys[0].key_bits = key_bits;
 
-    if( cipher_info->mode != MBEDTLS_MODE_GCM &&
-        cipher_info->mode != MBEDTLS_MODE_CCM )
-    {
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    ctx->keys[1].alg = alg;
+    ctx->keys[1].key_type = key_type;
+    ctx->keys[1].key_bits = key_bits;
+#else
+    if ((ret = mbedtls_cipher_setup(&ctx->keys[0].ctx, cipher_info)) != 0) {
+        return ret;
     }
 
-    if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    ret = mbedtls_cipher_setup_psa( &ctx->keys[0].ctx,
-                                    cipher_info, TICKET_AUTH_TAG_BYTES );
-    if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
-        return( ret );
-    /* We don't yet expect to support all ciphers through PSA,
-     * so allow fallback to ordinary mbedtls_cipher_setup(). */
-    if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
+    if ((ret = mbedtls_cipher_setup(&ctx->keys[1].ctx, cipher_info)) != 0) {
+        return ret;
+    }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
-    if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 )
-        return( ret );
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    ret = mbedtls_cipher_setup_psa( &ctx->keys[1].ctx,
-                                    cipher_info, TICKET_AUTH_TAG_BYTES );
-    if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
-        return( ret );
-    if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-    if( ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 )
-        return( ret );
-
-    if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 ||
-        ( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = ssl_ticket_gen_key(ctx, 0)) != 0 ||
+        (ret = ssl_ticket_gen_key(ctx, 1)) != 0) {
+        return ret;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -197,12 +295,12 @@
  * authenticated data.
  */
 
-int mbedtls_ssl_ticket_write( void *p_ticket,
-                              const mbedtls_ssl_session *session,
-                              unsigned char *start,
-                              const unsigned char *end,
-                              size_t *tlen,
-                              uint32_t *ticket_lifetime )
+int mbedtls_ssl_ticket_write(void *p_ticket,
+                             const mbedtls_ssl_session *session,
+                             unsigned char *start,
+                             const unsigned char *end,
+                             size_t *tlen,
+                             uint32_t *ticket_lifetime)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ssl_ticket_context *ctx = p_ticket;
@@ -213,55 +311,72 @@
     unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES;
     size_t clear_len, ciph_len;
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+#endif
+
     *tlen = 0;
 
-    if( ctx == NULL || ctx->f_rng == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ctx == NULL || ctx->f_rng == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
     /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag,
      * in addition to session itself, that will be checked when writing it. */
-    MBEDTLS_SSL_CHK_BUF_PTR( start, end, TICKET_MIN_LEN );
+    MBEDTLS_SSL_CHK_BUF_PTR(start, end, TICKET_MIN_LEN);
 
 #if defined(MBEDTLS_THREADING_C)
-    if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
+        return ret;
+    }
 #endif
 
-    if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 )
+    if ((ret = ssl_ticket_update_keys(ctx)) != 0) {
         goto cleanup;
+    }
 
     key = &ctx->keys[ctx->active];
 
     *ticket_lifetime = ctx->ticket_lifetime;
 
-    memcpy( key_name, key->name, TICKET_KEY_NAME_BYTES );
+    memcpy(key_name, key->name, TICKET_KEY_NAME_BYTES);
 
-    if( ( ret = ctx->f_rng( ctx->p_rng, iv, TICKET_IV_BYTES ) ) != 0 )
+    if ((ret = ctx->f_rng(ctx->p_rng, iv, TICKET_IV_BYTES)) != 0) {
         goto cleanup;
+    }
 
     /* Dump session state */
-    if( ( ret = mbedtls_ssl_session_save( session,
-                                          state, end - state,
-                                          &clear_len ) ) != 0 ||
-        (unsigned long) clear_len > 65535 )
-    {
-         goto cleanup;
-    }
-    MBEDTLS_PUT_UINT16_BE( clear_len, state_len_bytes, 0 );
-
-    /* Encrypt and authenticate */
-    if( ( ret = mbedtls_cipher_auth_encrypt_ext( &key->ctx,
-                    iv, TICKET_IV_BYTES,
-                    /* Additional data: key name, IV and length */
-                    key_name, TICKET_ADD_DATA_LEN,
-                    state, clear_len,
-                    state, end - state, &ciph_len,
-                    TICKET_AUTH_TAG_BYTES ) ) != 0 )
-    {
+    if ((ret = mbedtls_ssl_session_save(session,
+                                        state, end - state,
+                                        &clear_len)) != 0 ||
+        (unsigned long) clear_len > 65535) {
         goto cleanup;
     }
-    if( ciph_len != clear_len + TICKET_AUTH_TAG_BYTES )
-    {
+    MBEDTLS_PUT_UINT16_BE(clear_len, state_len_bytes, 0);
+
+    /* Encrypt and authenticate */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if ((status = psa_aead_encrypt(key->key, key->alg, iv, TICKET_IV_BYTES,
+                                   key_name, TICKET_ADD_DATA_LEN,
+                                   state, clear_len,
+                                   state, end - state,
+                                   &ciph_len)) != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        goto cleanup;
+    }
+#else
+    if ((ret = mbedtls_cipher_auth_encrypt_ext(&key->ctx,
+                                               iv, TICKET_IV_BYTES,
+                                               /* Additional data: key name, IV and length */
+                                               key_name, TICKET_ADD_DATA_LEN,
+                                               state, clear_len,
+                                               state, end - state, &ciph_len,
+                                               TICKET_AUTH_TAG_BYTES)) != 0) {
+        goto cleanup;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    if (ciph_len != clear_len + TICKET_AUTH_TAG_BYTES) {
         ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
         goto cleanup;
     }
@@ -270,36 +385,39 @@
 
 cleanup:
 #if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
-        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
+        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
+    }
 #endif
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Select key based on name
  */
 static mbedtls_ssl_ticket_key *ssl_ticket_select_key(
-        mbedtls_ssl_ticket_context *ctx,
-        const unsigned char name[4] )
+    mbedtls_ssl_ticket_context *ctx,
+    const unsigned char name[4])
 {
     unsigned char i;
 
-    for( i = 0; i < sizeof( ctx->keys ) / sizeof( *ctx->keys ); i++ )
-        if( memcmp( name, ctx->keys[i].name, 4 ) == 0 )
-            return( &ctx->keys[i] );
+    for (i = 0; i < sizeof(ctx->keys) / sizeof(*ctx->keys); i++) {
+        if (memcmp(name, ctx->keys[i].name, 4) == 0) {
+            return &ctx->keys[i];
+        }
+    }
 
-    return( NULL );
+    return NULL;
 }
 
 /*
  * Load session ticket (see mbedtls_ssl_ticket_write for structure)
  */
-int mbedtls_ssl_ticket_parse( void *p_ticket,
-                              mbedtls_ssl_session *session,
-                              unsigned char *buf,
-                              size_t len )
+int mbedtls_ssl_ticket_parse(void *p_ticket,
+                             mbedtls_ssl_session *session,
+                             unsigned char *buf,
+                             size_t len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ssl_ticket_context *ctx = p_ticket;
@@ -310,31 +428,37 @@
     unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES;
     size_t enc_len, clear_len;
 
-    if( ctx == NULL || ctx->f_rng == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    if( len < TICKET_MIN_LEN )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-#if defined(MBEDTLS_THREADING_C)
-    if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
-        return( ret );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 #endif
 
-    if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 )
+    if (ctx == NULL || ctx->f_rng == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    if (len < TICKET_MIN_LEN) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+#if defined(MBEDTLS_THREADING_C)
+    if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
+        return ret;
+    }
+#endif
+
+    if ((ret = ssl_ticket_update_keys(ctx)) != 0) {
         goto cleanup;
+    }
 
-    enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1];
+    enc_len = (enc_len_p[0] << 8) | enc_len_p[1];
 
-    if( len != TICKET_MIN_LEN + enc_len )
-    {
+    if (len != TICKET_MIN_LEN + enc_len) {
         ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
         goto cleanup;
     }
 
     /* Select key */
-    if( ( key = ssl_ticket_select_key( ctx, key_name ) ) == NULL )
-    {
+    if ((key = ssl_ticket_select_key(ctx, key_name)) == NULL) {
         /* We can't know for sure but this is a likely option unless we're
          * under attack - this is only informative anyway */
         ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
@@ -342,37 +466,47 @@
     }
 
     /* Decrypt and authenticate */
-    if( ( ret = mbedtls_cipher_auth_decrypt_ext( &key->ctx,
-                    iv, TICKET_IV_BYTES,
-                    /* Additional data: key name, IV and length */
-                    key_name, TICKET_ADD_DATA_LEN,
-                    ticket, enc_len + TICKET_AUTH_TAG_BYTES,
-                    ticket, enc_len, &clear_len,
-                    TICKET_AUTH_TAG_BYTES ) ) != 0 )
-    {
-        if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED )
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if ((status = psa_aead_decrypt(key->key, key->alg, iv, TICKET_IV_BYTES,
+                                   key_name, TICKET_ADD_DATA_LEN,
+                                   ticket, enc_len + TICKET_AUTH_TAG_BYTES,
+                                   ticket, enc_len, &clear_len)) != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        goto cleanup;
+    }
+#else
+    if ((ret = mbedtls_cipher_auth_decrypt_ext(&key->ctx,
+                                               iv, TICKET_IV_BYTES,
+                                               /* Additional data: key name, IV and length */
+                                               key_name, TICKET_ADD_DATA_LEN,
+                                               ticket, enc_len + TICKET_AUTH_TAG_BYTES,
+                                               ticket, enc_len, &clear_len,
+                                               TICKET_AUTH_TAG_BYTES)) != 0) {
+        if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) {
             ret = MBEDTLS_ERR_SSL_INVALID_MAC;
+        }
 
         goto cleanup;
     }
-    if( clear_len != enc_len )
-    {
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    if (clear_len != enc_len) {
         ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
         goto cleanup;
     }
 
     /* Actually load session */
-    if( ( ret = mbedtls_ssl_session_load( session, ticket, clear_len ) ) != 0 )
+    if ((ret = mbedtls_ssl_session_load(session, ticket, clear_len)) != 0) {
         goto cleanup;
+    }
 
 #if defined(MBEDTLS_HAVE_TIME)
     {
         /* Check for expiration */
-        mbedtls_time_t current_time = mbedtls_time( NULL );
+        mbedtls_time_t current_time = mbedtls_time(NULL);
 
-        if( current_time < session->start ||
-            (uint32_t)( current_time - session->start ) > ctx->ticket_lifetime )
-        {
+        if (current_time < session->start ||
+            (uint32_t) (current_time - session->start) > ctx->ticket_lifetime) {
             ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
             goto cleanup;
         }
@@ -381,26 +515,32 @@
 
 cleanup:
 #if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
-        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+    if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
+        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
+    }
 #endif
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Free context
  */
-void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx )
+void mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx)
 {
-    mbedtls_cipher_free( &ctx->keys[0].ctx );
-    mbedtls_cipher_free( &ctx->keys[1].ctx );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_destroy_key(ctx->keys[0].key);
+    psa_destroy_key(ctx->keys[1].key);
+#else
+    mbedtls_cipher_free(&ctx->keys[0].ctx);
+    mbedtls_cipher_free(&ctx->keys[1].ctx);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #if defined(MBEDTLS_THREADING_C)
-    mbedtls_mutex_free( &ctx->mutex );
+    mbedtls_mutex_free(&ctx->mutex);
 #endif
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_ticket_context));
 }
 
 #endif /* MBEDTLS_SSL_TICKET_C */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls.c b/lib/libmbedtls/mbedtls/library/ssl_tls.c
index 7badec5..a6129da 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_tls.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls.c
@@ -1,5 +1,5 @@
 /*
- *  SSLv3/TLSv1 shared functions
+ *  TLS shared functions
  *
  *  Copyright The Mbed TLS Contributors
  *  SPDX-License-Identifier: Apache-2.0
@@ -17,10 +17,6 @@
  *  limitations under the License.
  */
 /*
- *  The SSL 3.0 specification was drafted by Netscape in 1996,
- *  and became an IETF standard in 1999.
- *
- *  http://wp.netscape.com/eng/ssl3/
  *  http://www.ietf.org/rfc/rfc2246.txt
  *  http://www.ietf.org/rfc/rfc4346.txt
  */
@@ -29,16 +25,13 @@
 
 #if defined(MBEDTLS_SSL_TLS_C)
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free      free
-#endif
 
 #include "mbedtls/ssl.h"
-#include "mbedtls/ssl_internal.h"
+#include "ssl_client.h"
+#include "ssl_debug_helpers.h"
+#include "ssl_misc.h"
+
 #include "mbedtls/debug.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
@@ -51,103 +44,162 @@
 #include "mbedtls/psa_util.h"
 #include "psa/crypto.h"
 #endif
+#include "mbedtls/legacy_or_psa.h"
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 #include "mbedtls/oid.h"
 #endif
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \
+                                                           psa_to_ssl_errors, \
+                                                           psa_generic_status_to_mbedtls)
+#define PSA_TO_MD_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \
+                                                      psa_to_md_errors, \
+                                                      psa_generic_status_to_mbedtls)
+#endif
+
+#if defined(MBEDTLS_TEST_HOOKS)
+static mbedtls_ssl_chk_buf_ptr_args chk_buf_ptr_fail_args;
+
+void mbedtls_ssl_set_chk_buf_ptr_fail_args(
+    const uint8_t *cur, const uint8_t *end, size_t need)
+{
+    chk_buf_ptr_fail_args.cur = cur;
+    chk_buf_ptr_fail_args.end = end;
+    chk_buf_ptr_fail_args.need = need;
+}
+
+void mbedtls_ssl_reset_chk_buf_ptr_fail_args(void)
+{
+    memset(&chk_buf_ptr_fail_args, 0, sizeof(chk_buf_ptr_fail_args));
+}
+
+int mbedtls_ssl_cmp_chk_buf_ptr_fail_args(mbedtls_ssl_chk_buf_ptr_args *args)
+{
+    return (chk_buf_ptr_fail_args.cur  != args->cur) ||
+           (chk_buf_ptr_fail_args.end  != args->end) ||
+           (chk_buf_ptr_fail_args.need != args->need);
+}
+#endif /* MBEDTLS_TEST_HOOKS */
+
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
 /* Top-level Connection ID API */
 
-int mbedtls_ssl_conf_cid( mbedtls_ssl_config *conf,
-                          size_t len,
-                          int ignore_other_cid )
+int mbedtls_ssl_conf_cid(mbedtls_ssl_config *conf,
+                         size_t len,
+                         int ignore_other_cid)
 {
-    if( len > MBEDTLS_SSL_CID_IN_LEN_MAX )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (len > MBEDTLS_SSL_CID_IN_LEN_MAX) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    if( ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_FAIL &&
-        ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_IGNORE )
-    {
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_FAIL &&
+        ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_IGNORE) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
     conf->ignore_unexpected_cid = ignore_other_cid;
     conf->cid_len = len;
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_ssl_set_cid( mbedtls_ssl_context *ssl,
-                         int enable,
-                         unsigned char const *own_cid,
-                         size_t own_cid_len )
+int mbedtls_ssl_set_cid(mbedtls_ssl_context *ssl,
+                        int enable,
+                        unsigned char const *own_cid,
+                        size_t own_cid_len)
 {
-    if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
     ssl->negotiate_cid = enable;
-    if( enable == MBEDTLS_SSL_CID_DISABLED )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "Disable use of CID extension." ) );
-        return( 0 );
+    if (enable == MBEDTLS_SSL_CID_DISABLED) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("Disable use of CID extension."));
+        return 0;
     }
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "Enable use of CID extension." ) );
-    MBEDTLS_SSL_DEBUG_BUF( 3, "Own CID", own_cid, own_cid_len );
+    MBEDTLS_SSL_DEBUG_MSG(3, ("Enable use of CID extension."));
+    MBEDTLS_SSL_DEBUG_BUF(3, "Own CID", own_cid, own_cid_len);
 
-    if( own_cid_len != ssl->conf->cid_len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "CID length %u does not match CID length %u in config",
-                                    (unsigned) own_cid_len,
-                                    (unsigned) ssl->conf->cid_len ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (own_cid_len != ssl->conf->cid_len) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("CID length %u does not match CID length %u in config",
+                                  (unsigned) own_cid_len,
+                                  (unsigned) ssl->conf->cid_len));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    memcpy( ssl->own_cid, own_cid, own_cid_len );
+    memcpy(ssl->own_cid, own_cid, own_cid_len);
     /* Truncation is not an issue here because
      * MBEDTLS_SSL_CID_IN_LEN_MAX at most 255. */
     ssl->own_cid_len = (uint8_t) own_cid_len;
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_ssl_get_peer_cid( mbedtls_ssl_context *ssl,
-                     int *enabled,
-                     unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ],
-                     size_t *peer_cid_len )
+int mbedtls_ssl_get_own_cid(mbedtls_ssl_context *ssl,
+                            int *enabled,
+                            unsigned char own_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX],
+                            size_t *own_cid_len)
 {
     *enabled = MBEDTLS_SSL_CID_DISABLED;
 
-    if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
-        ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
-    {
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    /* We report MBEDTLS_SSL_CID_DISABLED in case the CID length is
+     * zero as this is indistinguishable from not requesting to use
+     * the CID extension. */
+    if (ssl->own_cid_len == 0 || ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) {
+        return 0;
+    }
+
+    if (own_cid_len != NULL) {
+        *own_cid_len = ssl->own_cid_len;
+        if (own_cid != NULL) {
+            memcpy(own_cid, ssl->own_cid, ssl->own_cid_len);
+        }
+    }
+
+    *enabled = MBEDTLS_SSL_CID_ENABLED;
+
+    return 0;
+}
+
+int mbedtls_ssl_get_peer_cid(mbedtls_ssl_context *ssl,
+                             int *enabled,
+                             unsigned char peer_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX],
+                             size_t *peer_cid_len)
+{
+    *enabled = MBEDTLS_SSL_CID_DISABLED;
+
+    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
+        mbedtls_ssl_is_handshake_over(ssl) == 0) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
     /* We report MBEDTLS_SSL_CID_DISABLED in case the CID extensions
      * were used, but client and server requested the empty CID.
      * This is indistinguishable from not using the CID extension
      * in the first place. */
-    if( ssl->transform_in->in_cid_len  == 0 &&
-        ssl->transform_in->out_cid_len == 0 )
-    {
-        return( 0 );
+    if (ssl->transform_in->in_cid_len  == 0 &&
+        ssl->transform_in->out_cid_len == 0) {
+        return 0;
     }
 
-    if( peer_cid_len != NULL )
-    {
+    if (peer_cid_len != NULL) {
         *peer_cid_len = ssl->transform_in->out_cid_len;
-        if( peer_cid != NULL )
-        {
-            memcpy( peer_cid, ssl->transform_in->out_cid,
-                    ssl->transform_in->out_cid_len );
+        if (peer_cid != NULL) {
+            memcpy(peer_cid, ssl->transform_in->out_cid,
+                   ssl->transform_in->out_cid_len);
         }
     }
 
     *enabled = MBEDTLS_SSL_CID_ENABLED;
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
@@ -162,67 +214,68 @@
  *    } MaxFragmentLength;
  * and we add 0 -> extension unused
  */
-static unsigned int ssl_mfl_code_to_length( int mfl )
+static unsigned int ssl_mfl_code_to_length(int mfl)
 {
-    switch( mfl )
-    {
-    case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
-        return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN );
-    case MBEDTLS_SSL_MAX_FRAG_LEN_512:
-        return 512;
-    case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
-        return 1024;
-    case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
-        return 2048;
-    case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
-        return 4096;
-    default:
-        return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN );
+    switch (mfl) {
+        case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
+            return MBEDTLS_TLS_EXT_ADV_CONTENT_LEN;
+        case MBEDTLS_SSL_MAX_FRAG_LEN_512:
+            return 512;
+        case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
+            return 1024;
+        case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
+            return 2048;
+        case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
+            return 4096;
+        default:
+            return MBEDTLS_TLS_EXT_ADV_CONTENT_LEN;
     }
 }
 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
 
-int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst,
-                              const mbedtls_ssl_session *src )
+int mbedtls_ssl_session_copy(mbedtls_ssl_session *dst,
+                             const mbedtls_ssl_session *src)
 {
-    mbedtls_ssl_session_free( dst );
-    memcpy( dst, src, sizeof( mbedtls_ssl_session ) );
-
+    mbedtls_ssl_session_free(dst);
+    memcpy(dst, src, sizeof(mbedtls_ssl_session));
 #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
     dst->ticket = NULL;
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
+    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    dst->hostname = NULL;
 #endif
+#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 
 #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    if( src->peer_cert != NULL )
-    {
+    if (src->peer_cert != NULL) {
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-        dst->peer_cert = mbedtls_calloc( 1, sizeof(mbedtls_x509_crt) );
-        if( dst->peer_cert == NULL )
-            return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+        dst->peer_cert = mbedtls_calloc(1, sizeof(mbedtls_x509_crt));
+        if (dst->peer_cert == NULL) {
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        }
 
-        mbedtls_x509_crt_init( dst->peer_cert );
+        mbedtls_x509_crt_init(dst->peer_cert);
 
-        if( ( ret = mbedtls_x509_crt_parse_der( dst->peer_cert, src->peer_cert->raw.p,
-                                        src->peer_cert->raw.len ) ) != 0 )
-        {
-            mbedtls_free( dst->peer_cert );
+        if ((ret = mbedtls_x509_crt_parse_der(dst->peer_cert, src->peer_cert->raw.p,
+                                              src->peer_cert->raw.len)) != 0) {
+            mbedtls_free(dst->peer_cert);
             dst->peer_cert = NULL;
-            return( ret );
+            return ret;
         }
     }
 #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-    if( src->peer_cert_digest != NULL )
-    {
+    if (src->peer_cert_digest != NULL) {
         dst->peer_cert_digest =
-            mbedtls_calloc( 1, src->peer_cert_digest_len );
-        if( dst->peer_cert_digest == NULL )
-            return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+            mbedtls_calloc(1, src->peer_cert_digest_len);
+        if (dst->peer_cert_digest == NULL) {
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        }
 
-        memcpy( dst->peer_cert_digest, src->peer_cert_digest,
-                src->peer_cert_digest_len );
+        memcpy(dst->peer_cert_digest, src->peer_cert_digest,
+               src->peer_cert_digest_len);
         dst->peer_cert_digest_type = src->peer_cert_digest_type;
         dst->peer_cert_digest_len = src->peer_cert_digest_len;
     }
@@ -231,35 +284,48 @@
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
-    if( src->ticket != NULL )
-    {
-        dst->ticket = mbedtls_calloc( 1, src->ticket_len );
-        if( dst->ticket == NULL )
-            return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+    if (src->ticket != NULL) {
+        dst->ticket = mbedtls_calloc(1, src->ticket_len);
+        if (dst->ticket == NULL) {
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        }
 
-        memcpy( dst->ticket, src->ticket, src->ticket_len );
+        memcpy(dst->ticket, src->ticket, src->ticket_len);
     }
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
+    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    if (src->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        ret = mbedtls_ssl_session_set_hostname(dst, src->hostname);
+        if (ret != 0) {
+            return ret;
+        }
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 &&
+          MBEDTLS_SSL_SERVER_NAME_INDICATION */
 #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
 
-    return( 0 );
+    return 0;
 }
 
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int resize_buffer( unsigned char **buffer, size_t len_new, size_t *len_old )
+static int resize_buffer(unsigned char **buffer, size_t len_new, size_t *len_old)
 {
-    unsigned char* resized_buffer = mbedtls_calloc( 1, len_new );
-    if( resized_buffer == NULL )
+    unsigned char *resized_buffer = mbedtls_calloc(1, len_new);
+    if (resized_buffer == NULL) {
         return -1;
+    }
 
     /* We want to copy len_new bytes when downsizing the buffer, and
      * len_old bytes when upsizing, so we choose the smaller of two sizes,
      * to fit one buffer into another. Size checks, ensuring that no data is
      * lost, are done outside of this function. */
-    memcpy( resized_buffer, *buffer,
-            ( len_new < *len_old ) ? len_new : *len_old );
-    mbedtls_platform_zeroize( *buffer, *len_old );
-    mbedtls_free( *buffer );
+    memcpy(resized_buffer, *buffer,
+           (len_new < *len_old) ? len_new : *len_old);
+    mbedtls_platform_zeroize(*buffer, *len_old);
+    mbedtls_free(*buffer);
 
     *buffer = resized_buffer;
     *len_old = len_new;
@@ -267,60 +333,49 @@
     return 0;
 }
 
-static void handle_buffer_resizing( mbedtls_ssl_context *ssl, int downsizing,
-                                    size_t in_buf_new_len,
-                                    size_t out_buf_new_len )
+static void handle_buffer_resizing(mbedtls_ssl_context *ssl, int downsizing,
+                                   size_t in_buf_new_len,
+                                   size_t out_buf_new_len)
 {
     int modified = 0;
     size_t written_in = 0, iv_offset_in = 0, len_offset_in = 0;
     size_t written_out = 0, iv_offset_out = 0, len_offset_out = 0;
-    if( ssl->in_buf != NULL )
-    {
+    if (ssl->in_buf != NULL) {
         written_in = ssl->in_msg - ssl->in_buf;
         iv_offset_in = ssl->in_iv - ssl->in_buf;
         len_offset_in = ssl->in_len - ssl->in_buf;
-        if( downsizing ?
+        if (downsizing ?
             ssl->in_buf_len > in_buf_new_len && ssl->in_left < in_buf_new_len :
-            ssl->in_buf_len < in_buf_new_len )
-        {
-            if( resize_buffer( &ssl->in_buf, in_buf_new_len, &ssl->in_buf_len ) != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "input buffer resizing failed - out of memory" ) );
-            }
-            else
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating in_buf to %" MBEDTLS_PRINTF_SIZET,
-                                            in_buf_new_len ) );
+            ssl->in_buf_len < in_buf_new_len) {
+            if (resize_buffer(&ssl->in_buf, in_buf_new_len, &ssl->in_buf_len) != 0) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("input buffer resizing failed - out of memory"));
+            } else {
+                MBEDTLS_SSL_DEBUG_MSG(2, ("Reallocating in_buf to %" MBEDTLS_PRINTF_SIZET,
+                                          in_buf_new_len));
                 modified = 1;
             }
         }
     }
 
-    if( ssl->out_buf != NULL )
-    {
+    if (ssl->out_buf != NULL) {
         written_out = ssl->out_msg - ssl->out_buf;
         iv_offset_out = ssl->out_iv - ssl->out_buf;
         len_offset_out = ssl->out_len - ssl->out_buf;
-        if( downsizing ?
+        if (downsizing ?
             ssl->out_buf_len > out_buf_new_len && ssl->out_left < out_buf_new_len :
-            ssl->out_buf_len < out_buf_new_len )
-        {
-            if( resize_buffer( &ssl->out_buf, out_buf_new_len, &ssl->out_buf_len ) != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "output buffer resizing failed - out of memory" ) );
-            }
-            else
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating out_buf to %" MBEDTLS_PRINTF_SIZET,
-                                            out_buf_new_len ) );
+            ssl->out_buf_len < out_buf_new_len) {
+            if (resize_buffer(&ssl->out_buf, out_buf_new_len, &ssl->out_buf_len) != 0) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("output buffer resizing failed - out of memory"));
+            } else {
+                MBEDTLS_SSL_DEBUG_MSG(2, ("Reallocating out_buf to %" MBEDTLS_PRINTF_SIZET,
+                                          out_buf_new_len));
                 modified = 1;
             }
         }
     }
-    if( modified )
-    {
+    if (modified) {
         /* Update pointers here to avoid doing it twice. */
-        mbedtls_ssl_reset_in_out_pointers( ssl );
+        mbedtls_ssl_reset_in_out_pointers(ssl);
         /* Fields below might not be properly updated with record
          * splitting or with CID, so they are manually updated here. */
         ssl->out_msg = ssl->out_buf + written_out;
@@ -334,1838 +389,119 @@
 }
 #endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */
 
-/*
- * Key material generation
- */
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl3_prf( const unsigned char *secret, size_t slen,
-                     const char *label,
-                     const unsigned char *random, size_t rlen,
-                     unsigned char *dstbuf, size_t dlen )
-{
-    int ret = 0;
-    size_t i;
-    mbedtls_md5_context md5;
-    mbedtls_sha1_context sha1;
-    unsigned char padding[16];
-    unsigned char sha1sum[20];
-    ((void)label);
-
-    mbedtls_md5_init(  &md5  );
-    mbedtls_sha1_init( &sha1 );
-
-    /*
-     *  SSLv3:
-     *    block =
-     *      MD5( secret + SHA1( 'A'    + secret + random ) ) +
-     *      MD5( secret + SHA1( 'BB'   + secret + random ) ) +
-     *      MD5( secret + SHA1( 'CCC'  + secret + random ) ) +
-     *      ...
-     */
-    for( i = 0; i < dlen / 16; i++ )
-    {
-        memset( padding, (unsigned char) ('A' + i), 1 + i );
-
-        if( ( ret = mbedtls_sha1_starts_ret( &sha1 ) ) != 0 )
-            goto exit;
-        if( ( ret = mbedtls_sha1_update_ret( &sha1, padding, 1 + i ) ) != 0 )
-            goto exit;
-        if( ( ret = mbedtls_sha1_update_ret( &sha1, secret, slen ) ) != 0 )
-            goto exit;
-        if( ( ret = mbedtls_sha1_update_ret( &sha1, random, rlen ) ) != 0 )
-            goto exit;
-        if( ( ret = mbedtls_sha1_finish_ret( &sha1, sha1sum ) ) != 0 )
-            goto exit;
-
-        if( ( ret = mbedtls_md5_starts_ret( &md5 ) ) != 0 )
-            goto exit;
-        if( ( ret = mbedtls_md5_update_ret( &md5, secret, slen ) ) != 0 )
-            goto exit;
-        if( ( ret = mbedtls_md5_update_ret( &md5, sha1sum, 20 ) ) != 0 )
-            goto exit;
-        if( ( ret = mbedtls_md5_finish_ret( &md5, dstbuf + i * 16 ) ) != 0 )
-            goto exit;
-    }
-
-exit:
-    mbedtls_md5_free(  &md5  );
-    mbedtls_sha1_free( &sha1 );
-
-    mbedtls_platform_zeroize( padding, sizeof( padding ) );
-    mbedtls_platform_zeroize( sha1sum, sizeof( sha1sum ) );
-
-    return( ret );
-}
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int tls1_prf( const unsigned char *secret, size_t slen,
-                     const char *label,
-                     const unsigned char *random, size_t rlen,
-                     unsigned char *dstbuf, size_t dlen )
-{
-    size_t nb, hs;
-    size_t i, j, k;
-    const unsigned char *S1, *S2;
-    unsigned char *tmp;
-    size_t tmp_len = 0;
-    unsigned char h_i[20];
-    const mbedtls_md_info_t *md_info;
-    mbedtls_md_context_t md_ctx;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    mbedtls_md_init( &md_ctx );
-
-    tmp_len = 20 + strlen( label ) + rlen;
-    tmp = mbedtls_calloc( 1, tmp_len );
-    if( tmp == NULL )
-    {
-        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
-        goto exit;
-    }
-
-    hs = ( slen + 1 ) / 2;
-    S1 = secret;
-    S2 = secret + slen - hs;
-
-    nb = strlen( label );
-    memcpy( tmp + 20, label, nb );
-    memcpy( tmp + 20 + nb, random, rlen );
-    nb += rlen;
-
-    /*
-     * First compute P_md5(secret,label+random)[0..dlen]
-     */
-    if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ) ) == NULL )
-    {
-        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-        goto exit;
-    }
-
-    if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
-    {
-        goto exit;
-    }
-
-    ret = mbedtls_md_hmac_starts( &md_ctx, S1, hs );
-    if( ret != 0 )
-        goto exit;
-    ret = mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb );
-    if( ret != 0 )
-        goto exit;
-    ret = mbedtls_md_hmac_finish( &md_ctx, 4 + tmp );
-    if( ret != 0 )
-        goto exit;
-
-    for( i = 0; i < dlen; i += 16 )
-    {
-        ret = mbedtls_md_hmac_reset ( &md_ctx );
-        if( ret != 0 )
-            goto exit;
-        ret = mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 + nb );
-        if( ret != 0 )
-            goto exit;
-        ret = mbedtls_md_hmac_finish( &md_ctx, h_i );
-        if( ret != 0 )
-            goto exit;
-
-        ret = mbedtls_md_hmac_reset ( &md_ctx );
-        if( ret != 0 )
-            goto exit;
-        ret = mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 );
-        if( ret != 0 )
-            goto exit;
-        ret = mbedtls_md_hmac_finish( &md_ctx, 4 + tmp );
-        if( ret != 0 )
-            goto exit;
-
-        k = ( i + 16 > dlen ) ? dlen % 16 : 16;
-
-        for( j = 0; j < k; j++ )
-            dstbuf[i + j]  = h_i[j];
-    }
-
-    mbedtls_md_free( &md_ctx );
-
-    /*
-     * XOR out with P_sha1(secret,label+random)[0..dlen]
-     */
-    if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) == NULL )
-    {
-        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-        goto exit;
-    }
-
-    if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
-    {
-        goto exit;
-    }
-
-    ret = mbedtls_md_hmac_starts( &md_ctx, S2, hs );
-    if( ret != 0 )
-        goto exit;
-    ret = mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb );
-    if( ret != 0 )
-        goto exit;
-    ret = mbedtls_md_hmac_finish( &md_ctx, tmp );
-    if( ret != 0 )
-        goto exit;
-
-    for( i = 0; i < dlen; i += 20 )
-    {
-        ret = mbedtls_md_hmac_reset ( &md_ctx );
-        if( ret != 0 )
-            goto exit;
-        ret = mbedtls_md_hmac_update( &md_ctx, tmp, 20 + nb );
-        if( ret != 0 )
-            goto exit;
-        ret = mbedtls_md_hmac_finish( &md_ctx, h_i );
-        if( ret != 0 )
-            goto exit;
-
-        ret = mbedtls_md_hmac_reset ( &md_ctx );
-        if( ret != 0 )
-            goto exit;
-        ret = mbedtls_md_hmac_update( &md_ctx, tmp, 20 );
-        if( ret != 0 )
-            goto exit;
-        ret = mbedtls_md_hmac_finish( &md_ctx, tmp );
-        if( ret != 0 )
-            goto exit;
-
-        k = ( i + 20 > dlen ) ? dlen % 20 : 20;
-
-        for( j = 0; j < k; j++ )
-            dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] );
-    }
-
-exit:
-    mbedtls_md_free( &md_ctx );
-
-    mbedtls_platform_zeroize( tmp, tmp_len );
-    mbedtls_platform_zeroize( h_i, sizeof( h_i ) );
-
-    mbedtls_free( tmp );
-    return( ret );
-}
-#endif /* MBEDTLS_SSL_PROTO_TLS1) || MBEDTLS_SSL_PROTO_TLS1_1 */
-
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
 
-static psa_status_t setup_psa_key_derivation( psa_key_derivation_operation_t* derivation,
-                                              psa_key_id_t key,
-                                              psa_algorithm_t alg,
-                                              const unsigned char* seed, size_t seed_length,
-                                              const unsigned char* label, size_t label_length,
-                                              size_t capacity )
-{
-    psa_status_t status;
-
-    status = psa_key_derivation_setup( derivation, alg );
-    if( status != PSA_SUCCESS )
-        return( status );
-
-    if( PSA_ALG_IS_TLS12_PRF( alg ) || PSA_ALG_IS_TLS12_PSK_TO_MS( alg ) )
-    {
-        status = psa_key_derivation_input_bytes( derivation,
-                                                 PSA_KEY_DERIVATION_INPUT_SEED,
-                                                 seed, seed_length );
-        if( status != PSA_SUCCESS )
-            return( status );
-
-        if( mbedtls_svc_key_id_is_null( key ) )
-        {
-            status = psa_key_derivation_input_bytes(
-                derivation, PSA_KEY_DERIVATION_INPUT_SECRET,
-                NULL, 0 );
-        }
-        else
-        {
-            status = psa_key_derivation_input_key(
-                derivation, PSA_KEY_DERIVATION_INPUT_SECRET, key );
-        }
-        if( status != PSA_SUCCESS )
-            return( status );
-
-        status = psa_key_derivation_input_bytes( derivation,
-                                                 PSA_KEY_DERIVATION_INPUT_LABEL,
-                                                 label, label_length );
-        if( status != PSA_SUCCESS )
-            return( status );
-    }
-    else
-    {
-        return( PSA_ERROR_NOT_SUPPORTED );
-    }
-
-    status = psa_key_derivation_set_capacity( derivation, capacity );
-    if( status != PSA_SUCCESS )
-        return( status );
-
-    return( PSA_SUCCESS );
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int tls_prf_generic( mbedtls_md_type_t md_type,
-                            const unsigned char *secret, size_t slen,
-                            const char *label,
-                            const unsigned char *random, size_t rlen,
-                            unsigned char *dstbuf, size_t dlen )
-{
-    psa_status_t status;
-    psa_algorithm_t alg;
-    psa_key_id_t master_key = MBEDTLS_SVC_KEY_ID_INIT;
-    psa_key_derivation_operation_t derivation =
-        PSA_KEY_DERIVATION_OPERATION_INIT;
-
-    if( md_type == MBEDTLS_MD_SHA384 )
-        alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384);
-    else
-        alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256);
-
-    /* Normally a "secret" should be long enough to be impossible to
-     * find by brute force, and in particular should not be empty. But
-     * this PRF is also used to derive an IV, in particular in EAP-TLS,
-     * and for this use case it makes sense to have a 0-length "secret".
-     * Since the key API doesn't allow importing a key of length 0,
-     * keep master_key=0, which setup_psa_key_derivation() understands
-     * to mean a 0-length "secret" input. */
-    if( slen != 0 )
-    {
-        psa_key_attributes_t key_attributes = psa_key_attributes_init();
-        psa_set_key_usage_flags( &key_attributes, PSA_KEY_USAGE_DERIVE );
-        psa_set_key_algorithm( &key_attributes, alg );
-        psa_set_key_type( &key_attributes, PSA_KEY_TYPE_DERIVE );
-
-        status = psa_import_key( &key_attributes, secret, slen, &master_key );
-        if( status != PSA_SUCCESS )
-            return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-    }
-
-    status = setup_psa_key_derivation( &derivation,
-                                       master_key, alg,
-                                       random, rlen,
-                                       (unsigned char const *) label,
-                                       (size_t) strlen( label ),
-                                       dlen );
-    if( status != PSA_SUCCESS )
-    {
-        psa_key_derivation_abort( &derivation );
-        psa_destroy_key( master_key );
-        return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-    }
-
-    status = psa_key_derivation_output_bytes( &derivation, dstbuf, dlen );
-    if( status != PSA_SUCCESS )
-    {
-        psa_key_derivation_abort( &derivation );
-        psa_destroy_key( master_key );
-        return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-    }
-
-    status = psa_key_derivation_abort( &derivation );
-    if( status != PSA_SUCCESS )
-    {
-        psa_destroy_key( master_key );
-        return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-    }
-
-    if( ! mbedtls_svc_key_id_is_null( master_key ) )
-        status = psa_destroy_key( master_key );
-    if( status != PSA_SUCCESS )
-        return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-
-    return( 0 );
-}
-
-#else /* MBEDTLS_USE_PSA_CRYPTO */
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int tls_prf_generic( mbedtls_md_type_t md_type,
-                            const unsigned char *secret, size_t slen,
-                            const char *label,
-                            const unsigned char *random, size_t rlen,
-                            unsigned char *dstbuf, size_t dlen )
-{
-    size_t nb;
-    size_t i, j, k, md_len;
-    unsigned char *tmp;
-    size_t tmp_len = 0;
-    unsigned char h_i[MBEDTLS_MD_MAX_SIZE];
-    const mbedtls_md_info_t *md_info;
-    mbedtls_md_context_t md_ctx;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    mbedtls_md_init( &md_ctx );
-
-    if( ( md_info = mbedtls_md_info_from_type( md_type ) ) == NULL )
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-
-    md_len = mbedtls_md_get_size( md_info );
-
-    tmp_len = md_len + strlen( label ) + rlen;
-    tmp = mbedtls_calloc( 1, tmp_len );
-    if( tmp == NULL )
-    {
-        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
-        goto exit;
-    }
-
-    nb = strlen( label );
-    memcpy( tmp + md_len, label, nb );
-    memcpy( tmp + md_len + nb, random, rlen );
-    nb += rlen;
-
-    /*
-     * Compute P_<hash>(secret, label + random)[0..dlen]
-     */
-    if ( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
-        goto exit;
-
-    ret = mbedtls_md_hmac_starts( &md_ctx, secret, slen );
-    if( ret != 0 )
-        goto exit;
-    ret = mbedtls_md_hmac_update( &md_ctx, tmp + md_len, nb );
-    if( ret != 0 )
-        goto exit;
-    ret = mbedtls_md_hmac_finish( &md_ctx, tmp );
-    if( ret != 0 )
-        goto exit;
-
-    for( i = 0; i < dlen; i += md_len )
-    {
-        ret = mbedtls_md_hmac_reset ( &md_ctx );
-        if( ret != 0 )
-            goto exit;
-        ret = mbedtls_md_hmac_update( &md_ctx, tmp, md_len + nb );
-        if( ret != 0 )
-            goto exit;
-        ret = mbedtls_md_hmac_finish( &md_ctx, h_i );
-        if( ret != 0 )
-            goto exit;
-
-        ret = mbedtls_md_hmac_reset ( &md_ctx );
-        if( ret != 0 )
-            goto exit;
-        ret = mbedtls_md_hmac_update( &md_ctx, tmp, md_len );
-        if( ret != 0 )
-            goto exit;
-        ret = mbedtls_md_hmac_finish( &md_ctx, tmp );
-        if( ret != 0 )
-            goto exit;
-
-        k = ( i + md_len > dlen ) ? dlen % md_len : md_len;
-
-        for( j = 0; j < k; j++ )
-            dstbuf[i + j]  = h_i[j];
-    }
-
-exit:
-    mbedtls_md_free( &md_ctx );
-
-    mbedtls_platform_zeroize( tmp, tmp_len );
-    mbedtls_platform_zeroize( h_i, sizeof( h_i ) );
-
-    mbedtls_free( tmp );
-
-    return( ret );
-}
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-#if defined(MBEDTLS_SHA256_C)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int tls_prf_sha256( const unsigned char *secret, size_t slen,
-                           const char *label,
-                           const unsigned char *random, size_t rlen,
-                           unsigned char *dstbuf, size_t dlen )
-{
-    return( tls_prf_generic( MBEDTLS_MD_SHA256, secret, slen,
-                             label, random, rlen, dstbuf, dlen ) );
-}
-#endif /* MBEDTLS_SHA256_C */
-
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int tls_prf_sha384( const unsigned char *secret, size_t slen,
-                           const char *label,
-                           const unsigned char *random, size_t rlen,
-                           unsigned char *dstbuf, size_t dlen )
-{
-    return( tls_prf_generic( MBEDTLS_MD_SHA384, secret, slen,
-                             label, random, rlen, dstbuf, dlen ) );
-}
-#endif /* MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384 */
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-
-static void ssl_update_checksum_start( mbedtls_ssl_context *, const unsigned char *, size_t );
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_1)
-static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *, const unsigned char *, size_t );
-#endif
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-static void ssl_calc_verify_ssl( const mbedtls_ssl_context *, unsigned char *, size_t * );
-static void ssl_calc_finished_ssl( mbedtls_ssl_context *, unsigned char *, int );
-#endif
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
-static void ssl_calc_verify_tls( const mbedtls_ssl_context *, unsigned char*, size_t * );
-static void ssl_calc_finished_tls( mbedtls_ssl_context *, unsigned char *, int );
-#endif
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_SHA256_C)
-static void ssl_update_checksum_sha256( mbedtls_ssl_context *, const unsigned char *, size_t );
-static void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *,unsigned char*, size_t * );
-static void ssl_calc_finished_tls_sha256( mbedtls_ssl_context *,unsigned char *, int );
-#endif
-
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
-static void ssl_update_checksum_sha384( mbedtls_ssl_context *, const unsigned char *, size_t );
-static void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *, unsigned char*, size_t * );
-static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *, int );
-#endif
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) && \
-    defined(MBEDTLS_USE_PSA_CRYPTO)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl )
-{
-    if( ssl->conf->f_psk != NULL )
-    {
-        /* If we've used a callback to select the PSK,
-         * the static configuration is irrelevant. */
-        if( ! mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) )
-            return( 1 );
-
-        return( 0 );
-    }
-
-    if( ! mbedtls_svc_key_id_is_null( ssl->conf->psk_opaque ) )
-        return( 1 );
-
-    return( 0 );
-}
-#endif /* MBEDTLS_USE_PSA_CRYPTO &&
-          MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
-
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
-static mbedtls_tls_prf_types tls_prf_get_type( mbedtls_ssl_tls_prf_cb *tls_prf )
-{
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-    if( tls_prf == ssl3_prf )
-    {
-        return( MBEDTLS_SSL_TLS_PRF_SSL3 );
-    }
-    else
-#endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
-    if( tls_prf == tls1_prf )
-    {
-        return( MBEDTLS_SSL_TLS_PRF_TLS1 );
-    }
-    else
-#endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
-    if( tls_prf == tls_prf_sha384 )
-    {
-        return( MBEDTLS_SSL_TLS_PRF_SHA384 );
-    }
-    else
-#endif
-#if defined(MBEDTLS_SHA256_C)
-    if( tls_prf == tls_prf_sha256 )
-    {
-        return( MBEDTLS_SSL_TLS_PRF_SHA256 );
-    }
-    else
-#endif
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-    return( MBEDTLS_SSL_TLS_PRF_NONE );
-}
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
-
-int  mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf,
-                          const unsigned char *secret, size_t slen,
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+typedef int (*tls_prf_fn)(const unsigned char *secret, size_t slen,
                           const char *label,
                           const unsigned char *random, size_t rlen,
-                          unsigned char *dstbuf, size_t dlen )
-{
-    mbedtls_ssl_tls_prf_cb *tls_prf = NULL;
+                          unsigned char *dstbuf, size_t dlen);
 
-    switch( prf )
-    {
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-        case MBEDTLS_SSL_TLS_PRF_SSL3:
-            tls_prf = ssl3_prf;
-        break;
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
-        case MBEDTLS_SSL_TLS_PRF_TLS1:
-            tls_prf = tls1_prf;
-        break;
-#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */
+static tls_prf_fn ssl_tls12prf_from_cs(int ciphersuite_id);
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
-        case MBEDTLS_SSL_TLS_PRF_SHA384:
-            tls_prf = tls_prf_sha384;
-        break;
-#endif /* MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384 */
-#if defined(MBEDTLS_SHA256_C)
-        case MBEDTLS_SSL_TLS_PRF_SHA256:
-            tls_prf = tls_prf_sha256;
-        break;
-#endif /* MBEDTLS_SHA256_C */
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-    default:
-        return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
-    }
-
-    return( tls_prf( secret, slen, label, random, rlen, dstbuf, dlen ) );
-}
+#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
 
 /* Type for the TLS PRF */
 typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *,
                           const unsigned char *, size_t,
                           unsigned char *, size_t);
 
-/*
- * Populate a transform structure with session keys and all the other
- * necessary information.
- *
- * Parameters:
- * - [in/out]: transform: structure to populate
- *      [in] must be just initialised with mbedtls_ssl_transform_init()
- *      [out] fully populated, ready for use by mbedtls_ssl_{en,de}crypt_buf()
- * - [in] ciphersuite
- * - [in] master
- * - [in] encrypt_then_mac
- * - [in] trunc_hmac
- * - [in] compression
- * - [in] tls_prf: pointer to PRF to use for key derivation
- * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random
- * - [in] minor_ver: SSL/TLS minor version
- * - [in] endpoint: client or server
- * - [in] ssl: optionally used for:
- *        - MBEDTLS_SSL_HW_RECORD_ACCEL: whole context (non-const)
- *        - MBEDTLS_SSL_EXPORT_KEYS: ssl->conf->{f,p}_export_keys
- *        - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg
- */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_populate_transform( mbedtls_ssl_transform *transform,
-                                   int ciphersuite,
-                                   const unsigned char master[48],
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-                                   int encrypt_then_mac,
-#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-                                   int trunc_hmac,
-#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
-#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-                                   int compression,
-#endif
-                                   ssl_tls_prf_t tls_prf,
-                                   const unsigned char randbytes[64],
-                                   int minor_ver,
-                                   unsigned endpoint,
-#if !defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
-                                   const
-#endif
-                                   mbedtls_ssl_context *ssl )
-{
-    int ret = 0;
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    int psa_fallthrough;
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-    unsigned char keyblk[256];
-    unsigned char *key1;
-    unsigned char *key2;
-    unsigned char *mac_enc;
-    unsigned char *mac_dec;
-    size_t mac_key_len = 0;
-    size_t iv_copy_len;
-    unsigned keylen;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
-    const mbedtls_cipher_info_t *cipher_info;
-    const mbedtls_md_info_t *md_info;
+static int ssl_tls12_populate_transform(mbedtls_ssl_transform *transform,
+                                        int ciphersuite,
+                                        const unsigned char master[48],
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+                                        int encrypt_then_mac,
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
+                                        ssl_tls_prf_t tls_prf,
+                                        const unsigned char randbytes[64],
+                                        mbedtls_ssl_protocol_version tls_version,
+                                        unsigned endpoint,
+                                        const mbedtls_ssl_context *ssl);
 
-#if !defined(MBEDTLS_SSL_HW_RECORD_ACCEL) && \
-    !defined(MBEDTLS_SSL_EXPORT_KEYS) && \
-    !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
-    !defined(MBEDTLS_DEBUG_C)
-    ssl = NULL; /* make sure we don't use it except for those cases */
-    (void) ssl;
-#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int tls_prf_sha256(const unsigned char *secret, size_t slen,
+                          const char *label,
+                          const unsigned char *random, size_t rlen,
+                          unsigned char *dstbuf, size_t dlen);
+static int ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *, unsigned char *, size_t *);
+static int ssl_calc_finished_tls_sha256(mbedtls_ssl_context *, unsigned char *, int);
 
-    /*
-     * Some data just needs copying into the structure
-     */
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \
-    defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
-    transform->encrypt_then_mac = encrypt_then_mac;
-#endif
-    transform->minor_ver = minor_ver;
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
 
-#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
-    memcpy( transform->randbytes, randbytes, sizeof( transform->randbytes ) );
-#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int tls_prf_sha384(const unsigned char *secret, size_t slen,
+                          const char *label,
+                          const unsigned char *random, size_t rlen,
+                          unsigned char *dstbuf, size_t dlen);
 
-    /*
-     * Get various info structures
-     */
-    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite );
-    if( ciphersuite_info == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %d not found",
-                                    ciphersuite ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-    }
+static int ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *, unsigned char *, size_t *);
+static int ssl_calc_finished_tls_sha384(mbedtls_ssl_context *, unsigned char *, int);
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
 
-    cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher );
-    if( cipher_info == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %u not found",
-                                    ciphersuite_info->cipher ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-    }
+static size_t ssl_tls12_session_save(const mbedtls_ssl_session *session,
+                                     unsigned char *buf,
+                                     size_t buf_len);
 
-    md_info = mbedtls_md_info_from_type( ciphersuite_info->mac );
-    if( md_info == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "mbedtls_md info for %u not found",
-                            (unsigned) ciphersuite_info->mac ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-    }
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    /* Copy own and peer's CID if the use of the CID
-     * extension has been negotiated. */
-    if( ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_ENABLED )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "Copy CIDs into SSL transform" ) );
-
-        transform->in_cid_len = ssl->own_cid_len;
-        memcpy( transform->in_cid, ssl->own_cid, ssl->own_cid_len );
-        MBEDTLS_SSL_DEBUG_BUF( 3, "Incoming CID", transform->in_cid,
-                               transform->in_cid_len );
-
-        transform->out_cid_len = ssl->handshake->peer_cid_len;
-        memcpy( transform->out_cid, ssl->handshake->peer_cid,
-                ssl->handshake->peer_cid_len );
-        MBEDTLS_SSL_DEBUG_BUF( 3, "Outgoing CID", transform->out_cid,
-                               transform->out_cid_len );
-    }
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
-    /*
-     * Compute key block using the PRF
-     */
-    ret = tls_prf( master, 48, "key expansion", randbytes, 64, keyblk, 256 );
-    if( ret != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret );
-        return( ret );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite = %s",
-                           mbedtls_ssl_get_ciphersuite_name( ciphersuite ) ) );
-    MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", master, 48 );
-    MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", randbytes, 64 );
-    MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 );
-
-    /*
-     * Determine the appropriate key, IV and MAC length.
-     */
-
-    keylen = cipher_info->key_bitlen / 8;
-
-#if defined(MBEDTLS_GCM_C) ||                           \
-    defined(MBEDTLS_CCM_C) ||                           \
-    defined(MBEDTLS_CHACHAPOLY_C)
-    if( cipher_info->mode == MBEDTLS_MODE_GCM ||
-        cipher_info->mode == MBEDTLS_MODE_CCM ||
-        cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY )
-    {
-        size_t explicit_ivlen;
-
-        transform->maclen = 0;
-        mac_key_len = 0;
-        transform->taglen =
-            ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;
-
-        /* All modes haves 96-bit IVs, but the length of the static parts vary
-         * with mode and version:
-         * - For GCM and CCM in TLS 1.2, there's a static IV of 4 Bytes
-         *   (to be concatenated with a dynamically chosen IV of 8 Bytes)
-         * - For ChaChaPoly in TLS 1.2, and all modes in TLS 1.3, there's
-         *   a static IV of 12 Bytes (to be XOR'ed with the 8 Byte record
-         *   sequence number).
-         */
-        transform->ivlen = 12;
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
-        if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 )
-        {
-            transform->fixed_ivlen = 12;
-        }
-        else
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
-        {
-            if( cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY )
-                transform->fixed_ivlen = 12;
-            else
-                transform->fixed_ivlen = 4;
-        }
-
-        /* Minimum length of encrypted record */
-        explicit_ivlen = transform->ivlen - transform->fixed_ivlen;
-        transform->minlen = explicit_ivlen + transform->taglen;
-    }
-    else
-#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
-    if( cipher_info->mode == MBEDTLS_MODE_STREAM ||
-        cipher_info->mode == MBEDTLS_MODE_CBC )
-    {
-        /* Initialize HMAC contexts */
-        if( ( ret = mbedtls_md_setup( &transform->md_ctx_enc, md_info, 1 ) ) != 0 ||
-            ( ret = mbedtls_md_setup( &transform->md_ctx_dec, md_info, 1 ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret );
-            goto end;
-        }
-
-        /* Get MAC length */
-        mac_key_len = mbedtls_md_get_size( md_info );
-        transform->maclen = mac_key_len;
-
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-        /*
-         * If HMAC is to be truncated, we shall keep the leftmost bytes,
-         * (rfc 6066 page 13 or rfc 2104 section 4),
-         * so we only need to adjust the length here.
-         */
-        if( trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED )
-        {
-            transform->maclen = MBEDTLS_SSL_TRUNCATED_HMAC_LEN;
-
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT)
-            /* Fall back to old, non-compliant version of the truncated
-             * HMAC implementation which also truncates the key
-             * (Mbed TLS versions from 1.3 to 2.6.0) */
-            mac_key_len = transform->maclen;
-#endif
-        }
-#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
-
-        /* IV length */
-        transform->ivlen = cipher_info->iv_size;
-
-        /* Minimum length */
-        if( cipher_info->mode == MBEDTLS_MODE_STREAM )
-            transform->minlen = transform->maclen;
-        else
-        {
-            /*
-             * GenericBlockCipher:
-             * 1. if EtM is in use: one block plus MAC
-             *    otherwise: * first multiple of blocklen greater than maclen
-             * 2. IV except for SSL3 and TLS 1.0
-             */
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-            if( encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED )
-            {
-                transform->minlen = transform->maclen
-                                  + cipher_info->block_size;
-            }
-            else
-#endif
-            {
-                transform->minlen = transform->maclen
-                                  + cipher_info->block_size
-                                  - transform->maclen % cipher_info->block_size;
-            }
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1)
-            if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ||
-                minor_ver == MBEDTLS_SSL_MINOR_VERSION_1 )
-                ; /* No need to adjust minlen */
-            else
-#endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
-            if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_2 ||
-                minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
-            {
-                transform->minlen += transform->ivlen;
-            }
-            else
-#endif
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-                ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-                goto end;
-            }
-        }
-    }
-    else
-#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "keylen: %u, minlen: %u, ivlen: %u, maclen: %u",
-                                (unsigned) keylen,
-                                (unsigned) transform->minlen,
-                                (unsigned) transform->ivlen,
-                                (unsigned) transform->maclen ) );
-
-    /*
-     * Finally setup the cipher contexts, IVs and MAC secrets.
-     */
-#if defined(MBEDTLS_SSL_CLI_C)
-    if( endpoint == MBEDTLS_SSL_IS_CLIENT )
-    {
-        key1 = keyblk + mac_key_len * 2;
-        key2 = keyblk + mac_key_len * 2 + keylen;
-
-        mac_enc = keyblk;
-        mac_dec = keyblk + mac_key_len;
-
-        /*
-         * This is not used in TLS v1.1.
-         */
-        iv_copy_len = ( transform->fixed_ivlen ) ?
-                            transform->fixed_ivlen : transform->ivlen;
-        memcpy( transform->iv_enc, key2 + keylen,  iv_copy_len );
-        memcpy( transform->iv_dec, key2 + keylen + iv_copy_len,
-                iv_copy_len );
-    }
-    else
-#endif /* MBEDTLS_SSL_CLI_C */
-#if defined(MBEDTLS_SSL_SRV_C)
-    if( endpoint == MBEDTLS_SSL_IS_SERVER )
-    {
-        key1 = keyblk + mac_key_len * 2 + keylen;
-        key2 = keyblk + mac_key_len * 2;
-
-        mac_enc = keyblk + mac_key_len;
-        mac_dec = keyblk;
-
-        /*
-         * This is not used in TLS v1.1.
-         */
-        iv_copy_len = ( transform->fixed_ivlen ) ?
-                            transform->fixed_ivlen : transform->ivlen;
-        memcpy( transform->iv_dec, key1 + keylen,  iv_copy_len );
-        memcpy( transform->iv_enc, key1 + keylen + iv_copy_len,
-                iv_copy_len );
-    }
-    else
-#endif /* MBEDTLS_SSL_SRV_C */
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-        goto end;
-    }
-
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-    if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
-    {
-        if( mac_key_len > sizeof( transform->mac_enc ) )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-            ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-            goto end;
-        }
-
-        memcpy( transform->mac_enc, mac_enc, mac_key_len );
-        memcpy( transform->mac_dec, mac_dec, mac_key_len );
-    }
-    else
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    if( minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 )
-    {
-        /* For HMAC-based ciphersuites, initialize the HMAC transforms.
-           For AEAD-based ciphersuites, there is nothing to do here. */
-        if( mac_key_len != 0 )
-        {
-            ret = mbedtls_md_hmac_starts( &transform->md_ctx_enc,
-                                          mac_enc, mac_key_len );
-            if( ret != 0 )
-                goto end;
-            ret = mbedtls_md_hmac_starts( &transform->md_ctx_dec,
-                                          mac_dec, mac_key_len );
-            if( ret != 0 )
-                goto end;
-        }
-    }
-    else
-#endif
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-        goto end;
-    }
-#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
-
-#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
-    if( mbedtls_ssl_hw_record_init != NULL )
-    {
-        ret = 0;
-
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_init()" ) );
-
-        if( ( ret = mbedtls_ssl_hw_record_init( ssl, key1, key2, keylen,
-                                        transform->iv_enc, transform->iv_dec,
-                                        iv_copy_len,
-                                        mac_enc, mac_dec,
-                                        mac_key_len ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_init", ret );
-            ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
-            goto end;
-        }
-    }
-#else
-    ((void) mac_dec);
-    ((void) mac_enc);
-#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
-
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
-    if( ssl->conf->f_export_keys != NULL )
-    {
-        ssl->conf->f_export_keys( ssl->conf->p_export_keys,
-                                  master, keyblk,
-                                  mac_key_len, keylen,
-                                  iv_copy_len );
-    }
-
-    if( ssl->conf->f_export_keys_ext != NULL )
-    {
-        ssl->conf->f_export_keys_ext( ssl->conf->p_export_keys,
-                                      master, keyblk,
-                                      mac_key_len, keylen,
-                                      iv_copy_len,
-                                      randbytes + 32,
-                                      randbytes,
-                                      tls_prf_get_type( tls_prf ) );
-    }
-#endif
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-
-    /* Only use PSA-based ciphers for TLS-1.2.
-     * That's relevant at least for TLS-1.0, where
-     * we assume that mbedtls_cipher_crypt() updates
-     * the structure field for the IV, which the PSA-based
-     * implementation currently doesn't. */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
-    {
-        ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_enc,
-                                        cipher_info, transform->taglen );
-        if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret );
-            goto end;
-        }
-
-        if( ret == 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based encryption cipher context" ) );
-            psa_fallthrough = 0;
-        }
-        else
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record encryption - fall through to default setup." ) );
-            psa_fallthrough = 1;
-        }
-    }
-    else
-        psa_fallthrough = 1;
-#else
-    psa_fallthrough = 1;
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls12_session_load(mbedtls_ssl_session *session,
+                                  const unsigned char *buf,
+                                  size_t len);
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
-    if( psa_fallthrough == 1 )
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-    if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc,
-                                 cipher_info ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret );
-        goto end;
-    }
+static int ssl_update_checksum_start(mbedtls_ssl_context *, const unsigned char *, size_t);
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    /* Only use PSA-based ciphers for TLS-1.2.
-     * That's relevant at least for TLS-1.0, where
-     * we assume that mbedtls_cipher_crypt() updates
-     * the structure field for the IV, which the PSA-based
-     * implementation currently doesn't. */
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+static int ssl_update_checksum_sha256(mbedtls_ssl_context *, const unsigned char *, size_t);
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+static int ssl_update_checksum_sha384(mbedtls_ssl_context *, const unsigned char *, size_t);
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+
+int  mbedtls_ssl_tls_prf(const mbedtls_tls_prf_types prf,
+                         const unsigned char *secret, size_t slen,
+                         const char *label,
+                         const unsigned char *random, size_t rlen,
+                         unsigned char *dstbuf, size_t dlen)
+{
+    mbedtls_ssl_tls_prf_cb *tls_prf = NULL;
+
+    switch (prf) {
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
-    {
-        ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_dec,
-                                        cipher_info, transform->taglen );
-        if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret );
-            goto end;
-        }
-
-        if( ret == 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based decryption cipher context" ) );
-            psa_fallthrough = 0;
-        }
-        else
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record decryption - fall through to default setup." ) );
-            psa_fallthrough = 1;
-        }
-    }
-    else
-        psa_fallthrough = 1;
-#else
-    psa_fallthrough = 1;
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_SSL_TLS_PRF_SHA384:
+            tls_prf = tls_prf_sha384;
+            break;
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_SSL_TLS_PRF_SHA256:
+            tls_prf = tls_prf_sha256;
+            break;
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-
-    if( psa_fallthrough == 1 )
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-    if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec,
-                                 cipher_info ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret );
-        goto end;
+        default:
+            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
     }
 
-    if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_enc, key1,
-                               cipher_info->key_bitlen,
-                               MBEDTLS_ENCRYPT ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret );
-        goto end;
-    }
-
-    if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_dec, key2,
-                               cipher_info->key_bitlen,
-                               MBEDTLS_DECRYPT ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret );
-        goto end;
-    }
-
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-    if( cipher_info->mode == MBEDTLS_MODE_CBC )
-    {
-        if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_enc,
-                                             MBEDTLS_PADDING_NONE ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret );
-            goto end;
-        }
-
-        if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_dec,
-                                             MBEDTLS_PADDING_NONE ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret );
-            goto end;
-        }
-    }
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-
-
-    /* Initialize Zlib contexts */
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-    if( compression == MBEDTLS_SSL_COMPRESS_DEFLATE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "Initializing zlib states" ) );
-
-        memset( &transform->ctx_deflate, 0, sizeof( transform->ctx_deflate ) );
-        memset( &transform->ctx_inflate, 0, sizeof( transform->ctx_inflate ) );
-
-        if( deflateInit( &transform->ctx_deflate,
-                         Z_DEFAULT_COMPRESSION )   != Z_OK ||
-            inflateInit( &transform->ctx_inflate ) != Z_OK )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) );
-            ret = MBEDTLS_ERR_SSL_COMPRESSION_FAILED;
-            goto end;
-        }
-    }
-#endif /* MBEDTLS_ZLIB_SUPPORT */
-
-end:
-    mbedtls_platform_zeroize( keyblk, sizeof( keyblk ) );
-    return( ret );
+    return tls_prf(secret, slen, label, random, rlen, dstbuf, dlen);
 }
 
-/*
- * Set appropriate PRF function and other SSL / TLS 1.0/1.1 / TLS1.2 functions
- *
- * Inputs:
- * - SSL/TLS minor version
- * - hash associated with the ciphersuite (only used by TLS 1.2)
- *
- * Outputs:
- * - the tls_prf, calc_verify and calc_finished members of handshake structure
- */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake,
-                                   int minor_ver,
-                                   mbedtls_md_type_t hash )
-{
-#if !defined(MBEDTLS_SSL_PROTO_TLS1_2) ||       \
-    !( defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) )
-    (void) hash;
-#endif
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-    if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
-    {
-        handshake->tls_prf = ssl3_prf;
-        handshake->calc_verify = ssl_calc_verify_ssl;
-        handshake->calc_finished = ssl_calc_finished_ssl;
-    }
-    else
-#endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
-    if( minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 )
-    {
-        handshake->tls_prf = tls1_prf;
-        handshake->calc_verify = ssl_calc_verify_tls;
-        handshake->calc_finished = ssl_calc_finished_tls;
-    }
-    else
-#endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
-    if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 &&
-        hash == MBEDTLS_MD_SHA384 )
-    {
-        handshake->tls_prf = tls_prf_sha384;
-        handshake->calc_verify = ssl_calc_verify_tls_sha384;
-        handshake->calc_finished = ssl_calc_finished_tls_sha384;
-    }
-    else
-#endif
-#if defined(MBEDTLS_SHA256_C)
-    if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
-    {
-        handshake->tls_prf = tls_prf_sha256;
-        handshake->calc_verify = ssl_calc_verify_tls_sha256;
-        handshake->calc_finished = ssl_calc_finished_tls_sha256;
-    }
-    else
-#endif
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-    {
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-
-    return( 0 );
-}
-
-/*
- * Compute master secret if needed
- *
- * Parameters:
- * [in/out] handshake
- *          [in] resume, premaster, extended_ms, calc_verify, tls_prf
- *               (PSA-PSK) ciphersuite_info, psk_opaque
- *          [out] premaster (cleared)
- * [out] master
- * [in] ssl: optionally used for debugging, EMS and PSA-PSK
- *      debug: conf->f_dbg, conf->p_dbg
- *      EMS: passed to calc_verify (debug + (SSL3) session_negotiate)
- *      PSA-PSA: minor_ver, conf
- */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake,
-                               unsigned char *master,
-                               const mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    /* cf. RFC 5246, Section 8.1:
-     * "The master secret is always exactly 48 bytes in length." */
-    size_t const master_secret_len = 48;
-
-#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-    unsigned char session_hash[48];
-#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
-
-    /* The label for the KDF used for key expansion.
-     * This is either "master secret" or "extended master secret"
-     * depending on whether the Extended Master Secret extension
-     * is used. */
-    char const *lbl = "master secret";
-
-    /* The salt for the KDF used for key expansion.
-     * - If the Extended Master Secret extension is not used,
-     *   this is ClientHello.Random + ServerHello.Random
-     *   (see Sect. 8.1 in RFC 5246).
-     * - If the Extended Master Secret extension is used,
-     *   this is the transcript of the handshake so far.
-     *   (see Sect. 4 in RFC 7627). */
-    unsigned char const *salt = handshake->randbytes;
-    size_t salt_len = 64;
-
-#if !defined(MBEDTLS_DEBUG_C) &&                    \
-    !defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \
-    !(defined(MBEDTLS_USE_PSA_CRYPTO) &&            \
-      defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED))
-    ssl = NULL; /* make sure we don't use it except for those cases */
-    (void) ssl;
-#endif
-
-    if( handshake->resume != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) );
-        return( 0 );
-    }
-
-#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-    if( handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED )
-    {
-        lbl  = "extended master secret";
-        salt = session_hash;
-        handshake->calc_verify( ssl, session_hash, &salt_len );
-
-        MBEDTLS_SSL_DEBUG_BUF( 3, "session hash for extended master secret",
-                                  session_hash, salt_len );
-    }
-#endif /* MBEDTLS_SSL_EXTENDED_MS_ENABLED */
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO) &&          \
-    defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
-    if( handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK &&
-        ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 &&
-        ssl_use_opaque_psk( ssl ) == 1 )
-    {
-        /* Perform PSK-to-MS expansion in a single step. */
-        psa_status_t status;
-        psa_algorithm_t alg;
-        psa_key_id_t psk;
-        psa_key_derivation_operation_t derivation =
-            PSA_KEY_DERIVATION_OPERATION_INIT;
-        mbedtls_md_type_t hash_alg = handshake->ciphersuite_info->mac;
-
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "perform PSA-based PSK-to-MS expansion" ) );
-
-        psk = mbedtls_ssl_get_opaque_psk( ssl );
-
-        if( hash_alg == MBEDTLS_MD_SHA384 )
-            alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384);
-        else
-            alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256);
-
-        status = setup_psa_key_derivation( &derivation, psk, alg,
-                                           salt, salt_len,
-                                           (unsigned char const *) lbl,
-                                           (size_t) strlen( lbl ),
-                                           master_secret_len );
-        if( status != PSA_SUCCESS )
-        {
-            psa_key_derivation_abort( &derivation );
-            return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-        }
-
-        status = psa_key_derivation_output_bytes( &derivation,
-                                                  master,
-                                                  master_secret_len );
-        if( status != PSA_SUCCESS )
-        {
-            psa_key_derivation_abort( &derivation );
-            return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-        }
-
-        status = psa_key_derivation_abort( &derivation );
-        if( status != PSA_SUCCESS )
-            return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-    }
-    else
-#endif
-    {
-        ret = handshake->tls_prf( handshake->premaster, handshake->pmslen,
-                                  lbl, salt, salt_len,
-                                  master,
-                                  master_secret_len );
-        if( ret != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret );
-            return( ret );
-        }
-
-        MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret",
-                               handshake->premaster,
-                               handshake->pmslen );
-
-        mbedtls_platform_zeroize( handshake->premaster,
-                                  sizeof(handshake->premaster) );
-    }
-
-    return( 0 );
-}
-
-int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> derive keys" ) );
-
-    /* Set PRF, calc_verify and calc_finished function pointers */
-    ret = ssl_set_handshake_prfs( ssl->handshake,
-                                  ssl->minor_ver,
-                                  ciphersuite_info->mac );
-    if( ret != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_set_handshake_prfs", ret );
-        return( ret );
-    }
-
-    /* Compute master secret if needed */
-    ret = ssl_compute_master( ssl->handshake,
-                              ssl->session_negotiate->master,
-                              ssl );
-    if( ret != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compute_master", ret );
-        return( ret );
-    }
-
-    /* Swap the client and server random values:
-     * - MS derivation wanted client+server (RFC 5246 8.1)
-     * - key derivation wants server+client (RFC 5246 6.3) */
-    {
-        unsigned char tmp[64];
-        memcpy( tmp, ssl->handshake->randbytes, 64 );
-        memcpy( ssl->handshake->randbytes, tmp + 32, 32 );
-        memcpy( ssl->handshake->randbytes + 32, tmp, 32 );
-        mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
-    }
-
-    /* Populate transform structure */
-    ret = ssl_populate_transform( ssl->transform_negotiate,
-                                  ssl->session_negotiate->ciphersuite,
-                                  ssl->session_negotiate->master,
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-                                  ssl->session_negotiate->encrypt_then_mac,
-#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-                                  ssl->session_negotiate->trunc_hmac,
-#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
-#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-                                  ssl->session_negotiate->compression,
-#endif
-                                  ssl->handshake->tls_prf,
-                                  ssl->handshake->randbytes,
-                                  ssl->minor_ver,
-                                  ssl->conf->endpoint,
-                                  ssl );
-    if( ret != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_populate_transform", ret );
-        return( ret );
-    }
-
-    /* We no longer need Server/ClientHello.random values */
-    mbedtls_platform_zeroize( ssl->handshake->randbytes,
-                      sizeof( ssl->handshake->randbytes ) );
-
-    /* Allocate compression buffer */
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-    if( ssl->session_negotiate->compression == MBEDTLS_SSL_COMPRESS_DEFLATE &&
-        ssl->compress_buf == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) );
-        ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_COMPRESS_BUFFER_LEN );
-        if( ssl->compress_buf == NULL )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
-                                        MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) );
-            return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
-        }
-    }
-#endif
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= derive keys" ) );
-
-    return( 0 );
-}
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-void ssl_calc_verify_ssl( const mbedtls_ssl_context *ssl,
-                          unsigned char *hash,
-                          size_t *hlen )
-{
-    mbedtls_md5_context md5;
-    mbedtls_sha1_context sha1;
-    unsigned char pad_1[48];
-    unsigned char pad_2[48];
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) );
-
-    mbedtls_md5_init( &md5 );
-    mbedtls_sha1_init( &sha1 );
-
-    mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 );
-    mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 );
-
-    memset( pad_1, 0x36, 48 );
-    memset( pad_2, 0x5C, 48 );
-
-    mbedtls_md5_update_ret( &md5, ssl->session_negotiate->master, 48 );
-    mbedtls_md5_update_ret( &md5, pad_1, 48 );
-    mbedtls_md5_finish_ret( &md5, hash );
-
-    mbedtls_md5_starts_ret( &md5 );
-    mbedtls_md5_update_ret( &md5, ssl->session_negotiate->master, 48 );
-    mbedtls_md5_update_ret( &md5, pad_2, 48 );
-    mbedtls_md5_update_ret( &md5, hash,  16 );
-    mbedtls_md5_finish_ret( &md5, hash );
-
-    mbedtls_sha1_update_ret( &sha1, ssl->session_negotiate->master, 48 );
-    mbedtls_sha1_update_ret( &sha1, pad_1, 40 );
-    mbedtls_sha1_finish_ret( &sha1, hash + 16 );
-
-    mbedtls_sha1_starts_ret( &sha1 );
-    mbedtls_sha1_update_ret( &sha1, ssl->session_negotiate->master, 48 );
-    mbedtls_sha1_update_ret( &sha1, pad_2, 40 );
-    mbedtls_sha1_update_ret( &sha1, hash + 16, 20 );
-    mbedtls_sha1_finish_ret( &sha1, hash + 16 );
-
-    *hlen = 36;
-
-    MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen );
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
-
-    mbedtls_md5_free(  &md5  );
-    mbedtls_sha1_free( &sha1 );
-
-    return;
-}
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
-void ssl_calc_verify_tls( const mbedtls_ssl_context *ssl,
-                          unsigned char *hash,
-                          size_t *hlen )
-{
-    mbedtls_md5_context md5;
-    mbedtls_sha1_context sha1;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) );
-
-    mbedtls_md5_init( &md5 );
-    mbedtls_sha1_init( &sha1 );
-
-    mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 );
-    mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 );
-
-    mbedtls_md5_finish_ret( &md5,  hash );
-    mbedtls_sha1_finish_ret( &sha1, hash + 16 );
-
-    *hlen = 36;
-
-    MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen );
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
-
-    mbedtls_md5_free(  &md5  );
-    mbedtls_sha1_free( &sha1 );
-
-    return;
-}
-#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_SHA256_C)
-void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *ssl,
-                                 unsigned char *hash,
-                                 size_t *hlen )
-{
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    size_t hash_size;
-    psa_status_t status;
-    psa_hash_operation_t sha256_psa = psa_hash_operation_init();
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> PSA calc verify sha256" ) );
-    status = psa_hash_clone( &ssl->handshake->fin_sha256_psa, &sha256_psa );
-    if( status != PSA_SUCCESS )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) );
-        return;
-    }
-
-    status = psa_hash_finish( &sha256_psa, hash, 32, &hash_size );
-    if( status != PSA_SUCCESS )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) );
-        return;
-    }
-
-    *hlen = 32;
-    MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated verify result", hash, *hlen );
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= PSA calc verify" ) );
-#else
-    mbedtls_sha256_context sha256;
-
-    mbedtls_sha256_init( &sha256 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) );
-
-    mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 );
-    mbedtls_sha256_finish_ret( &sha256, hash );
-
-    *hlen = 32;
-
-    MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen );
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
-
-    mbedtls_sha256_free( &sha256 );
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-    return;
-}
-#endif /* MBEDTLS_SHA256_C */
-
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
-void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *ssl,
-                                 unsigned char *hash,
-                                 size_t *hlen )
-{
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    size_t hash_size;
-    psa_status_t status;
-    psa_hash_operation_t sha384_psa = psa_hash_operation_init();
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> PSA calc verify sha384" ) );
-    status = psa_hash_clone( &ssl->handshake->fin_sha384_psa, &sha384_psa );
-    if( status != PSA_SUCCESS )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) );
-        return;
-    }
-
-    status = psa_hash_finish( &sha384_psa, hash, 48, &hash_size );
-    if( status != PSA_SUCCESS )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) );
-        return;
-    }
-
-    *hlen = 48;
-    MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated verify result", hash, *hlen );
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= PSA calc verify" ) );
-#else
-    mbedtls_sha512_context sha512;
-
-    mbedtls_sha512_init( &sha512 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) );
-
-    mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 );
-    mbedtls_sha512_finish_ret( &sha512, hash );
-
-    *hlen = 48;
-
-    MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen );
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
-
-    mbedtls_sha512_free( &sha512 );
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-    return;
-}
-#endif /* MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384 */
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
-int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex )
-{
-    unsigned char *p = ssl->handshake->premaster;
-    unsigned char *end = p + sizeof( ssl->handshake->premaster );
-    const unsigned char *psk = NULL;
-    size_t psk_len = 0;
-
-    if( mbedtls_ssl_get_psk( ssl, &psk, &psk_len )
-            == MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED )
-    {
-        /*
-         * This should never happen because the existence of a PSK is always
-         * checked before calling this function
-         */
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-
-    /*
-     * PMS = struct {
-     *     opaque other_secret<0..2^16-1>;
-     *     opaque psk<0..2^16-1>;
-     * };
-     * with "other_secret" depending on the particular key exchange
-     */
-#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
-    if( key_ex == MBEDTLS_KEY_EXCHANGE_PSK )
-    {
-        if( end - p < 2 )
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-        MBEDTLS_PUT_UINT16_BE( psk_len, p, 0 );
-        p += 2;
-
-        if( end < p || (size_t)( end - p ) < psk_len )
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-        memset( p, 0, psk_len );
-        p += psk_len;
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
-    if( key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
-    {
-        /*
-         * other_secret already set by the ClientKeyExchange message,
-         * and is 48 bytes long
-         */
-        if( end - p < 2 )
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-        *p++ = 0;
-        *p++ = 48;
-        p += 48;
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
-    if( key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK )
-    {
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        size_t len;
-
-        /* Write length only when we know the actual value */
-        if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx,
-                                      p + 2, end - ( p + 2 ), &len,
-                                      ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret );
-            return( ret );
-        }
-        MBEDTLS_PUT_UINT16_BE( len, p, 0 );
-        p += 2 + len;
-
-        MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K  );
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
-    if( key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
-    {
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        size_t zlen;
-
-        if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen,
-                                       p + 2, end - ( p + 2 ),
-                                       ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret );
-            return( ret );
-        }
-
-        MBEDTLS_PUT_UINT16_BE( zlen, p, 0 );
-        p += 2 + zlen;
-
-        MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
-                                MBEDTLS_DEBUG_ECDH_Z );
-    }
-    else
-#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-
-    /* opaque psk<0..2^16-1>; */
-    if( end - p < 2 )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    MBEDTLS_PUT_UINT16_BE( psk_len, p, 0 );
-    p += 2;
-
-    if( end < p || (size_t)( end - p ) < psk_len )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    memcpy( p, psk, psk_len );
-    p += psk_len;
-
-    ssl->handshake->pmslen = p - ssl->handshake->premaster;
-
-    return( 0 );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
-
-#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_hello_request( mbedtls_ssl_context *ssl );
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-int mbedtls_ssl_resend_hello_request( mbedtls_ssl_context *ssl )
-{
-    /* If renegotiation is not enforced, retransmit until we would reach max
-     * timeout if we were using the usual handshake doubling scheme */
-    if( ssl->conf->renego_max_records < 0 )
-    {
-        uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1;
-        unsigned char doublings = 1;
-
-        while( ratio != 0 )
-        {
-            ++doublings;
-            ratio >>= 1;
-        }
-
-        if( ++ssl->renego_records_seen > doublings )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "no longer retransmitting hello request" ) );
-            return( 0 );
-        }
-    }
-
-    return( ssl_write_hello_request( ssl ) );
-}
-#endif
-#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
-
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
-static void ssl_clear_peer_cert( mbedtls_ssl_session *session )
+static void ssl_clear_peer_cert(mbedtls_ssl_session *session)
 {
 #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    if( session->peer_cert != NULL )
-    {
-        mbedtls_x509_crt_free( session->peer_cert );
-        mbedtls_free( session->peer_cert );
+    if (session->peer_cert != NULL) {
+        mbedtls_x509_crt_free(session->peer_cert);
+        mbedtls_free(session->peer_cert);
         session->peer_cert = NULL;
     }
 #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-    if( session->peer_cert_digest != NULL )
-    {
+    if (session->peer_cert_digest != NULL) {
         /* Zeroization is not necessary. */
-        mbedtls_free( session->peer_cert_digest );
+        mbedtls_free(session->peer_cert_digest);
         session->peer_cert_digest      = NULL;
         session->peer_cert_digest_type = MBEDTLS_MD_NONE;
         session->peer_cert_digest_len  = 0;
@@ -2174,1613 +510,492 @@
 }
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
-/*
- * Handshake functions
- */
-#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-/* No certificate support -> dummy functions */
-int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl )
+uint32_t mbedtls_ssl_get_extension_id(unsigned int extension_type)
 {
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
+    switch (extension_type) {
+        case MBEDTLS_TLS_EXT_SERVERNAME:
+            return MBEDTLS_SSL_EXT_ID_SERVERNAME;
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) );
+        case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH:
+            return MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH;
 
-    if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
-        ssl->state++;
-        return( 0 );
+        case MBEDTLS_TLS_EXT_STATUS_REQUEST:
+            return MBEDTLS_SSL_EXT_ID_STATUS_REQUEST;
+
+        case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS:
+            return MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS;
+
+        case MBEDTLS_TLS_EXT_SIG_ALG:
+            return MBEDTLS_SSL_EXT_ID_SIG_ALG;
+
+        case MBEDTLS_TLS_EXT_USE_SRTP:
+            return MBEDTLS_SSL_EXT_ID_USE_SRTP;
+
+        case MBEDTLS_TLS_EXT_HEARTBEAT:
+            return MBEDTLS_SSL_EXT_ID_HEARTBEAT;
+
+        case MBEDTLS_TLS_EXT_ALPN:
+            return MBEDTLS_SSL_EXT_ID_ALPN;
+
+        case MBEDTLS_TLS_EXT_SCT:
+            return MBEDTLS_SSL_EXT_ID_SCT;
+
+        case MBEDTLS_TLS_EXT_CLI_CERT_TYPE:
+            return MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE;
+
+        case MBEDTLS_TLS_EXT_SERV_CERT_TYPE:
+            return MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE;
+
+        case MBEDTLS_TLS_EXT_PADDING:
+            return MBEDTLS_SSL_EXT_ID_PADDING;
+
+        case MBEDTLS_TLS_EXT_PRE_SHARED_KEY:
+            return MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY;
+
+        case MBEDTLS_TLS_EXT_EARLY_DATA:
+            return MBEDTLS_SSL_EXT_ID_EARLY_DATA;
+
+        case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS:
+            return MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS;
+
+        case MBEDTLS_TLS_EXT_COOKIE:
+            return MBEDTLS_SSL_EXT_ID_COOKIE;
+
+        case MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES:
+            return MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES;
+
+        case MBEDTLS_TLS_EXT_CERT_AUTH:
+            return MBEDTLS_SSL_EXT_ID_CERT_AUTH;
+
+        case MBEDTLS_TLS_EXT_OID_FILTERS:
+            return MBEDTLS_SSL_EXT_ID_OID_FILTERS;
+
+        case MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH:
+            return MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH;
+
+        case MBEDTLS_TLS_EXT_SIG_ALG_CERT:
+            return MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT;
+
+        case MBEDTLS_TLS_EXT_KEY_SHARE:
+            return MBEDTLS_SSL_EXT_ID_KEY_SHARE;
+
+        case MBEDTLS_TLS_EXT_TRUNCATED_HMAC:
+            return MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC;
+
+        case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS:
+            return MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS;
+
+        case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC:
+            return MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC;
+
+        case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET:
+            return MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET;
+
+        case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT:
+            return MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT;
+
+        case MBEDTLS_TLS_EXT_SESSION_TICKET:
+            return MBEDTLS_SSL_EXT_ID_SESSION_TICKET;
+
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-    return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    return MBEDTLS_SSL_EXT_ID_UNRECOGNIZED;
 }
 
-int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
+uint32_t mbedtls_ssl_get_extension_mask(unsigned int extension_type)
 {
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
-
-    if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
-        ssl->state++;
-        return( 0 );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
-    return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    return 1 << mbedtls_ssl_get_extension_id(extension_type);
 }
 
-#else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
-/* Some certificate support -> implement write and parse */
-
-int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl )
-{
-    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-    size_t i, n;
-    const mbedtls_x509_crt *crt;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) );
-
-    if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
-        ssl->state++;
-        return( 0 );
-    }
-
-#if defined(MBEDTLS_SSL_CLI_C)
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
-    {
-        if( ssl->client_auth == 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
-            ssl->state++;
-            return( 0 );
-        }
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-        /*
-         * If using SSLv3 and got no cert, send an Alert message
-         * (otherwise an empty Certificate message will be sent).
-         */
-        if( mbedtls_ssl_own_cert( ssl )  == NULL &&
-            ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
-        {
-            ssl->out_msglen  = 2;
-            ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT;
-            ssl->out_msg[0]  = MBEDTLS_SSL_ALERT_LEVEL_WARNING;
-            ssl->out_msg[1]  = MBEDTLS_SSL_ALERT_MSG_NO_CERT;
-
-            MBEDTLS_SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) );
-            goto write_msg;
-        }
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-    }
-#endif /* MBEDTLS_SSL_CLI_C */
-#if defined(MBEDTLS_SSL_SRV_C)
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
-    {
-        if( mbedtls_ssl_own_cert( ssl ) == NULL )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) );
-            return( MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED );
-        }
-    }
-#endif
-
-    MBEDTLS_SSL_DEBUG_CRT( 3, "own certificate", mbedtls_ssl_own_cert( ssl ) );
-
-    /*
-     *     0  .  0    handshake type
-     *     1  .  3    handshake length
-     *     4  .  6    length of all certs
-     *     7  .  9    length of cert. 1
-     *    10  . n-1   peer certificate
-     *     n  . n+2   length of cert. 2
-     *    n+3 . ...   upper level cert, etc.
-     */
-    i = 7;
-    crt = mbedtls_ssl_own_cert( ssl );
-
-    while( crt != NULL )
-    {
-        n = crt->raw.len;
-        if( n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %" MBEDTLS_PRINTF_SIZET
-                                        " > %" MBEDTLS_PRINTF_SIZET,
-                           i + 3 + n, (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
-            return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE );
-        }
-
-        ssl->out_msg[i    ] = MBEDTLS_BYTE_2( n );
-        ssl->out_msg[i + 1] = MBEDTLS_BYTE_1( n );
-        ssl->out_msg[i + 2] = MBEDTLS_BYTE_0( n );
-
-        i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n );
-        i += n; crt = crt->next;
-    }
-
-    ssl->out_msg[4]  = MBEDTLS_BYTE_2( i - 7 );
-    ssl->out_msg[5]  = MBEDTLS_BYTE_1( i - 7 );
-    ssl->out_msg[6]  = MBEDTLS_BYTE_0( i - 7 );
-
-    ssl->out_msglen  = i;
-    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
-    ssl->out_msg[0]  = MBEDTLS_SSL_HS_CERTIFICATE;
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C)
-write_msg:
-#endif
-
-    ssl->state++;
-
-    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
-        return( ret );
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate" ) );
-
-    return( ret );
-}
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
-
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
-                                         unsigned char *crt_buf,
-                                         size_t crt_buf_len )
-{
-    mbedtls_x509_crt const * const peer_crt = ssl->session->peer_cert;
-
-    if( peer_crt == NULL )
-        return( -1 );
-
-    if( peer_crt->raw.len != crt_buf_len )
-        return( -1 );
-
-    return( memcmp( peer_crt->raw.p, crt_buf, peer_crt->raw.len ) );
-}
-#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
-                                         unsigned char *crt_buf,
-                                         size_t crt_buf_len )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char const * const peer_cert_digest =
-        ssl->session->peer_cert_digest;
-    mbedtls_md_type_t const peer_cert_digest_type =
-        ssl->session->peer_cert_digest_type;
-    mbedtls_md_info_t const * const digest_info =
-        mbedtls_md_info_from_type( peer_cert_digest_type );
-    unsigned char tmp_digest[MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN];
-    size_t digest_len;
-
-    if( peer_cert_digest == NULL || digest_info == NULL )
-        return( -1 );
-
-    digest_len = mbedtls_md_get_size( digest_info );
-    if( digest_len > MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN )
-        return( -1 );
-
-    ret = mbedtls_md( digest_info, crt_buf, crt_buf_len, tmp_digest );
-    if( ret != 0 )
-        return( -1 );
-
-    return( memcmp( tmp_digest, peer_cert_digest, digest_len ) );
-}
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
-
-/*
- * Once the certificate message is read, parse it into a cert chain and
- * perform basic checks, but leave actual verification to the caller
- */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl,
-                                        mbedtls_x509_crt *chain )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
-    int crt_cnt=0;
-#endif
-    size_t i, n;
-    uint8_t alert;
-
-    if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
-        return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
-    }
-
-    if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE ||
-        ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
-    }
-
-    i = mbedtls_ssl_hs_hdr_len( ssl );
-
-    /*
-     * Same message structure as in mbedtls_ssl_write_certificate()
-     */
-    n = ( ssl->in_msg[i+1] << 8 ) | ssl->in_msg[i+2];
-
-    if( ssl->in_msg[i] != 0 ||
-        ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
-    }
-
-    /* Make &ssl->in_msg[i] point to the beginning of the CRT chain. */
-    i += 3;
-
-    /* Iterate through and parse the CRTs in the provided chain. */
-    while( i < ssl->in_hslen )
-    {
-        /* Check that there's room for the next CRT's length fields. */
-        if ( i + 3 > ssl->in_hslen ) {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
-            mbedtls_ssl_send_alert_message( ssl,
-                              MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                              MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
-        }
-        /* In theory, the CRT can be up to 2**24 Bytes, but we don't support
-         * anything beyond 2**16 ~ 64K. */
-        if( ssl->in_msg[i] != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
-            mbedtls_ssl_send_alert_message( ssl,
-                            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                            MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
-        }
-
-        /* Read length of the next CRT in the chain. */
-        n = ( (unsigned int) ssl->in_msg[i + 1] << 8 )
-            | (unsigned int) ssl->in_msg[i + 2];
-        i += 3;
-
-        if( n < 128 || i + n > ssl->in_hslen )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
-            mbedtls_ssl_send_alert_message( ssl,
-                                 MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                 MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-            return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
-        }
-
-        /* Check if we're handling the first CRT in the chain. */
-#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
-        if( crt_cnt++ == 0 &&
-            ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
-            ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
-        {
-            /* During client-side renegotiation, check that the server's
-             * end-CRTs hasn't changed compared to the initial handshake,
-             * mitigating the triple handshake attack. On success, reuse
-             * the original end-CRT instead of parsing it again. */
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "Check that peer CRT hasn't changed during renegotiation" ) );
-            if( ssl_check_peer_crt_unchanged( ssl,
-                                              &ssl->in_msg[i],
-                                              n ) != 0 )
-            {
-                MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) );
-                mbedtls_ssl_send_alert_message( ssl,
-                                                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                                MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED );
-                return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
-            }
-
-            /* Now we can safely free the original chain. */
-            ssl_clear_peer_cert( ssl->session );
-        }
-#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
-
-        /* Parse the next certificate in the chain. */
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-        ret = mbedtls_x509_crt_parse_der( chain, ssl->in_msg + i, n );
-#else
-        /* If we don't need to store the CRT chain permanently, parse
-         * it in-place from the input buffer instead of making a copy. */
-        ret = mbedtls_x509_crt_parse_der_nocopy( chain, ssl->in_msg + i, n );
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-        switch( ret )
-        {
-            case 0: /*ok*/
-            case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND:
-                /* Ignore certificate with an unknown algorithm: maybe a
-                   prior certificate was already trusted. */
-                break;
-
-            case MBEDTLS_ERR_X509_ALLOC_FAILED:
-                alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR;
-                goto crt_parse_der_failed;
-
-            case MBEDTLS_ERR_X509_UNKNOWN_VERSION:
-                alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
-                goto crt_parse_der_failed;
-
-            default:
-                alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
-            crt_parse_der_failed:
-                mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert );
-                MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret );
-                return( ret );
-        }
-
-        i += n;
-    }
-
-    MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", chain );
-    return( 0 );
-}
-
-#if defined(MBEDTLS_SSL_SRV_C)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_srv_check_client_no_crt_notification( mbedtls_ssl_context *ssl )
-{
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
-        return( -1 );
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-    /*
-     * Check if the client sent an empty certificate
-     */
-    if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
-    {
-        if( ssl->in_msglen  == 2                        &&
-            ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT            &&
-            ssl->in_msg[0]  == MBEDTLS_SSL_ALERT_LEVEL_WARNING  &&
-            ssl->in_msg[1]  == MBEDTLS_SSL_ALERT_MSG_NO_CERT )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) );
-            return( 0 );
-        }
-
-        return( -1 );
-    }
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    if( ssl->in_hslen   == 3 + mbedtls_ssl_hs_hdr_len( ssl ) &&
-        ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE    &&
-        ssl->in_msg[0]  == MBEDTLS_SSL_HS_CERTIFICATE   &&
-        memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) );
-        return( 0 );
-    }
-
-    return( -1 );
-#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
-          MBEDTLS_SSL_PROTO_TLS1_2 */
-}
-#endif /* MBEDTLS_SSL_SRV_C */
-
-/* Check if a certificate message is expected.
- * Return either
- * - SSL_CERTIFICATE_EXPECTED, or
- * - SSL_CERTIFICATE_SKIP
- * indicating whether a Certificate message is expected or not.
- */
-#define SSL_CERTIFICATE_EXPECTED 0
-#define SSL_CERTIFICATE_SKIP     1
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_certificate_coordinate( mbedtls_ssl_context *ssl,
-                                             int authmode )
-{
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-
-    if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) )
-        return( SSL_CERTIFICATE_SKIP );
-
-#if defined(MBEDTLS_SSL_SRV_C)
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
-    {
-        if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
-            return( SSL_CERTIFICATE_SKIP );
-
-        if( authmode == MBEDTLS_SSL_VERIFY_NONE )
-        {
-            ssl->session_negotiate->verify_result =
-                MBEDTLS_X509_BADCERT_SKIP_VERIFY;
-            return( SSL_CERTIFICATE_SKIP );
-        }
-    }
-#else
-    ((void) authmode);
-#endif /* MBEDTLS_SSL_SRV_C */
-
-    return( SSL_CERTIFICATE_EXPECTED );
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
-                                         int authmode,
-                                         mbedtls_x509_crt *chain,
-                                         void *rs_ctx )
-{
-    int ret = 0;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-    int have_ca_chain = 0;
-
-    int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *);
-    void *p_vrfy;
-
-    if( authmode == MBEDTLS_SSL_VERIFY_NONE )
-        return( 0 );
-
-    if( ssl->f_vrfy != NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use context-specific verification callback" ) );
-        f_vrfy = ssl->f_vrfy;
-        p_vrfy = ssl->p_vrfy;
-    }
-    else
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use configuration-specific verification callback" ) );
-        f_vrfy = ssl->conf->f_vrfy;
-        p_vrfy = ssl->conf->p_vrfy;
-    }
-
-    /*
-     * Main check: verify certificate
-     */
-#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
-    if( ssl->conf->f_ca_cb != NULL )
-    {
-        ((void) rs_ctx);
-        have_ca_chain = 1;
-
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "use CA callback for X.509 CRT verification" ) );
-        ret = mbedtls_x509_crt_verify_with_ca_cb(
-            chain,
-            ssl->conf->f_ca_cb,
-            ssl->conf->p_ca_cb,
-            ssl->conf->cert_profile,
-            ssl->hostname,
-            &ssl->session_negotiate->verify_result,
-            f_vrfy, p_vrfy );
-    }
-    else
-#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
-    {
-        mbedtls_x509_crt *ca_chain;
-        mbedtls_x509_crl *ca_crl;
-
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-        if( ssl->handshake->sni_ca_chain != NULL )
-        {
-            ca_chain = ssl->handshake->sni_ca_chain;
-            ca_crl   = ssl->handshake->sni_ca_crl;
-        }
-        else
-#endif
-        {
-            ca_chain = ssl->conf->ca_chain;
-            ca_crl   = ssl->conf->ca_crl;
-        }
-
-        if( ca_chain != NULL )
-            have_ca_chain = 1;
-
-        ret = mbedtls_x509_crt_verify_restartable(
-            chain,
-            ca_chain, ca_crl,
-            ssl->conf->cert_profile,
-            ssl->hostname,
-            &ssl->session_negotiate->verify_result,
-            f_vrfy, p_vrfy, rs_ctx );
-    }
-
-    if( ret != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
-    }
-
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
-        return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS );
-#endif
-
-    /*
-     * Secondary checks: always done, but change 'ret' only if it was 0
-     */
-
-#if defined(MBEDTLS_ECP_C)
-    {
-        const mbedtls_pk_context *pk = &chain->pk;
-
-        /* If certificate uses an EC key, make sure the curve is OK.
-         * This is a public key, so it can't be opaque, so can_do() is a good
-         * enough check to ensure pk_ec() is safe to use here. */
-        if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) &&
-            mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 )
-        {
-            ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY;
-
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) );
-            if( ret == 0 )
-                ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
-        }
-    }
-#endif /* MBEDTLS_ECP_C */
-
-    if( mbedtls_ssl_check_cert_usage( chain,
-                                      ciphersuite_info,
-                                      ! ssl->conf->endpoint,
-                                      &ssl->session_negotiate->verify_result ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) );
-        if( ret == 0 )
-            ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
-    }
-
-    /* mbedtls_x509_crt_verify_with_profile is supposed to report a
-     * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED,
-     * with details encoded in the verification flags. All other kinds
-     * of error codes, including those from the user provided f_vrfy
-     * functions, are treated as fatal and lead to a failure of
-     * ssl_parse_certificate even if verification was optional. */
-    if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
-        ( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
-          ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) )
-    {
-        ret = 0;
-    }
-
-    if( have_ca_chain == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) );
-        ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
-    }
-
-    if( ret != 0 )
-    {
-        uint8_t alert;
-
-        /* The certificate may have been rejected for several reasons.
-           Pick one and send the corresponding alert. Which alert to send
-           may be a subject of debate in some cases. */
-        if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER )
-            alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED;
-        else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH )
-            alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
-        else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE )
-            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
-        else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE )
-            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
-        else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE )
-            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
-        else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK )
-            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
-        else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY )
-            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
-        else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED )
-            alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED;
-        else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED )
-            alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED;
-        else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED )
-            alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA;
-        else
-            alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN;
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        alert );
-    }
-
 #if defined(MBEDTLS_DEBUG_C)
-    if( ssl->session_negotiate->verify_result != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %08x",
-                                    (unsigned int) ssl->session_negotiate->verify_result ) );
+static const char *extension_name_table[] = {
+    [MBEDTLS_SSL_EXT_ID_UNRECOGNIZED] = "unrecognized",
+    [MBEDTLS_SSL_EXT_ID_SERVERNAME] = "server_name",
+    [MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH] = "max_fragment_length",
+    [MBEDTLS_SSL_EXT_ID_STATUS_REQUEST] = "status_request",
+    [MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS] = "supported_groups",
+    [MBEDTLS_SSL_EXT_ID_SIG_ALG] = "signature_algorithms",
+    [MBEDTLS_SSL_EXT_ID_USE_SRTP] = "use_srtp",
+    [MBEDTLS_SSL_EXT_ID_HEARTBEAT] = "heartbeat",
+    [MBEDTLS_SSL_EXT_ID_ALPN] = "application_layer_protocol_negotiation",
+    [MBEDTLS_SSL_EXT_ID_SCT] = "signed_certificate_timestamp",
+    [MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE] = "client_certificate_type",
+    [MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE] = "server_certificate_type",
+    [MBEDTLS_SSL_EXT_ID_PADDING] = "padding",
+    [MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY] = "pre_shared_key",
+    [MBEDTLS_SSL_EXT_ID_EARLY_DATA] = "early_data",
+    [MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS] = "supported_versions",
+    [MBEDTLS_SSL_EXT_ID_COOKIE] = "cookie",
+    [MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES] = "psk_key_exchange_modes",
+    [MBEDTLS_SSL_EXT_ID_CERT_AUTH] = "certificate_authorities",
+    [MBEDTLS_SSL_EXT_ID_OID_FILTERS] = "oid_filters",
+    [MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH] = "post_handshake_auth",
+    [MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT] = "signature_algorithms_cert",
+    [MBEDTLS_SSL_EXT_ID_KEY_SHARE] = "key_share",
+    [MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC] = "truncated_hmac",
+    [MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS] = "supported_point_formats",
+    [MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC] = "encrypt_then_mac",
+    [MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET] = "extended_master_secret",
+    [MBEDTLS_SSL_EXT_ID_SESSION_TICKET] = "session_ticket",
+    [MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT] = "record_size_limit"
+};
+
+static unsigned int extension_type_table[] = {
+    [MBEDTLS_SSL_EXT_ID_UNRECOGNIZED] = 0xff,
+    [MBEDTLS_SSL_EXT_ID_SERVERNAME] = MBEDTLS_TLS_EXT_SERVERNAME,
+    [MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH] = MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH,
+    [MBEDTLS_SSL_EXT_ID_STATUS_REQUEST] = MBEDTLS_TLS_EXT_STATUS_REQUEST,
+    [MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS] = MBEDTLS_TLS_EXT_SUPPORTED_GROUPS,
+    [MBEDTLS_SSL_EXT_ID_SIG_ALG] = MBEDTLS_TLS_EXT_SIG_ALG,
+    [MBEDTLS_SSL_EXT_ID_USE_SRTP] = MBEDTLS_TLS_EXT_USE_SRTP,
+    [MBEDTLS_SSL_EXT_ID_HEARTBEAT] = MBEDTLS_TLS_EXT_HEARTBEAT,
+    [MBEDTLS_SSL_EXT_ID_ALPN] = MBEDTLS_TLS_EXT_ALPN,
+    [MBEDTLS_SSL_EXT_ID_SCT] = MBEDTLS_TLS_EXT_SCT,
+    [MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE] = MBEDTLS_TLS_EXT_CLI_CERT_TYPE,
+    [MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE] = MBEDTLS_TLS_EXT_SERV_CERT_TYPE,
+    [MBEDTLS_SSL_EXT_ID_PADDING] = MBEDTLS_TLS_EXT_PADDING,
+    [MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY] = MBEDTLS_TLS_EXT_PRE_SHARED_KEY,
+    [MBEDTLS_SSL_EXT_ID_EARLY_DATA] = MBEDTLS_TLS_EXT_EARLY_DATA,
+    [MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS] = MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS,
+    [MBEDTLS_SSL_EXT_ID_COOKIE] = MBEDTLS_TLS_EXT_COOKIE,
+    [MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES] = MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES,
+    [MBEDTLS_SSL_EXT_ID_CERT_AUTH] = MBEDTLS_TLS_EXT_CERT_AUTH,
+    [MBEDTLS_SSL_EXT_ID_OID_FILTERS] = MBEDTLS_TLS_EXT_OID_FILTERS,
+    [MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH] = MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH,
+    [MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT] = MBEDTLS_TLS_EXT_SIG_ALG_CERT,
+    [MBEDTLS_SSL_EXT_ID_KEY_SHARE] = MBEDTLS_TLS_EXT_KEY_SHARE,
+    [MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC] = MBEDTLS_TLS_EXT_TRUNCATED_HMAC,
+    [MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS] = MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS,
+    [MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC] = MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC,
+    [MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET] = MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET,
+    [MBEDTLS_SSL_EXT_ID_SESSION_TICKET] = MBEDTLS_TLS_EXT_SESSION_TICKET,
+    [MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT] = MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT
+};
+
+const char *mbedtls_ssl_get_extension_name(unsigned int extension_type)
+{
+    return extension_name_table[
+        mbedtls_ssl_get_extension_id(extension_type)];
+}
+
+static const char *ssl_tls13_get_hs_msg_name(int hs_msg_type)
+{
+    switch (hs_msg_type) {
+        case MBEDTLS_SSL_HS_CLIENT_HELLO:
+            return "ClientHello";
+        case MBEDTLS_SSL_HS_SERVER_HELLO:
+            return "ServerHello";
+        case MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST:
+            return "HelloRetryRequest";
+        case MBEDTLS_SSL_HS_NEW_SESSION_TICKET:
+            return "NewSessionTicket";
+        case MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS:
+            return "EncryptedExtensions";
+        case MBEDTLS_SSL_HS_CERTIFICATE:
+            return "Certificate";
+        case MBEDTLS_SSL_HS_CERTIFICATE_REQUEST:
+            return "CertificateRequest";
     }
-    else
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) );
+    return "Unknown";
+}
+
+void mbedtls_ssl_print_extension(const mbedtls_ssl_context *ssl,
+                                 int level, const char *file, int line,
+                                 int hs_msg_type, unsigned int extension_type,
+                                 const char *extra_msg0, const char *extra_msg1)
+{
+    const char *extra_msg;
+    if (extra_msg0 && extra_msg1) {
+        mbedtls_debug_print_msg(
+            ssl, level, file, line,
+            "%s: %s(%u) extension %s %s.",
+            ssl_tls13_get_hs_msg_name(hs_msg_type),
+            mbedtls_ssl_get_extension_name(extension_type),
+            extension_type,
+            extra_msg0, extra_msg1);
+        return;
     }
+
+    extra_msg = extra_msg0 ? extra_msg0 : extra_msg1;
+    if (extra_msg) {
+        mbedtls_debug_print_msg(
+            ssl, level, file, line,
+            "%s: %s(%u) extension %s.", ssl_tls13_get_hs_msg_name(hs_msg_type),
+            mbedtls_ssl_get_extension_name(extension_type), extension_type,
+            extra_msg);
+        return;
+    }
+
+    mbedtls_debug_print_msg(
+        ssl, level, file, line,
+        "%s: %s(%u) extension.", ssl_tls13_get_hs_msg_name(hs_msg_type),
+        mbedtls_ssl_get_extension_name(extension_type), extension_type);
+}
+
+void mbedtls_ssl_print_extensions(const mbedtls_ssl_context *ssl,
+                                  int level, const char *file, int line,
+                                  int hs_msg_type, uint32_t extensions_mask,
+                                  const char *extra)
+{
+
+    for (unsigned i = 0;
+         i < sizeof(extension_name_table) / sizeof(extension_name_table[0]);
+         i++) {
+        mbedtls_ssl_print_extension(
+            ssl, level, file, line, hs_msg_type, extension_type_table[i],
+            extensions_mask & (1 << i) ? "exists" : "does not exist", extra);
+    }
+}
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)
+#define ARRAY_LENGTH(a) (sizeof(a) / sizeof(*(a)))
+
+static const char *ticket_flag_name_table[] =
+{
+    [0] = "ALLOW_PSK_RESUMPTION",
+    [2] = "ALLOW_PSK_EPHEMERAL_RESUMPTION",
+    [3] = "ALLOW_EARLY_DATA",
+};
+
+void mbedtls_ssl_print_ticket_flags(const mbedtls_ssl_context *ssl,
+                                    int level, const char *file, int line,
+                                    unsigned int flags)
+{
+    size_t i;
+
+    mbedtls_debug_print_msg(ssl, level, file, line,
+                            "print ticket_flags (0x%02x)", flags);
+
+    flags = flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK;
+
+    for (i = 0; i < ARRAY_LENGTH(ticket_flag_name_table); i++) {
+        if ((flags & (1 << i))) {
+            mbedtls_debug_print_msg(ssl, level, file, line, "- %s is set.",
+                                    ticket_flag_name_table[i]);
+        }
+    }
+}
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */
+
 #endif /* MBEDTLS_DEBUG_C */
 
-    return( ret );
-}
-
-#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_remember_peer_crt_digest( mbedtls_ssl_context *ssl,
-                                         unsigned char *start, size_t len )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    /* Remember digest of the peer's end-CRT. */
-    ssl->session_negotiate->peer_cert_digest =
-        mbedtls_calloc( 1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN );
-    if( ssl->session_negotiate->peer_cert_digest == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
-                                    MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN ) );
-        mbedtls_ssl_send_alert_message( ssl,
-                                        MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
-
-        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
-    }
-
-    ret = mbedtls_md( mbedtls_md_info_from_type(
-                          MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE ),
-                      start, len,
-                      ssl->session_negotiate->peer_cert_digest );
-
-    ssl->session_negotiate->peer_cert_digest_type =
-        MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE;
-    ssl->session_negotiate->peer_cert_digest_len =
-        MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN;
-
-    return( ret );
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_remember_peer_pubkey( mbedtls_ssl_context *ssl,
-                                     unsigned char *start, size_t len )
-{
-    unsigned char *end = start + len;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    /* Make a copy of the peer's raw public key. */
-    mbedtls_pk_init( &ssl->handshake->peer_pubkey );
-    ret = mbedtls_pk_parse_subpubkey( &start, end,
-                                      &ssl->handshake->peer_pubkey );
-    if( ret != 0 )
-    {
-        /* We should have parsed the public key before. */
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
-    }
-
-    return( 0 );
-}
-#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-
-int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
-{
-    int ret = 0;
-    int crt_expected;
-#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-    const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
-                       ? ssl->handshake->sni_authmode
-                       : ssl->conf->authmode;
-#else
-    const int authmode = ssl->conf->authmode;
-#endif
-    void *rs_ctx = NULL;
-    mbedtls_x509_crt *chain = NULL;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
-
-    crt_expected = ssl_parse_certificate_coordinate( ssl, authmode );
-    if( crt_expected == SSL_CERTIFICATE_SKIP )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
-        goto exit;
-    }
-
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    if( ssl->handshake->ecrs_enabled &&
-        ssl->handshake->ecrs_state == ssl_ecrs_crt_verify )
-    {
-        chain = ssl->handshake->ecrs_peer_cert;
-        ssl->handshake->ecrs_peer_cert = NULL;
-        goto crt_verify;
-    }
-#endif
-
-    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
-    {
-        /* mbedtls_ssl_read_record may have sent an alert already. We
-           let it decide whether to alert. */
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
-        goto exit;
-    }
-
-#if defined(MBEDTLS_SSL_SRV_C)
-    if( ssl_srv_check_client_no_crt_notification( ssl ) == 0 )
-    {
-        ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
-
-        if( authmode != MBEDTLS_SSL_VERIFY_OPTIONAL )
-            ret = MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE;
-
-        goto exit;
-    }
-#endif /* MBEDTLS_SSL_SRV_C */
-
-    /* Clear existing peer CRT structure in case we tried to
-     * reuse a session but it failed, and allocate a new one. */
-    ssl_clear_peer_cert( ssl->session_negotiate );
-
-    chain = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
-    if( chain == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed",
-                                    sizeof( mbedtls_x509_crt ) ) );
-        mbedtls_ssl_send_alert_message( ssl,
-                                        MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
-
-        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
-        goto exit;
-    }
-    mbedtls_x509_crt_init( chain );
-
-    ret = ssl_parse_certificate_chain( ssl, chain );
-    if( ret != 0 )
-        goto exit;
-
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    if( ssl->handshake->ecrs_enabled)
-        ssl->handshake->ecrs_state = ssl_ecrs_crt_verify;
-
-crt_verify:
-    if( ssl->handshake->ecrs_enabled)
-        rs_ctx = &ssl->handshake->ecrs_ctx;
-#endif
-
-    ret = ssl_parse_certificate_verify( ssl, authmode,
-                                        chain, rs_ctx );
-    if( ret != 0 )
-        goto exit;
-
-#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    {
-        unsigned char *crt_start, *pk_start;
-        size_t crt_len, pk_len;
-
-        /* We parse the CRT chain without copying, so
-         * these pointers point into the input buffer,
-         * and are hence still valid after freeing the
-         * CRT chain. */
-
-        crt_start = chain->raw.p;
-        crt_len   = chain->raw.len;
-
-        pk_start = chain->pk_raw.p;
-        pk_len   = chain->pk_raw.len;
-
-        /* Free the CRT structures before computing
-         * digest and copying the peer's public key. */
-        mbedtls_x509_crt_free( chain );
-        mbedtls_free( chain );
-        chain = NULL;
-
-        ret = ssl_remember_peer_crt_digest( ssl, crt_start, crt_len );
-        if( ret != 0 )
-            goto exit;
-
-        ret = ssl_remember_peer_pubkey( ssl, pk_start, pk_len );
-        if( ret != 0 )
-            goto exit;
-    }
-#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-    /* Pass ownership to session structure. */
-    ssl->session_negotiate->peer_cert = chain;
-    chain = NULL;
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
-
-exit:
-
-    if( ret == 0 )
-        ssl->state++;
-
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS )
-    {
-        ssl->handshake->ecrs_peer_cert = chain;
-        chain = NULL;
-    }
-#endif
-
-    if( chain != NULL )
-    {
-        mbedtls_x509_crt_free( chain );
-        mbedtls_free( chain );
-    }
-
-    return( ret );
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
-
-void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl,
-                            const mbedtls_ssl_ciphersuite_t *ciphersuite_info )
+void mbedtls_ssl_optimize_checksum(mbedtls_ssl_context *ssl,
+                                   const mbedtls_ssl_ciphersuite_t *ciphersuite_info)
 {
     ((void) ciphersuite_info);
 
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_1)
-    if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 )
-        ssl->handshake->update_checksum = ssl_update_checksum_md5sha1;
-    else
-#endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
-    if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 )
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    if (ciphersuite_info->mac == MBEDTLS_MD_SHA384) {
         ssl->handshake->update_checksum = ssl_update_checksum_sha384;
-    else
+    } else
 #endif
-#if defined(MBEDTLS_SHA256_C)
-    if( ciphersuite_info->mac != MBEDTLS_MD_SHA384 )
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    if (ciphersuite_info->mac != MBEDTLS_MD_SHA384) {
         ssl->handshake->update_checksum = ssl_update_checksum_sha256;
-    else
+    } else
 #endif
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
         return;
     }
 }
 
-void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_add_hs_hdr_to_checksum(mbedtls_ssl_context *ssl,
+                                       unsigned hs_type,
+                                       size_t total_hs_len)
 {
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_1)
-     mbedtls_md5_starts_ret( &ssl->handshake->fin_md5  );
-    mbedtls_sha1_starts_ret( &ssl->handshake->fin_sha1 );
-#endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_SHA256_C)
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_abort( &ssl->handshake->fin_sha256_psa );
-    psa_hash_setup( &ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256 );
-#else
-    mbedtls_sha256_starts_ret( &ssl->handshake->fin_sha256, 0 );
-#endif
-#endif
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_abort( &ssl->handshake->fin_sha384_psa );
-    psa_hash_setup( &ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384 );
-#else
-    mbedtls_sha512_starts_ret( &ssl->handshake->fin_sha512, 1 );
-#endif
-#endif
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+    unsigned char hs_hdr[4];
+
+    /* Build HS header for checksum update. */
+    hs_hdr[0] = MBEDTLS_BYTE_0(hs_type);
+    hs_hdr[1] = MBEDTLS_BYTE_2(total_hs_len);
+    hs_hdr[2] = MBEDTLS_BYTE_1(total_hs_len);
+    hs_hdr[3] = MBEDTLS_BYTE_0(total_hs_len);
+
+    return ssl->handshake->update_checksum(ssl, hs_hdr, sizeof(hs_hdr));
 }
 
-static void ssl_update_checksum_start( mbedtls_ssl_context *ssl,
-                                       const unsigned char *buf, size_t len )
+int mbedtls_ssl_add_hs_msg_to_checksum(mbedtls_ssl_context *ssl,
+                                       unsigned hs_type,
+                                       unsigned char const *msg,
+                                       size_t msg_len)
 {
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_1)
-     mbedtls_md5_update_ret( &ssl->handshake->fin_md5 , buf, len );
-    mbedtls_sha1_update_ret( &ssl->handshake->fin_sha1, buf, len );
-#endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_SHA256_C)
+    int ret;
+    ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl, hs_type, msg_len);
+    if (ret != 0) {
+        return ret;
+    }
+    return ssl->handshake->update_checksum(ssl, msg, msg_len);
+}
+
+int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl)
+{
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) || \
+    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_update( &ssl->handshake->fin_sha256_psa, buf, len );
-#else
-    mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len );
-#endif
-#endif
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_update( &ssl->handshake->fin_sha384_psa, buf, len );
-#else
-    mbedtls_sha512_update_ret( &ssl->handshake->fin_sha512, buf, len );
-#endif
-#endif
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-}
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_1)
-static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *ssl,
-                                         const unsigned char *buf, size_t len )
-{
-     mbedtls_md5_update_ret( &ssl->handshake->fin_md5 , buf, len );
-    mbedtls_sha1_update_ret( &ssl->handshake->fin_sha1, buf, len );
-}
-#endif
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_SHA256_C)
-static void ssl_update_checksum_sha256( mbedtls_ssl_context *ssl,
-                                        const unsigned char *buf, size_t len )
-{
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_update( &ssl->handshake->fin_sha256_psa, buf, len );
-#else
-    mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len );
-#endif
-}
-#endif
-
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
-static void ssl_update_checksum_sha384( mbedtls_ssl_context *ssl,
-                                        const unsigned char *buf, size_t len )
-{
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_update( &ssl->handshake->fin_sha384_psa, buf, len );
-#else
-    mbedtls_sha512_update_ret( &ssl->handshake->fin_sha512, buf, len );
-#endif
-}
-#endif
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-static void ssl_calc_finished_ssl(
-                mbedtls_ssl_context *ssl, unsigned char *buf, int from )
-{
-    const char *sender;
-    mbedtls_md5_context  md5;
-    mbedtls_sha1_context sha1;
-
-    unsigned char padbuf[48];
-    unsigned char md5sum[16];
-    unsigned char sha1sum[20];
-
-    mbedtls_ssl_session *session = ssl->session_negotiate;
-    if( !session )
-        session = ssl->session;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc  finished ssl" ) );
-
-    mbedtls_md5_init( &md5 );
-    mbedtls_sha1_init( &sha1 );
-
-    mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 );
-    mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 );
-
-    /*
-     * SSLv3:
-     *   hash =
-     *      MD5( master + pad2 +
-     *          MD5( handshake + sender + master + pad1 ) )
-     *   + SHA1( master + pad2 +
-     *         SHA1( handshake + sender + master + pad1 ) )
-     */
-
-#if !defined(MBEDTLS_MD5_ALT)
-    MBEDTLS_SSL_DEBUG_BUF( 4, "finished  md5 state", (unsigned char *)
-                    md5.state, sizeof(  md5.state ) );
-#endif
-
-#if !defined(MBEDTLS_SHA1_ALT)
-    MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *)
-                   sha1.state, sizeof( sha1.state ) );
-#endif
-
-    sender = ( from == MBEDTLS_SSL_IS_CLIENT ) ? "CLNT"
-                                       : "SRVR";
-
-    memset( padbuf, 0x36, 48 );
-
-    mbedtls_md5_update_ret( &md5, (const unsigned char *) sender, 4 );
-    mbedtls_md5_update_ret( &md5, session->master, 48 );
-    mbedtls_md5_update_ret( &md5, padbuf, 48 );
-    mbedtls_md5_finish_ret( &md5, md5sum );
-
-    mbedtls_sha1_update_ret( &sha1, (const unsigned char *) sender, 4 );
-    mbedtls_sha1_update_ret( &sha1, session->master, 48 );
-    mbedtls_sha1_update_ret( &sha1, padbuf, 40 );
-    mbedtls_sha1_finish_ret( &sha1, sha1sum );
-
-    memset( padbuf, 0x5C, 48 );
-
-    mbedtls_md5_starts_ret( &md5 );
-    mbedtls_md5_update_ret( &md5, session->master, 48 );
-    mbedtls_md5_update_ret( &md5, padbuf, 48 );
-    mbedtls_md5_update_ret( &md5, md5sum, 16 );
-    mbedtls_md5_finish_ret( &md5, buf );
-
-    mbedtls_sha1_starts_ret( &sha1 );
-    mbedtls_sha1_update_ret( &sha1, session->master, 48 );
-    mbedtls_sha1_update_ret( &sha1, padbuf , 40 );
-    mbedtls_sha1_update_ret( &sha1, sha1sum, 20 );
-    mbedtls_sha1_finish_ret( &sha1, buf + 16 );
-
-    MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 );
-
-    mbedtls_md5_free(  &md5  );
-    mbedtls_sha1_free( &sha1 );
-
-    mbedtls_platform_zeroize(  padbuf, sizeof(  padbuf ) );
-    mbedtls_platform_zeroize(  md5sum, sizeof(  md5sum ) );
-    mbedtls_platform_zeroize( sha1sum, sizeof( sha1sum ) );
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
-}
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
-static void ssl_calc_finished_tls(
-                mbedtls_ssl_context *ssl, unsigned char *buf, int from )
-{
-    int len = 12;
-    const char *sender;
-    mbedtls_md5_context  md5;
-    mbedtls_sha1_context sha1;
-    unsigned char padbuf[36];
-
-    mbedtls_ssl_session *session = ssl->session_negotiate;
-    if( !session )
-        session = ssl->session;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc  finished tls" ) );
-
-    mbedtls_md5_init( &md5 );
-    mbedtls_sha1_init( &sha1 );
-
-    mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 );
-    mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 );
-
-    /*
-     * TLSv1:
-     *   hash = PRF( master, finished_label,
-     *               MD5( handshake ) + SHA1( handshake ) )[0..11]
-     */
-
-#if !defined(MBEDTLS_MD5_ALT)
-    MBEDTLS_SSL_DEBUG_BUF( 4, "finished  md5 state", (unsigned char *)
-                    md5.state, sizeof(  md5.state ) );
-#endif
-
-#if !defined(MBEDTLS_SHA1_ALT)
-    MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *)
-                   sha1.state, sizeof( sha1.state ) );
-#endif
-
-    sender = ( from == MBEDTLS_SSL_IS_CLIENT )
-             ? "client finished"
-             : "server finished";
-
-    mbedtls_md5_finish_ret(  &md5, padbuf );
-    mbedtls_sha1_finish_ret( &sha1, padbuf + 16 );
-
-    ssl->handshake->tls_prf( session->master, 48, sender,
-                             padbuf, 36, buf, len );
-
-    MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
-
-    mbedtls_md5_free(  &md5  );
-    mbedtls_sha1_free( &sha1 );
-
-    mbedtls_platform_zeroize(  padbuf, sizeof(  padbuf ) );
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
-}
-#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_SHA256_C)
-static void ssl_calc_finished_tls_sha256(
-                mbedtls_ssl_context *ssl, unsigned char *buf, int from )
-{
-    int len = 12;
-    const char *sender;
-    unsigned char padbuf[32];
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    size_t hash_size;
-    psa_hash_operation_t sha256_psa = PSA_HASH_OPERATION_INIT;
     psa_status_t status;
 #else
-    mbedtls_sha256_context sha256;
-#endif
-
-    mbedtls_ssl_session *session = ssl->session_negotiate;
-    if( !session )
-        session = ssl->session;
-
-    sender = ( from == MBEDTLS_SSL_IS_CLIENT )
-             ? "client finished"
-             : "server finished";
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    sha256_psa = psa_hash_operation_init();
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc PSA finished tls sha256" ) );
-
-    status = psa_hash_clone( &ssl->handshake->fin_sha256_psa, &sha256_psa );
-    if( status != PSA_SUCCESS )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) );
-        return;
-    }
-
-    status = psa_hash_finish( &sha256_psa, padbuf, sizeof( padbuf ), &hash_size );
-    if( status != PSA_SUCCESS )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) );
-        return;
-    }
-    MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated padbuf", padbuf, 32 );
-#else
-
-    mbedtls_sha256_init( &sha256 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc  finished tls sha256" ) );
-
-    mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 );
-
-    /*
-     * TLSv1.2:
-     *   hash = PRF( master, finished_label,
-     *               Hash( handshake ) )[0.11]
-     */
-
-#if !defined(MBEDTLS_SHA256_ALT)
-    MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *)
-                   sha256.state, sizeof( sha256.state ) );
-#endif
-
-    mbedtls_sha256_finish_ret( &sha256, padbuf );
-    mbedtls_sha256_free( &sha256 );
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-    ssl->handshake->tls_prf( session->master, 48, sender,
-                             padbuf, 32, buf, len );
-
-    MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
-
-    mbedtls_platform_zeroize(  padbuf, sizeof(  padbuf ) );
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
-}
-#endif /* MBEDTLS_SHA256_C */
-
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
-
-static void ssl_calc_finished_tls_sha384(
-                mbedtls_ssl_context *ssl, unsigned char *buf, int from )
-{
-    int len = 12;
-    const char *sender;
-    unsigned char padbuf[48];
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    size_t hash_size;
-    psa_hash_operation_t sha384_psa = PSA_HASH_OPERATION_INIT;
-    psa_status_t status;
-#else
-    mbedtls_sha512_context sha512;
-#endif
-
-    mbedtls_ssl_session *session = ssl->session_negotiate;
-    if( !session )
-        session = ssl->session;
-
-    sender = ( from == MBEDTLS_SSL_IS_CLIENT )
-                ? "client finished"
-                : "server finished";
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    sha384_psa = psa_hash_operation_init();
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc PSA finished tls sha384" ) );
-
-    status = psa_hash_clone( &ssl->handshake->fin_sha384_psa, &sha384_psa );
-    if( status != PSA_SUCCESS )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) );
-        return;
-    }
-
-    status = psa_hash_finish( &sha384_psa, padbuf, sizeof( padbuf ), &hash_size );
-    if( status != PSA_SUCCESS )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) );
-        return;
-    }
-    MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated padbuf", padbuf, 48 );
-#else
-    mbedtls_sha512_init( &sha512 );
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc  finished tls sha384" ) );
-
-    mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 );
-
-    /*
-     * TLSv1.2:
-     *   hash = PRF( master, finished_label,
-     *               Hash( handshake ) )[0.11]
-     */
-
-#if !defined(MBEDTLS_SHA512_ALT)
-    MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha512 state", (unsigned char *)
-                   sha512.state, sizeof( sha512.state ) );
-#endif
-    /* mbedtls_sha512_finish_ret's output parameter is declared as a
-     * 64-byte buffer, but sice we're using SHA-384, we know that the
-     * output fits in 48 bytes. This is correct C, but GCC 11.1 warns
-     * about it.
-     */
-#if defined(__GNUC__) && __GNUC__ >= 11
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wstringop-overflow"
-#endif
-    mbedtls_sha512_finish_ret( &sha512, padbuf );
-#if defined(__GNUC__) && __GNUC__ >= 11
-#pragma GCC diagnostic pop
-#endif
-
-    mbedtls_sha512_free( &sha512 );
-#endif
-
-    ssl->handshake->tls_prf( session->master, 48, sender,
-                             padbuf, 48, buf, len );
-
-    MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
-
-    mbedtls_platform_zeroize(  padbuf, sizeof( padbuf ) );
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc  finished" ) );
-}
-#endif /* MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384 */
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-
-void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl )
-{
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup: final free" ) );
-
-    /*
-     * Free our handshake params
-     */
-    mbedtls_ssl_handshake_free( ssl );
-    mbedtls_free( ssl->handshake );
-    ssl->handshake = NULL;
-
-    /*
-     * Free the previous transform and switch in the current one
-     */
-    if( ssl->transform )
-    {
-        mbedtls_ssl_transform_free( ssl->transform );
-        mbedtls_free( ssl->transform );
-    }
-    ssl->transform = ssl->transform_negotiate;
-    ssl->transform_negotiate = NULL;
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup: final free" ) );
-}
-
-void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl )
-{
-    int resume = ssl->handshake->resume;
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) );
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
-    {
-        ssl->renego_status =  MBEDTLS_SSL_RENEGOTIATION_DONE;
-        ssl->renego_records_seen = 0;
-    }
-#endif
-
-    /*
-     * Free the previous session and switch in the current one
-     */
-    if( ssl->session )
-    {
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-        /* RFC 7366 3.1: keep the EtM state */
-        ssl->session_negotiate->encrypt_then_mac =
-                  ssl->session->encrypt_then_mac;
-#endif
-
-        mbedtls_ssl_session_free( ssl->session );
-        mbedtls_free( ssl->session );
-    }
-    ssl->session = ssl->session_negotiate;
-    ssl->session_negotiate = NULL;
-
-    /*
-     * Add cache entry
-     */
-    if( ssl->conf->f_set_cache != NULL &&
-        ssl->session->id_len != 0 &&
-        resume == 0 )
-    {
-        if( ssl->conf->f_set_cache( ssl->conf->p_cache, ssl->session ) != 0 )
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "cache did not store session" ) );
-    }
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ssl->handshake->flight != NULL )
-    {
-        /* Cancel handshake timer */
-        mbedtls_ssl_set_timer( ssl, 0 );
-
-        /* Keep last flight around in case we need to resend it:
-         * we need the handshake and transform structures for that */
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip freeing handshake and transform" ) );
-    }
-    else
-#endif
-        mbedtls_ssl_handshake_wrapup_free_hs_transform( ssl );
-
-    ssl->state++;
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) );
-}
-
-int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl )
-{
-    int ret, hash_len;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) );
-
-    mbedtls_ssl_update_out_pointers( ssl, ssl->transform_negotiate );
-
-    ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint );
-
-    /*
-     * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites
-     * may define some other value. Currently (early 2016), no defined
-     * ciphersuite does this (and this is unlikely to change as activity has
-     * moved to TLS 1.3 now) so we can keep the hardcoded 12 here.
-     */
-    hash_len = ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) ? 36 : 12;
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    ssl->verify_data_len = hash_len;
-    memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len );
-#endif
-
-    ssl->out_msglen  = 4 + hash_len;
-    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
-    ssl->out_msg[0]  = MBEDTLS_SSL_HS_FINISHED;
-
-    /*
-     * In case of session resuming, invert the client and server
-     * ChangeCipherSpec messages order.
-     */
-    if( ssl->handshake->resume != 0 )
-    {
-#if defined(MBEDTLS_SSL_CLI_C)
-        if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
-            ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
-#endif
-#if defined(MBEDTLS_SSL_SRV_C)
-        if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
-            ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC;
-#endif
-    }
-    else
-        ssl->state++;
-
-    /*
-     * Switch to our negotiated transform and session parameters for outbound
-     * data.
-     */
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) );
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        unsigned char i;
-
-        /* Remember current epoch settings for resending */
-        ssl->handshake->alt_transform_out = ssl->transform_out;
-        memcpy( ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, 8 );
-
-        /* Set sequence_number to zero */
-        memset( ssl->cur_out_ctr + 2, 0, 6 );
-
-        /* Increment epoch */
-        for( i = 2; i > 0; i-- )
-            if( ++ssl->cur_out_ctr[i - 1] != 0 )
-                break;
-
-        /* The loop goes to its end iff the counter is wrapping */
-        if( i == 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) );
-            return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
-        }
-    }
-    else
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-    memset( ssl->cur_out_ctr, 0, 8 );
-
-    ssl->transform_out = ssl->transform_negotiate;
-    ssl->session_out = ssl->session_negotiate;
-
-#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
-    if( mbedtls_ssl_hw_record_activate != NULL )
-    {
-        if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret );
-            return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-        }
-    }
-#endif
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-        mbedtls_ssl_send_flight_completed( ssl );
-#endif
-
-    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
-        return( ret );
-    }
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret );
-        return( ret );
-    }
-#endif
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished" ) );
-
-    return( 0 );
-}
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-#define SSL_MAX_HASH_LEN 36
-#else
-#define SSL_MAX_HASH_LEN 12
-#endif
-
-int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl )
-{
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned int hash_len;
-    unsigned char buf[SSL_MAX_HASH_LEN];
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse finished" ) );
-
-    /* There is currently no ciphersuite using another length with TLS 1.2 */
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-    if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
-        hash_len = 36;
-    else
 #endif
-        hash_len = 12;
-
-    ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 );
-
-    if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
-        goto exit;
+#else /* SHA-256 or SHA-384 */
+    ((void) ssl);
+#endif /* SHA-256 or SHA-384 */
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    status = psa_hash_abort(&ssl->handshake->fin_sha256_psa);
+    if (status != PSA_SUCCESS) {
+        return PSA_TO_MD_ERR(status);
     }
-
-    if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
-        ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
-        goto exit;
+    status = psa_hash_setup(&ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256);
+    if (status != PSA_SUCCESS) {
+        return PSA_TO_MD_ERR(status);
     }
-
-    if( ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED ||
-        ssl->in_hslen  != mbedtls_ssl_hs_hdr_len( ssl ) + hash_len )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        ret = MBEDTLS_ERR_SSL_BAD_HS_FINISHED;
-        goto exit;
+#else
+    mbedtls_md_free(&ssl->handshake->fin_sha256);
+    mbedtls_md_init(&ssl->handshake->fin_sha256);
+    ret = mbedtls_md_setup(&ssl->handshake->fin_sha256,
+                           mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
+                           0);
+    if (ret != 0) {
+        return ret;
     }
-
-    if( mbedtls_ct_memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ),
-                      buf, hash_len ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) );
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
-        ret = MBEDTLS_ERR_SSL_BAD_HS_FINISHED;
-        goto exit;
+    ret = mbedtls_md_starts(&ssl->handshake->fin_sha256);
+    if (ret != 0) {
+        return ret;
     }
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    ssl->verify_data_len = hash_len;
-    memcpy( ssl->peer_verify_data, buf, hash_len );
 #endif
-
-    if( ssl->handshake->resume != 0 )
-    {
-#if defined(MBEDTLS_SSL_CLI_C)
-        if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
-            ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC;
 #endif
-#if defined(MBEDTLS_SSL_SRV_C)
-        if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
-            ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
-#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    status = psa_hash_abort(&ssl->handshake->fin_sha384_psa);
+    if (status != PSA_SUCCESS) {
+        return PSA_TO_MD_ERR(status);
     }
-    else
-        ssl->state++;
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-        mbedtls_ssl_recv_flight_completed( ssl );
+    status = psa_hash_setup(&ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384);
+    if (status != PSA_SUCCESS) {
+        return PSA_TO_MD_ERR(status);
+    }
+#else
+    mbedtls_md_free(&ssl->handshake->fin_sha384);
+    mbedtls_md_init(&ssl->handshake->fin_sha384);
+    ret = mbedtls_md_setup(&ssl->handshake->fin_sha384,
+                           mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0);
+    if (ret != 0) {
+        return ret;
+    }
+    ret = mbedtls_md_starts(&ssl->handshake->fin_sha384);
+    if (ret != 0) {
+        return ret;
+    }
 #endif
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse finished" ) );
-
-exit:
-    mbedtls_platform_zeroize( buf, hash_len );
-    return( ret );
+#endif
+    return 0;
 }
 
-static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake )
+static int ssl_update_checksum_start(mbedtls_ssl_context *ssl,
+                                     const unsigned char *buf, size_t len)
 {
-    memset( handshake, 0, sizeof( mbedtls_ssl_handshake_params ) );
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_1)
-     mbedtls_md5_init(   &handshake->fin_md5  );
-    mbedtls_sha1_init(   &handshake->fin_sha1 );
-     mbedtls_md5_starts_ret( &handshake->fin_md5  );
-    mbedtls_sha1_starts_ret( &handshake->fin_sha1 );
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) || \
+    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_status_t status;
+#else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 #endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_SHA256_C)
+#else /* SHA-256 or SHA-384 */
+    ((void) ssl);
+    (void) buf;
+    (void) len;
+#endif /* SHA-256 or SHA-384 */
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    status = psa_hash_update(&ssl->handshake->fin_sha256_psa, buf, len);
+    if (status != PSA_SUCCESS) {
+        return PSA_TO_MD_ERR(status);
+    }
+#else
+    ret = mbedtls_md_update(&ssl->handshake->fin_sha256, buf, len);
+    if (ret != 0) {
+        return ret;
+    }
+#endif
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    status = psa_hash_update(&ssl->handshake->fin_sha384_psa, buf, len);
+    if (status != PSA_SUCCESS) {
+        return PSA_TO_MD_ERR(status);
+    }
+#else
+    ret = mbedtls_md_update(&ssl->handshake->fin_sha384, buf, len);
+    if (ret != 0) {
+        return ret;
+    }
+#endif
+#endif
+    return 0;
+}
+
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+static int ssl_update_checksum_sha256(mbedtls_ssl_context *ssl,
+                                      const unsigned char *buf, size_t len)
+{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    return PSA_TO_MD_ERR(psa_hash_update(
+                             &ssl->handshake->fin_sha256_psa, buf, len));
+#else
+    return mbedtls_md_update(&ssl->handshake->fin_sha256, buf, len);
+#endif
+}
+#endif
+
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+static int ssl_update_checksum_sha384(mbedtls_ssl_context *ssl,
+                                      const unsigned char *buf, size_t len)
+{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    return PSA_TO_MD_ERR(psa_hash_update(
+                             &ssl->handshake->fin_sha384_psa, buf, len));
+#else
+    return mbedtls_md_update(&ssl->handshake->fin_sha384, buf, len);
+#endif
+}
+#endif
+
+static void ssl_handshake_params_init(mbedtls_ssl_handshake_params *handshake)
+{
+    memset(handshake, 0, sizeof(mbedtls_ssl_handshake_params));
+
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     handshake->fin_sha256_psa = psa_hash_operation_init();
-    psa_hash_setup( &handshake->fin_sha256_psa, PSA_ALG_SHA_256 );
 #else
-    mbedtls_sha256_init(   &handshake->fin_sha256    );
-    mbedtls_sha256_starts_ret( &handshake->fin_sha256, 0 );
+    mbedtls_md_init(&handshake->fin_sha256);
 #endif
 #endif
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     handshake->fin_sha384_psa = psa_hash_operation_init();
-    psa_hash_setup( &handshake->fin_sha384_psa, PSA_ALG_SHA_384 );
 #else
-    mbedtls_sha512_init(   &handshake->fin_sha512    );
-    mbedtls_sha512_starts_ret( &handshake->fin_sha512, 1 );
+    mbedtls_md_init(&handshake->fin_sha384);
 #endif
 #endif
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
     handshake->update_checksum = ssl_update_checksum_start;
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
-    defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-    mbedtls_ssl_sig_hash_set_init( &handshake->hash_algs );
-#endif
-
 #if defined(MBEDTLS_DHM_C)
-    mbedtls_dhm_init( &handshake->dhm_ctx );
+    mbedtls_dhm_init(&handshake->dhm_ctx);
 #endif
-#if defined(MBEDTLS_ECDH_C)
-    mbedtls_ecdh_init( &handshake->ecdh_ctx );
+#if !defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ECDH_C)
+    mbedtls_ecdh_init(&handshake->ecdh_ctx);
 #endif
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    mbedtls_ecjpake_init( &handshake->ecjpake_ctx );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    handshake->psa_pake_ctx = psa_pake_operation_init();
+    handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT;
+#else
+    mbedtls_ecjpake_init(&handshake->ecjpake_ctx);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 #if defined(MBEDTLS_SSL_CLI_C)
     handshake->ecjpake_cache = NULL;
     handshake->ecjpake_cache_len = 0;
@@ -3788,7 +1003,7 @@
 #endif
 
 #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    mbedtls_x509_crt_restart_init( &handshake->ecrs_ctx );
+    mbedtls_x509_crt_restart_init(&handshake->ecrs_ctx);
 #endif
 
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
@@ -3797,110 +1012,256 @@
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C) && \
     !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    mbedtls_pk_init( &handshake->peer_pubkey );
+    mbedtls_pk_init(&handshake->peer_pubkey);
 #endif
 }
 
-void mbedtls_ssl_transform_init( mbedtls_ssl_transform *transform )
+void mbedtls_ssl_transform_init(mbedtls_ssl_transform *transform)
 {
-    memset( transform, 0, sizeof(mbedtls_ssl_transform) );
+    memset(transform, 0, sizeof(mbedtls_ssl_transform));
 
-    mbedtls_cipher_init( &transform->cipher_ctx_enc );
-    mbedtls_cipher_init( &transform->cipher_ctx_dec );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    transform->psa_key_enc = MBEDTLS_SVC_KEY_ID_INIT;
+    transform->psa_key_dec = MBEDTLS_SVC_KEY_ID_INIT;
+#else
+    mbedtls_cipher_init(&transform->cipher_ctx_enc);
+    mbedtls_cipher_init(&transform->cipher_ctx_dec);
+#endif
 
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
-    mbedtls_md_init( &transform->md_ctx_enc );
-    mbedtls_md_init( &transform->md_ctx_dec );
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    transform->psa_mac_enc = MBEDTLS_SVC_KEY_ID_INIT;
+    transform->psa_mac_dec = MBEDTLS_SVC_KEY_ID_INIT;
+#else
+    mbedtls_md_init(&transform->md_ctx_enc);
+    mbedtls_md_init(&transform->md_ctx_dec);
+#endif
 #endif
 }
 
-void mbedtls_ssl_session_init( mbedtls_ssl_session *session )
+void mbedtls_ssl_session_init(mbedtls_ssl_session *session)
 {
-    memset( session, 0, sizeof(mbedtls_ssl_session) );
+    memset(session, 0, sizeof(mbedtls_ssl_session));
 }
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_handshake_init( mbedtls_ssl_context *ssl )
+static int ssl_handshake_init(mbedtls_ssl_context *ssl)
 {
-    /* Clear old handshake information if present */
-    if( ssl->transform_negotiate )
-        mbedtls_ssl_transform_free( ssl->transform_negotiate );
-    if( ssl->session_negotiate )
-        mbedtls_ssl_session_free( ssl->session_negotiate );
-    if( ssl->handshake )
-        mbedtls_ssl_handshake_free( ssl );
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
+    /* Clear old handshake information if present */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    if (ssl->transform_negotiate) {
+        mbedtls_ssl_transform_free(ssl->transform_negotiate);
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+    if (ssl->session_negotiate) {
+        mbedtls_ssl_session_free(ssl->session_negotiate);
+    }
+    if (ssl->handshake) {
+        mbedtls_ssl_handshake_free(ssl);
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
     /*
      * Either the pointers are now NULL or cleared properly and can be freed.
      * Now allocate missing structures.
      */
-    if( ssl->transform_negotiate == NULL )
-    {
-        ssl->transform_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_transform) );
+    if (ssl->transform_negotiate == NULL) {
+        ssl->transform_negotiate = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform));
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+    if (ssl->session_negotiate == NULL) {
+        ssl->session_negotiate = mbedtls_calloc(1, sizeof(mbedtls_ssl_session));
     }
 
-    if( ssl->session_negotiate == NULL )
-    {
-        ssl->session_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_session) );
-    }
-
-    if( ssl->handshake == NULL )
-    {
-        ssl->handshake = mbedtls_calloc( 1, sizeof(mbedtls_ssl_handshake_params) );
+    if (ssl->handshake == NULL) {
+        ssl->handshake = mbedtls_calloc(1, sizeof(mbedtls_ssl_handshake_params));
     }
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
     /* If the buffers are too small - reallocate */
 
-    handle_buffer_resizing( ssl, 0, MBEDTLS_SSL_IN_BUFFER_LEN,
-                                    MBEDTLS_SSL_OUT_BUFFER_LEN );
+    handle_buffer_resizing(ssl, 0, MBEDTLS_SSL_IN_BUFFER_LEN,
+                           MBEDTLS_SSL_OUT_BUFFER_LEN);
 #endif
 
     /* All pointers should exist and can be directly freed without issue */
-    if( ssl->handshake == NULL ||
+    if (ssl->handshake           == NULL ||
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
         ssl->transform_negotiate == NULL ||
-        ssl->session_negotiate == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc() of ssl sub-contexts failed" ) );
+#endif
+        ssl->session_negotiate   == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("alloc() of ssl sub-contexts failed"));
 
-        mbedtls_free( ssl->handshake );
-        mbedtls_free( ssl->transform_negotiate );
-        mbedtls_free( ssl->session_negotiate );
-
+        mbedtls_free(ssl->handshake);
         ssl->handshake = NULL;
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        mbedtls_free(ssl->transform_negotiate);
         ssl->transform_negotiate = NULL;
+#endif
+
+        mbedtls_free(ssl->session_negotiate);
         ssl->session_negotiate = NULL;
 
-        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
     }
 
     /* Initialize structures */
-    mbedtls_ssl_session_init( ssl->session_negotiate );
-    mbedtls_ssl_transform_init( ssl->transform_negotiate );
-    ssl_handshake_params_init( ssl->handshake );
+    mbedtls_ssl_session_init(ssl->session_negotiate);
+    ssl_handshake_params_init(ssl->handshake);
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    mbedtls_ssl_transform_init(ssl->transform_negotiate);
+#endif
+
+    /* Setup handshake checksums */
+    ret = mbedtls_ssl_reset_checksum(ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_reset_checksum", ret);
+        return ret;
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
+    defined(MBEDTLS_SSL_SRV_C) && \
+    defined(MBEDTLS_SSL_SESSION_TICKETS)
+    ssl->handshake->new_session_tickets_count =
+        ssl->conf->new_session_tickets_count;
+#endif
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
         ssl->handshake->alt_transform_out = ssl->transform_out;
 
-        if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
+        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
             ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING;
-        else
+        } else {
             ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;
+        }
 
-        mbedtls_ssl_set_timer( ssl, 0 );
+        mbedtls_ssl_set_timer(ssl, 0);
     }
 #endif
 
-    return( 0 );
+/*
+ * curve_list is translated to IANA TLS group identifiers here because
+ * mbedtls_ssl_conf_curves returns void and so can't return
+ * any error codes.
+ */
+#if defined(MBEDTLS_ECP_C)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+    /* Heap allocate and translate curve_list from internal to IANA group ids */
+    if (ssl->conf->curve_list != NULL) {
+        size_t length;
+        const mbedtls_ecp_group_id *curve_list = ssl->conf->curve_list;
+
+        for (length = 0;  (curve_list[length] != MBEDTLS_ECP_DP_NONE) &&
+             (length < MBEDTLS_ECP_DP_MAX); length++) {
+        }
+
+        /* Leave room for zero termination */
+        uint16_t *group_list = mbedtls_calloc(length + 1, sizeof(uint16_t));
+        if (group_list == NULL) {
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        }
+
+        for (size_t i = 0; i < length; i++) {
+            uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(
+                curve_list[i]);
+            if (tls_id == 0) {
+                mbedtls_free(group_list);
+                return MBEDTLS_ERR_SSL_BAD_CONFIG;
+            }
+            group_list[i] = tls_id;
+        }
+
+        group_list[length] = 0;
+
+        ssl->handshake->group_list = group_list;
+        ssl->handshake->group_list_heap_allocated = 1;
+    } else {
+        ssl->handshake->group_list = ssl->conf->group_list;
+        ssl->handshake->group_list_heap_allocated = 0;
+    }
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+#endif /* MBEDTLS_ECP_C */
+
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    /* Heap allocate and translate sig_hashes from internal hash identifiers to
+       signature algorithms IANA identifiers.  */
+    if (mbedtls_ssl_conf_is_tls12_only(ssl->conf) &&
+        ssl->conf->sig_hashes != NULL) {
+        const int *md;
+        const int *sig_hashes = ssl->conf->sig_hashes;
+        size_t sig_algs_len = 0;
+        uint16_t *p;
+
+        MBEDTLS_STATIC_ASSERT(MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN
+                              <= (SIZE_MAX - (2 * sizeof(uint16_t))),
+                              "MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN too big");
+
+        for (md = sig_hashes; *md != MBEDTLS_MD_NONE; md++) {
+            if (mbedtls_ssl_hash_from_md_alg(*md) == MBEDTLS_SSL_HASH_NONE) {
+                continue;
+            }
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
+            sig_algs_len += sizeof(uint16_t);
+#endif
+
+#if defined(MBEDTLS_RSA_C)
+            sig_algs_len += sizeof(uint16_t);
+#endif
+            if (sig_algs_len > MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN) {
+                return MBEDTLS_ERR_SSL_BAD_CONFIG;
+            }
+        }
+
+        if (sig_algs_len < MBEDTLS_SSL_MIN_SIG_ALG_LIST_LEN) {
+            return MBEDTLS_ERR_SSL_BAD_CONFIG;
+        }
+
+        ssl->handshake->sig_algs = mbedtls_calloc(1, sig_algs_len +
+                                                  sizeof(uint16_t));
+        if (ssl->handshake->sig_algs == NULL) {
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        }
+
+        p = (uint16_t *) ssl->handshake->sig_algs;
+        for (md = sig_hashes; *md != MBEDTLS_MD_NONE; md++) {
+            unsigned char hash = mbedtls_ssl_hash_from_md_alg(*md);
+            if (hash == MBEDTLS_SSL_HASH_NONE) {
+                continue;
+            }
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
+            *p = ((hash << 8) | MBEDTLS_SSL_SIG_ECDSA);
+            p++;
+#endif
+#if defined(MBEDTLS_RSA_C)
+            *p = ((hash << 8) | MBEDTLS_SSL_SIG_RSA);
+            p++;
+#endif
+        }
+        *p = MBEDTLS_TLS_SIG_NONE;
+        ssl->handshake->sig_algs_heap_allocated = 1;
+    } else
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+    {
+        ssl->handshake->sig_algs_heap_allocated = 0;
+    }
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
+    return 0;
 }
 
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
 /* Dummy cookie callbacks for defaults */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_cookie_write_dummy( void *ctx,
-                      unsigned char **p, unsigned char *end,
-                      const unsigned char *cli_id, size_t cli_id_len )
+static int ssl_cookie_write_dummy(void *ctx,
+                                  unsigned char **p, unsigned char *end,
+                                  const unsigned char *cli_id, size_t cli_id_len)
 {
     ((void) ctx);
     ((void) p);
@@ -3908,13 +1269,13 @@
     ((void) cli_id);
     ((void) cli_id_len);
 
-    return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
 }
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_cookie_check_dummy( void *ctx,
-                      const unsigned char *cookie, size_t cookie_len,
-                      const unsigned char *cli_id, size_t cli_id_len )
+static int ssl_cookie_check_dummy(void *ctx,
+                                  const unsigned char *cookie, size_t cookie_len,
+                                  const unsigned char *cli_id, size_t cli_id_len)
 {
     ((void) ctx);
     ((void) cookie);
@@ -3922,24 +1283,107 @@
     ((void) cli_id);
     ((void) cli_id_len);
 
-    return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+    return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
 }
 #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */
 
 /*
  * Initialize an SSL context
  */
-void mbedtls_ssl_init( mbedtls_ssl_context *ssl )
+void mbedtls_ssl_init(mbedtls_ssl_context *ssl)
 {
-    memset( ssl, 0, sizeof( mbedtls_ssl_context ) );
+    memset(ssl, 0, sizeof(mbedtls_ssl_context));
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_conf_version_check(const mbedtls_ssl_context *ssl)
+{
+    const mbedtls_ssl_config *conf = ssl->conf;
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    if (mbedtls_ssl_conf_is_tls13_only(conf)) {
+        if (conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS 1.3 is not yet supported."));
+            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+        }
+
+        MBEDTLS_SSL_DEBUG_MSG(4, ("The SSL configuration is tls13 only."));
+        return 0;
+    }
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    if (mbedtls_ssl_conf_is_tls12_only(conf)) {
+        MBEDTLS_SSL_DEBUG_MSG(4, ("The SSL configuration is tls12 only."));
+        return 0;
+    }
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    if (mbedtls_ssl_conf_is_hybrid_tls12_tls13(conf)) {
+        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS not yet supported in Hybrid TLS 1.3 + TLS 1.2"));
+            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+        }
+
+        if (conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("TLS 1.3 server is not supported yet."));
+            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+        }
+
+
+        MBEDTLS_SSL_DEBUG_MSG(4, ("The SSL configuration is TLS 1.3 or TLS 1.2."));
+        return 0;
+    }
+#endif
+
+    MBEDTLS_SSL_DEBUG_MSG(1, ("The SSL configuration is invalid."));
+    return MBEDTLS_ERR_SSL_BAD_CONFIG;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_conf_check(const mbedtls_ssl_context *ssl)
+{
+    int ret;
+    ret = ssl_conf_version_check(ssl);
+    if (ret != 0) {
+        return ret;
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    /* RFC 8446 section 4.4.3
+     *
+     * If the verification fails, the receiver MUST terminate the handshake with
+     * a "decrypt_error" alert.
+     *
+     * If the client is configured as TLS 1.3 only with optional verify, return
+     * bad config.
+     *
+     */
+    if (mbedtls_ssl_conf_tls13_ephemeral_enabled(
+            (mbedtls_ssl_context *) ssl)                            &&
+        ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT                &&
+        ssl->conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3    &&
+        ssl->conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_3    &&
+        ssl->conf->authmode == MBEDTLS_SSL_VERIFY_OPTIONAL) {
+        MBEDTLS_SSL_DEBUG_MSG(
+            1, ("Optional verify auth mode "
+                "is not available for TLS 1.3 client"));
+        return MBEDTLS_ERR_SSL_BAD_CONFIG;
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+    /* Space for further checks */
+
+    return 0;
 }
 
 /*
  * Setup an SSL context
  */
 
-int mbedtls_ssl_setup( mbedtls_ssl_context *ssl,
-                       const mbedtls_ssl_config *conf )
+int mbedtls_ssl_setup(mbedtls_ssl_context *ssl,
+                      const mbedtls_ssl_config *conf)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
@@ -3947,6 +1391,10 @@
 
     ssl->conf = conf;
 
+    if ((ret = ssl_conf_check(ssl)) != 0) {
+        return ret;
+    }
+
     /*
      * Prepare base structures
      */
@@ -3957,10 +1405,9 @@
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
     ssl->in_buf_len = in_buf_len;
 #endif
-    ssl->in_buf = mbedtls_calloc( 1, in_buf_len );
-    if( ssl->in_buf == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", in_buf_len ) );
+    ssl->in_buf = mbedtls_calloc(1, in_buf_len);
+    if (ssl->in_buf == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", in_buf_len));
         ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
         goto error;
     }
@@ -3968,28 +1415,28 @@
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
     ssl->out_buf_len = out_buf_len;
 #endif
-    ssl->out_buf = mbedtls_calloc( 1, out_buf_len );
-    if( ssl->out_buf == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", out_buf_len ) );
+    ssl->out_buf = mbedtls_calloc(1, out_buf_len);
+    if (ssl->out_buf == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", out_buf_len));
         ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
         goto error;
     }
 
-    mbedtls_ssl_reset_in_out_pointers( ssl );
+    mbedtls_ssl_reset_in_out_pointers(ssl);
 
 #if defined(MBEDTLS_SSL_DTLS_SRTP)
-    memset( &ssl->dtls_srtp_info, 0, sizeof(ssl->dtls_srtp_info) );
+    memset(&ssl->dtls_srtp_info, 0, sizeof(ssl->dtls_srtp_info));
 #endif
 
-    if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
+    if ((ret = ssl_handshake_init(ssl)) != 0) {
         goto error;
+    }
 
-    return( 0 );
+    return 0;
 
 error:
-    mbedtls_free( ssl->in_buf );
-    mbedtls_free( ssl->out_buf );
+    mbedtls_free(ssl->in_buf);
+    mbedtls_free(ssl->out_buf);
 
     ssl->conf = NULL;
 
@@ -4012,7 +1459,7 @@
     ssl->out_iv = NULL;
     ssl->out_msg = NULL;
 
-    return( ret );
+    return ret;
 }
 
 /*
@@ -4022,9 +1469,9 @@
  * If partial is non-zero, keep data in the input buffer and client ID.
  * (Use when a DTLS client reconnects from the same port.)
  */
-int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
+void mbedtls_ssl_session_reset_msg_layer(mbedtls_ssl_context *ssl,
+                                         int partial)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
     size_t in_buf_len = ssl->in_buf_len;
     size_t out_buf_len = ssl->out_buf_len;
@@ -4033,93 +1480,101 @@
     size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
 #endif
 
-#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) ||     \
-    !defined(MBEDTLS_SSL_SRV_C)
-    ((void) partial);
+#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || !defined(MBEDTLS_SSL_SRV_C)
+    partial = 0;
 #endif
 
+    /* Cancel any possibly running timer */
+    mbedtls_ssl_set_timer(ssl, 0);
+
+    mbedtls_ssl_reset_in_out_pointers(ssl);
+
+    /* Reset incoming message parsing */
+    ssl->in_offt    = NULL;
+    ssl->nb_zero    = 0;
+    ssl->in_msgtype = 0;
+    ssl->in_msglen  = 0;
+    ssl->in_hslen   = 0;
+    ssl->keep_current_message = 0;
+    ssl->transform_in  = NULL;
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    ssl->next_record_offset = 0;
+    ssl->in_epoch = 0;
+#endif
+
+    /* Keep current datagram if partial == 1 */
+    if (partial == 0) {
+        ssl->in_left = 0;
+        memset(ssl->in_buf, 0, in_buf_len);
+    }
+
+    ssl->send_alert = 0;
+
+    /* Reset outgoing message writing */
+    ssl->out_msgtype = 0;
+    ssl->out_msglen  = 0;
+    ssl->out_left    = 0;
+    memset(ssl->out_buf, 0, out_buf_len);
+    memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr));
+    ssl->transform_out = NULL;
+
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+    mbedtls_ssl_dtls_replay_reset(ssl);
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    if (ssl->transform) {
+        mbedtls_ssl_transform_free(ssl->transform);
+        mbedtls_free(ssl->transform);
+        ssl->transform = NULL;
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    mbedtls_ssl_transform_free(ssl->transform_application);
+    mbedtls_free(ssl->transform_application);
+    ssl->transform_application = NULL;
+
+    if (ssl->handshake != NULL) {
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+        mbedtls_ssl_transform_free(ssl->handshake->transform_earlydata);
+        mbedtls_free(ssl->handshake->transform_earlydata);
+        ssl->handshake->transform_earlydata = NULL;
+#endif
+
+        mbedtls_ssl_transform_free(ssl->handshake->transform_handshake);
+        mbedtls_free(ssl->handshake->transform_handshake);
+        ssl->handshake->transform_handshake = NULL;
+    }
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+}
+
+int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
     ssl->state = MBEDTLS_SSL_HELLO_REQUEST;
 
-    /* Cancel any possibly running timer */
-    mbedtls_ssl_set_timer( ssl, 0 );
+    mbedtls_ssl_session_reset_msg_layer(ssl, partial);
 
+    /* Reset renegotiation state */
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
     ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE;
     ssl->renego_records_seen = 0;
 
     ssl->verify_data_len = 0;
-    memset( ssl->own_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN );
-    memset( ssl->peer_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN );
+    memset(ssl->own_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN);
+    memset(ssl->peer_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN);
 #endif
     ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION;
 
-    ssl->in_offt = NULL;
-    mbedtls_ssl_reset_in_out_pointers( ssl );
-
-    ssl->in_msgtype = 0;
-    ssl->in_msglen = 0;
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    ssl->next_record_offset = 0;
-    ssl->in_epoch = 0;
-#endif
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-    mbedtls_ssl_dtls_replay_reset( ssl );
-#endif
-
-    ssl->in_hslen = 0;
-    ssl->nb_zero = 0;
-
-    ssl->keep_current_message = 0;
-
-    ssl->out_msgtype = 0;
-    ssl->out_msglen = 0;
-    ssl->out_left = 0;
-#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
-    if( ssl->split_done != MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED )
-        ssl->split_done = 0;
-#endif
-
-    memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) );
-
-    ssl->transform_in = NULL;
-    ssl->transform_out = NULL;
-
-    ssl->session_in = NULL;
+    ssl->session_in  = NULL;
     ssl->session_out = NULL;
-
-    memset( ssl->out_buf, 0, out_buf_len );
-
-#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
-    if( partial == 0 )
-#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
-    {
-        ssl->in_left = 0;
-        memset( ssl->in_buf, 0, in_buf_len );
-    }
-
-#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
-    if( mbedtls_ssl_hw_record_reset != NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_reset()" ) );
-        if( ( ret = mbedtls_ssl_hw_record_reset( ssl ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_reset", ret );
-            return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-        }
-    }
-#endif
-
-    if( ssl->transform )
-    {
-        mbedtls_ssl_transform_free( ssl->transform );
-        mbedtls_free( ssl->transform );
-        ssl->transform = NULL;
-    }
-
-    if( ssl->session )
-    {
-        mbedtls_ssl_session_free( ssl->session );
-        mbedtls_free( ssl->session );
+    if (ssl->session) {
+        mbedtls_ssl_session_free(ssl->session);
+        mbedtls_free(ssl->session);
         ssl->session = NULL;
     }
 
@@ -4128,110 +1583,110 @@
 #endif
 
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
+    int free_cli_id = 1;
 #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE)
-    if( partial == 0 )
+    free_cli_id = (partial == 0);
 #endif
-    {
-        mbedtls_free( ssl->cli_id );
+    if (free_cli_id) {
+        mbedtls_free(ssl->cli_id);
         ssl->cli_id = NULL;
         ssl->cli_id_len = 0;
     }
 #endif
 
-    if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
-        return( ret );
+    if ((ret = ssl_handshake_init(ssl)) != 0) {
+        return ret;
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Reset an initialized and used SSL context for re-use while retaining
  * all application-set variables, function pointers and data.
  */
-int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl)
 {
-    return( mbedtls_ssl_session_reset_int( ssl, 0 ) );
+    return mbedtls_ssl_session_reset_int(ssl, 0);
 }
 
 /*
  * SSL set accessors
  */
-void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint )
+void mbedtls_ssl_conf_endpoint(mbedtls_ssl_config *conf, int endpoint)
 {
     conf->endpoint   = endpoint;
 }
 
-void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport )
+void mbedtls_ssl_conf_transport(mbedtls_ssl_config *conf, int transport)
 {
     conf->transport = transport;
 }
 
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode )
+void mbedtls_ssl_conf_dtls_anti_replay(mbedtls_ssl_config *conf, char mode)
 {
     conf->anti_replay = mode;
 }
 #endif
 
-#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
-void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit )
+void mbedtls_ssl_conf_dtls_badmac_limit(mbedtls_ssl_config *conf, unsigned limit)
 {
     conf->badmac_limit = limit;
 }
-#endif
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
 
-void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl,
-                                       unsigned allow_packing )
+void mbedtls_ssl_set_datagram_packing(mbedtls_ssl_context *ssl,
+                                      unsigned allow_packing)
 {
     ssl->disable_datagram_packing = !allow_packing;
 }
 
-void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf,
-                                         uint32_t min, uint32_t max )
+void mbedtls_ssl_conf_handshake_timeout(mbedtls_ssl_config *conf,
+                                        uint32_t min, uint32_t max)
 {
     conf->hs_timeout_min = min;
     conf->hs_timeout_max = max;
 }
 #endif
 
-void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode )
+void mbedtls_ssl_conf_authmode(mbedtls_ssl_config *conf, int authmode)
 {
     conf->authmode   = authmode;
 }
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
-void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf,
-                     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
-                     void *p_vrfy )
+void mbedtls_ssl_conf_verify(mbedtls_ssl_config *conf,
+                             int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+                             void *p_vrfy)
 {
     conf->f_vrfy      = f_vrfy;
     conf->p_vrfy      = p_vrfy;
 }
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
-void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf,
-                  int (*f_rng)(void *, unsigned char *, size_t),
-                  void *p_rng )
+void mbedtls_ssl_conf_rng(mbedtls_ssl_config *conf,
+                          int (*f_rng)(void *, unsigned char *, size_t),
+                          void *p_rng)
 {
     conf->f_rng      = f_rng;
     conf->p_rng      = p_rng;
 }
 
-void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf,
-                  void (*f_dbg)(void *, int, const char *, int, const char *),
-                  void  *p_dbg )
+void mbedtls_ssl_conf_dbg(mbedtls_ssl_config *conf,
+                          void (*f_dbg)(void *, int, const char *, int, const char *),
+                          void  *p_dbg)
 {
     conf->f_dbg      = f_dbg;
     conf->p_dbg      = p_dbg;
 }
 
-void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl,
-        void *p_bio,
-        mbedtls_ssl_send_t *f_send,
-        mbedtls_ssl_recv_t *f_recv,
-        mbedtls_ssl_recv_timeout_t *f_recv_timeout )
+void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl,
+                         void *p_bio,
+                         mbedtls_ssl_send_t *f_send,
+                         mbedtls_ssl_recv_t *f_recv,
+                         mbedtls_ssl_recv_timeout_t *f_recv_timeout)
 {
     ssl->p_bio          = p_bio;
     ssl->f_send         = f_send;
@@ -4240,35 +1695,35 @@
 }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu )
+void mbedtls_ssl_set_mtu(mbedtls_ssl_context *ssl, uint16_t mtu)
 {
     ssl->mtu = mtu;
 }
 #endif
 
-void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout )
+void mbedtls_ssl_conf_read_timeout(mbedtls_ssl_config *conf, uint32_t timeout)
 {
     conf->read_timeout   = timeout;
 }
 
-void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl,
-                               void *p_timer,
-                               mbedtls_ssl_set_timer_t *f_set_timer,
-                               mbedtls_ssl_get_timer_t *f_get_timer )
+void mbedtls_ssl_set_timer_cb(mbedtls_ssl_context *ssl,
+                              void *p_timer,
+                              mbedtls_ssl_set_timer_t *f_set_timer,
+                              mbedtls_ssl_get_timer_t *f_get_timer)
 {
     ssl->p_timer        = p_timer;
     ssl->f_set_timer    = f_set_timer;
     ssl->f_get_timer    = f_get_timer;
 
     /* Make sure we start with no timer running */
-    mbedtls_ssl_set_timer( ssl, 0 );
+    mbedtls_ssl_set_timer(ssl, 0);
 }
 
 #if defined(MBEDTLS_SSL_SRV_C)
-void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf,
-        void *p_cache,
-        int (*f_get_cache)(void *, mbedtls_ssl_session *),
-        int (*f_set_cache)(void *, const mbedtls_ssl_session *) )
+void mbedtls_ssl_conf_session_cache(mbedtls_ssl_config *conf,
+                                    void *p_cache,
+                                    mbedtls_ssl_cache_get_t *f_get_cache,
+                                    mbedtls_ssl_cache_set_t *f_set_cache)
 {
     conf->p_cache = p_cache;
     conf->f_get_cache = f_get_cache;
@@ -4277,99 +1732,144 @@
 #endif /* MBEDTLS_SSL_SRV_C */
 
 #if defined(MBEDTLS_SSL_CLI_C)
-int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session )
+int mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( ssl == NULL ||
+    if (ssl == NULL ||
         session == NULL ||
         ssl->session_negotiate == NULL ||
-        ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT )
-    {
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+        ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    if( ( ret = mbedtls_ssl_session_copy( ssl->session_negotiate,
-                                          session ) ) != 0 )
-        return( ret );
+    if (ssl->handshake->resume == 1) {
+        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    if (session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
+        const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+            mbedtls_ssl_ciphersuite_from_id(session->ciphersuite);
+
+        if (mbedtls_ssl_validate_ciphersuite(
+                ssl, ciphersuite_info, MBEDTLS_SSL_VERSION_TLS1_3,
+                MBEDTLS_SSL_VERSION_TLS1_3) != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(4, ("%d is not a valid TLS 1.3 ciphersuite.",
+                                      session->ciphersuite));
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+    if ((ret = mbedtls_ssl_session_copy(ssl->session_negotiate,
+                                        session)) != 0) {
+        return ret;
+    }
 
     ssl->handshake->resume = 1;
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_SSL_CLI_C */
 
-void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf,
-                                   const int *ciphersuites )
+void mbedtls_ssl_conf_ciphersuites(mbedtls_ssl_config *conf,
+                                   const int *ciphersuites)
 {
-    conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = ciphersuites;
-    conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = ciphersuites;
-    conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = ciphersuites;
-    conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = ciphersuites;
+    conf->ciphersuite_list = ciphersuites;
 }
 
-void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf,
-                                       const int *ciphersuites,
-                                       int major, int minor )
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+void mbedtls_ssl_conf_tls13_key_exchange_modes(mbedtls_ssl_config *conf,
+                                               const int kex_modes)
 {
-    if( major != MBEDTLS_SSL_MAJOR_VERSION_3 )
-        return;
-
-    if( minor < MBEDTLS_SSL_MINOR_VERSION_0 || minor > MBEDTLS_SSL_MINOR_VERSION_3 )
-        return;
-
-    conf->ciphersuite_list[minor] = ciphersuites;
+    conf->tls13_kex_modes = kex_modes & MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL;
 }
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+void mbedtls_ssl_tls13_conf_early_data(mbedtls_ssl_config *conf,
+                                       int early_data_enabled)
+{
+    conf->early_data_enabled = early_data_enabled;
+}
+
+#if defined(MBEDTLS_SSL_SRV_C)
+void mbedtls_ssl_tls13_conf_max_early_data_size(
+    mbedtls_ssl_config *conf, uint32_t max_early_data_size)
+{
+    conf->max_early_data_size = max_early_data_size;
+}
+#endif /* MBEDTLS_SSL_SRV_C */
+
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
-void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf,
-                                    const mbedtls_x509_crt_profile *profile )
+void mbedtls_ssl_conf_cert_profile(mbedtls_ssl_config *conf,
+                                   const mbedtls_x509_crt_profile *profile)
 {
     conf->cert_profile = profile;
 }
 
+static void ssl_key_cert_free(mbedtls_ssl_key_cert *key_cert)
+{
+    mbedtls_ssl_key_cert *cur = key_cert, *next;
+
+    while (cur != NULL) {
+        next = cur->next;
+        mbedtls_free(cur);
+        cur = next;
+    }
+}
+
 /* Append a new keycert entry to a (possibly empty) list */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_append_key_cert( mbedtls_ssl_key_cert **head,
-                                mbedtls_x509_crt *cert,
-                                mbedtls_pk_context *key )
+static int ssl_append_key_cert(mbedtls_ssl_key_cert **head,
+                               mbedtls_x509_crt *cert,
+                               mbedtls_pk_context *key)
 {
     mbedtls_ssl_key_cert *new_cert;
 
-    new_cert = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) );
-    if( new_cert == NULL )
-        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+    if (cert == NULL) {
+        /* Free list if cert is null */
+        ssl_key_cert_free(*head);
+        *head = NULL;
+        return 0;
+    }
+
+    new_cert = mbedtls_calloc(1, sizeof(mbedtls_ssl_key_cert));
+    if (new_cert == NULL) {
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+    }
 
     new_cert->cert = cert;
     new_cert->key  = key;
     new_cert->next = NULL;
 
-    /* Update head is the list was null, else add to the end */
-    if( *head == NULL )
-    {
+    /* Update head if the list was null, else add to the end */
+    if (*head == NULL) {
         *head = new_cert;
-    }
-    else
-    {
+    } else {
         mbedtls_ssl_key_cert *cur = *head;
-        while( cur->next != NULL )
+        while (cur->next != NULL) {
             cur = cur->next;
+        }
         cur->next = new_cert;
     }
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf,
+int mbedtls_ssl_conf_own_cert(mbedtls_ssl_config *conf,
                               mbedtls_x509_crt *own_cert,
-                              mbedtls_pk_context *pk_key )
+                              mbedtls_pk_context *pk_key)
 {
-    return( ssl_append_key_cert( &conf->key_cert, own_cert, pk_key ) );
+    return ssl_append_key_cert(&conf->key_cert, own_cert, pk_key);
 }
 
-void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf,
+void mbedtls_ssl_conf_ca_chain(mbedtls_ssl_config *conf,
                                mbedtls_x509_crt *ca_chain,
-                               mbedtls_x509_crl *ca_crl )
+                               mbedtls_x509_crl *ca_crl)
 {
     conf->ca_chain   = ca_chain;
     conf->ca_crl     = ca_crl;
@@ -4383,9 +1883,9 @@
 }
 
 #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
-void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf,
-                             mbedtls_x509_crt_ca_cb_t f_ca_cb,
-                             void *p_ca_cb )
+void mbedtls_ssl_conf_ca_cb(mbedtls_ssl_config *conf,
+                            mbedtls_x509_crt_ca_cb_t f_ca_cb,
+                            void *p_ca_cb)
 {
     conf->f_ca_cb = f_ca_cb;
     conf->p_ca_cb = p_ca_cb;
@@ -4399,33 +1899,48 @@
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl,
-                                 mbedtls_x509_crt *own_cert,
-                                 mbedtls_pk_context *pk_key )
+const unsigned char *mbedtls_ssl_get_hs_sni(mbedtls_ssl_context *ssl,
+                                            size_t *name_len)
 {
-    return( ssl_append_key_cert( &ssl->handshake->sni_key_cert,
-                                 own_cert, pk_key ) );
+    *name_len = ssl->handshake->sni_name_len;
+    return ssl->handshake->sni_name;
 }
 
-void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl,
-                                  mbedtls_x509_crt *ca_chain,
-                                  mbedtls_x509_crl *ca_crl )
+int mbedtls_ssl_set_hs_own_cert(mbedtls_ssl_context *ssl,
+                                mbedtls_x509_crt *own_cert,
+                                mbedtls_pk_context *pk_key)
+{
+    return ssl_append_key_cert(&ssl->handshake->sni_key_cert,
+                               own_cert, pk_key);
+}
+
+void mbedtls_ssl_set_hs_ca_chain(mbedtls_ssl_context *ssl,
+                                 mbedtls_x509_crt *ca_chain,
+                                 mbedtls_x509_crl *ca_crl)
 {
     ssl->handshake->sni_ca_chain   = ca_chain;
     ssl->handshake->sni_ca_crl     = ca_crl;
 }
 
-void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl,
-                                  int authmode )
+#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+void mbedtls_ssl_set_hs_dn_hints(mbedtls_ssl_context *ssl,
+                                 const mbedtls_x509_crt *crt)
+{
+    ssl->handshake->dn_hints = crt;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+
+void mbedtls_ssl_set_hs_authmode(mbedtls_ssl_context *ssl,
+                                 int authmode)
 {
     ssl->handshake->sni_authmode = authmode;
 }
 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
-void mbedtls_ssl_set_verify( mbedtls_ssl_context *ssl,
-                     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
-                     void *p_vrfy )
+void mbedtls_ssl_set_verify(mbedtls_ssl_context *ssl,
+                            int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+                            void *p_vrfy)
 {
     ssl->f_vrfy = f_vrfy;
     ssl->p_vrfy = p_vrfy;
@@ -4433,62 +1948,196 @@
 #endif
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-/*
- * Set EC J-PAKE password for current handshake
- */
-int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl,
-                                         const unsigned char *pw,
-                                         size_t pw_len )
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+static const uint8_t jpake_server_id[] = { 's', 'e', 'r', 'v', 'e', 'r' };
+static const uint8_t jpake_client_id[] = { 'c', 'l', 'i', 'e', 'n', 't' };
+
+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_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
+    const uint8_t *user = NULL;
+    size_t user_len = 0;
+    const uint8_t *peer = NULL;
+    size_t peer_len = 0;
+    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) {
+        user = jpake_server_id;
+        user_len = sizeof(jpake_server_id);
+        peer = jpake_client_id;
+        peer_len = sizeof(jpake_client_id);
+    } else {
+        user = jpake_client_id;
+        user_len = sizeof(jpake_client_id);
+        peer = jpake_server_id;
+        peer_len = sizeof(jpake_server_id);
+    }
+
+    status = psa_pake_set_user(&ssl->handshake->psa_pake_ctx, user, user_len);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = psa_pake_set_peer(&ssl->handshake->psa_pake_ctx, peer, peer_len);
+    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;
+    }
+
+    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, pw, pw_len,
+                            &ssl->handshake->psa_pake_password);
+    if (status != PSA_SUCCESS) {
+        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+    }
+
+    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);
+        psa_pake_abort(&ssl->handshake->psa_pake_ctx);
+        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+    }
+
+    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_pake_abort(&ssl->handshake->psa_pake_ctx);
+        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+    }
+
+    return 0;
+}
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+int mbedtls_ssl_set_hs_ecjpake_password(mbedtls_ssl_context *ssl,
+                                        const unsigned char *pw,
+                                        size_t pw_len)
 {
     mbedtls_ecjpake_role role;
 
-    if( ssl->handshake == NULL || ssl->conf == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl->handshake == NULL || ssl->conf == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
+    /* 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
+    } else {
         role = MBEDTLS_ECJPAKE_CLIENT;
+    }
 
-    return( mbedtls_ecjpake_setup( &ssl->handshake->ecjpake_ctx,
-                                   role,
-                                   MBEDTLS_MD_SHA256,
-                                   MBEDTLS_ECP_DP_SECP256R1,
-                                   pw, pw_len ) );
+    return mbedtls_ecjpake_setup(&ssl->handshake->ecjpake_ctx,
+                                 role,
+                                 MBEDTLS_MD_SHA256,
+                                 MBEDTLS_ECP_DP_SECP256R1,
+                                 pw, pw_len);
 }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
+int mbedtls_ssl_conf_has_static_psk(mbedtls_ssl_config const *conf)
+{
+    if (conf->psk_identity     == NULL ||
+        conf->psk_identity_len == 0) {
+        return 0;
+    }
 
-static void ssl_conf_remove_psk( mbedtls_ssl_config *conf )
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) {
+        return 1;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    if (conf->psk != NULL && conf->psk_len != 0) {
+        return 1;
+    }
+
+    return 0;
+}
+
+static void ssl_conf_remove_psk(mbedtls_ssl_config *conf)
 {
     /* Remove reference to existing PSK, if any. */
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ! mbedtls_svc_key_id_is_null( conf->psk_opaque ) )
-    {
+    if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) {
         /* The maintenance of the PSK key slot is the
          * user's responsibility. */
         conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT;
     }
-    /* This and the following branch should never
-     * be taken simultaenously as we maintain the
-     * invariant that raw and opaque PSKs are never
-     * configured simultaneously. As a safeguard,
-     * though, `else` is omitted here. */
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
-    if( conf->psk != NULL )
-    {
-        mbedtls_platform_zeroize( conf->psk, conf->psk_len );
+    if (conf->psk != NULL) {
+        mbedtls_platform_zeroize(conf->psk, conf->psk_len);
 
-        mbedtls_free( conf->psk );
+        mbedtls_free(conf->psk);
         conf->psk = NULL;
         conf->psk_len = 0;
     }
 
     /* Remove reference to PSK identity, if any. */
-    if( conf->psk_identity != NULL )
-    {
-        mbedtls_free( conf->psk_identity );
+    if (conf->psk_identity != NULL) {
+        mbedtls_free(conf->psk_identity);
         conf->psk_identity = NULL;
         conf->psk_identity_len = 0;
     }
@@ -4499,197 +2148,750 @@
  * to make a copy of it in the SSL config.
  * On failure, the PSK identity in the config remains unset. */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_conf_set_psk_identity( mbedtls_ssl_config *conf,
-                                      unsigned char const *psk_identity,
-                                      size_t psk_identity_len )
+static int ssl_conf_set_psk_identity(mbedtls_ssl_config *conf,
+                                     unsigned char const *psk_identity,
+                                     size_t psk_identity_len)
 {
     /* Identity len will be encoded on two bytes */
-    if( psk_identity               == NULL ||
-        ( psk_identity_len >> 16 ) != 0    ||
-        psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
-    {
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (psk_identity               == NULL ||
+        psk_identity_len           == 0    ||
+        (psk_identity_len >> 16) != 0    ||
+        psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    conf->psk_identity = mbedtls_calloc( 1, psk_identity_len );
-    if( conf->psk_identity == NULL )
-        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+    conf->psk_identity = mbedtls_calloc(1, psk_identity_len);
+    if (conf->psk_identity == NULL) {
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+    }
 
     conf->psk_identity_len = psk_identity_len;
-    memcpy( conf->psk_identity, psk_identity, conf->psk_identity_len );
+    memcpy(conf->psk_identity, psk_identity, conf->psk_identity_len);
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf,
-                const unsigned char *psk, size_t psk_len,
-                const unsigned char *psk_identity, size_t psk_identity_len )
+int mbedtls_ssl_conf_psk(mbedtls_ssl_config *conf,
+                         const unsigned char *psk, size_t psk_len,
+                         const unsigned char *psk_identity, size_t psk_identity_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    /* Remove opaque/raw PSK + PSK Identity */
-    ssl_conf_remove_psk( conf );
+
+    /* We currently only support one PSK, raw or opaque. */
+    if (mbedtls_ssl_conf_has_static_psk(conf)) {
+        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    }
 
     /* Check and set raw PSK */
-    if( psk == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-    if( psk_len == 0 )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-    if( psk_len > MBEDTLS_PSK_MAX_LEN )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (psk == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+    if (psk_len == 0) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+    if (psk_len > MBEDTLS_PSK_MAX_LEN) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL )
-        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+    if ((conf->psk = mbedtls_calloc(1, psk_len)) == NULL) {
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+    }
     conf->psk_len = psk_len;
-    memcpy( conf->psk, psk, conf->psk_len );
+    memcpy(conf->psk, psk, conf->psk_len);
 
     /* Check and set PSK Identity */
-    ret = ssl_conf_set_psk_identity( conf, psk_identity, psk_identity_len );
-    if( ret != 0 )
-        ssl_conf_remove_psk( conf );
+    ret = ssl_conf_set_psk_identity(conf, psk_identity, psk_identity_len);
+    if (ret != 0) {
+        ssl_conf_remove_psk(conf);
+    }
 
-    return( ret );
+    return ret;
 }
 
-static void ssl_remove_psk( mbedtls_ssl_context *ssl )
+static void ssl_remove_psk(mbedtls_ssl_context *ssl)
 {
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ! mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) )
-    {
+    if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) {
+        /* The maintenance of the external PSK key slot is the
+         * user's responsibility. */
+        if (ssl->handshake->psk_opaque_is_internal) {
+            psa_destroy_key(ssl->handshake->psk_opaque);
+            ssl->handshake->psk_opaque_is_internal = 0;
+        }
         ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT;
     }
-    else
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-    if( ssl->handshake->psk != NULL )
-    {
-        mbedtls_platform_zeroize( ssl->handshake->psk,
-                                  ssl->handshake->psk_len );
-        mbedtls_free( ssl->handshake->psk );
+#else
+    if (ssl->handshake->psk != NULL) {
+        mbedtls_platform_zeroize(ssl->handshake->psk,
+                                 ssl->handshake->psk_len);
+        mbedtls_free(ssl->handshake->psk);
         ssl->handshake->psk_len = 0;
     }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 }
 
-int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl,
-                            const unsigned char *psk, size_t psk_len )
+int mbedtls_ssl_set_hs_psk(mbedtls_ssl_context *ssl,
+                           const unsigned char *psk, size_t psk_len)
 {
-    if( psk == NULL || ssl->handshake == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_key_attributes_t key_attributes = psa_key_attributes_init();
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_algorithm_t alg = PSA_ALG_NONE;
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-    if( psk_len > MBEDTLS_PSK_MAX_LEN )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (psk == NULL || ssl->handshake == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    ssl_remove_psk( ssl );
+    if (psk_len > MBEDTLS_PSK_MAX_LEN) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL )
-        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+    ssl_remove_psk(ssl);
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {
+        if (ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384) {
+            alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384);
+        } else {
+            alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256);
+        }
+        psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
+        alg = PSA_ALG_HKDF_EXTRACT(PSA_ALG_ANY_HASH);
+        psa_set_key_usage_flags(&key_attributes,
+                                PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT);
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+    psa_set_key_algorithm(&key_attributes, alg);
+    psa_set_key_type(&key_attributes, PSA_KEY_TYPE_DERIVE);
+
+    status = psa_import_key(&key_attributes, psk, psk_len, &key);
+    if (status != PSA_SUCCESS) {
+        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+    }
+
+    /* Allow calling psa_destroy_key() on psk remove */
+    ssl->handshake->psk_opaque_is_internal = 1;
+    return mbedtls_ssl_set_hs_psk_opaque(ssl, key);
+#else
+    if ((ssl->handshake->psk = mbedtls_calloc(1, psk_len)) == NULL) {
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+    }
 
     ssl->handshake->psk_len = psk_len;
-    memcpy( ssl->handshake->psk, psk, ssl->handshake->psk_len );
+    memcpy(ssl->handshake->psk, psk, ssl->handshake->psk_len);
 
-    return( 0 );
+    return 0;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf,
-                                 psa_key_id_t psk,
-                                 const unsigned char *psk_identity,
-                                 size_t psk_identity_len )
+int mbedtls_ssl_conf_psk_opaque(mbedtls_ssl_config *conf,
+                                mbedtls_svc_key_id_t psk,
+                                const unsigned char *psk_identity,
+                                size_t psk_identity_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    /* Clear opaque/raw PSK + PSK Identity, if present. */
-    ssl_conf_remove_psk( conf );
+
+    /* We currently only support one PSK, raw or opaque. */
+    if (mbedtls_ssl_conf_has_static_psk(conf)) {
+        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    }
 
     /* Check and set opaque PSK */
-    if( mbedtls_svc_key_id_is_null( psk ) )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (mbedtls_svc_key_id_is_null(psk)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
     conf->psk_opaque = psk;
 
     /* Check and set PSK Identity */
-    ret = ssl_conf_set_psk_identity( conf, psk_identity,
-                                     psk_identity_len );
-    if( ret != 0 )
-        ssl_conf_remove_psk( conf );
+    ret = ssl_conf_set_psk_identity(conf, psk_identity,
+                                    psk_identity_len);
+    if (ret != 0) {
+        ssl_conf_remove_psk(conf);
+    }
 
-    return( ret );
+    return ret;
 }
 
-int mbedtls_ssl_set_hs_psk_opaque( mbedtls_ssl_context *ssl,
-                                   psa_key_id_t psk )
+int mbedtls_ssl_set_hs_psk_opaque(mbedtls_ssl_context *ssl,
+                                  mbedtls_svc_key_id_t psk)
 {
-    if( ( mbedtls_svc_key_id_is_null( psk ) ) ||
-        ( ssl->handshake == NULL ) )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if ((mbedtls_svc_key_id_is_null(psk)) ||
+        (ssl->handshake == NULL)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    ssl_remove_psk( ssl );
+    ssl_remove_psk(ssl);
     ssl->handshake->psk_opaque = psk;
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf,
-                     int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *,
-                     size_t),
-                     void *p_psk )
+#if defined(MBEDTLS_SSL_SRV_C)
+void mbedtls_ssl_conf_psk_cb(mbedtls_ssl_config *conf,
+                             int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *,
+                                          size_t),
+                             void *p_psk)
 {
     conf->f_psk = f_psk;
     conf->p_psk = p_psk;
 }
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+#endif /* MBEDTLS_SSL_SRV_C */
+
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+static mbedtls_ssl_mode_t mbedtls_ssl_get_base_mode(
+    psa_algorithm_t alg)
+{
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
+    if (alg == PSA_ALG_CBC_NO_PADDING) {
+        return MBEDTLS_SSL_MODE_CBC;
+    }
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
+    if (PSA_ALG_IS_AEAD(alg)) {
+        return MBEDTLS_SSL_MODE_AEAD;
+    }
+    return MBEDTLS_SSL_MODE_STREAM;
+}
+
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+
+static mbedtls_ssl_mode_t mbedtls_ssl_get_base_mode(
+    mbedtls_cipher_mode_t mode)
+{
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
+    if (mode == MBEDTLS_MODE_CBC) {
+        return MBEDTLS_SSL_MODE_CBC;
+    }
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
+
+#if defined(MBEDTLS_GCM_C) || \
+    defined(MBEDTLS_CCM_C) || \
+    defined(MBEDTLS_CHACHAPOLY_C)
+    if (mode == MBEDTLS_MODE_GCM ||
+        mode == MBEDTLS_MODE_CCM ||
+        mode == MBEDTLS_MODE_CHACHAPOLY) {
+        return MBEDTLS_SSL_MODE_AEAD;
+    }
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */
+
+    return MBEDTLS_SSL_MODE_STREAM;
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+static mbedtls_ssl_mode_t mbedtls_ssl_get_actual_mode(
+    mbedtls_ssl_mode_t base_mode,
+    int encrypt_then_mac)
+{
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+    if (encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED &&
+        base_mode == MBEDTLS_SSL_MODE_CBC) {
+        return MBEDTLS_SSL_MODE_CBC_ETM;
+    }
+#else
+    (void) encrypt_then_mac;
+#endif
+    return base_mode;
+}
+
+mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_transform(
+    const mbedtls_ssl_transform *transform)
+{
+    mbedtls_ssl_mode_t base_mode = mbedtls_ssl_get_base_mode(
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        transform->psa_alg
+#else
+        mbedtls_cipher_get_cipher_mode(&transform->cipher_ctx_enc)
+#endif
+        );
+
+    int encrypt_then_mac = 0;
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+    encrypt_then_mac = transform->encrypt_then_mac;
+#endif
+    return mbedtls_ssl_get_actual_mode(base_mode, encrypt_then_mac);
+}
+
+mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite(
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+    int encrypt_then_mac,
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
+    const mbedtls_ssl_ciphersuite_t *suite)
+{
+    mbedtls_ssl_mode_t base_mode = MBEDTLS_SSL_MODE_STREAM;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_status_t status;
+    psa_algorithm_t alg;
+    psa_key_type_t type;
+    size_t size;
+    status = mbedtls_ssl_cipher_to_psa(suite->cipher, 0, &alg, &type, &size);
+    if (status == PSA_SUCCESS) {
+        base_mode = mbedtls_ssl_get_base_mode(alg);
+    }
+#else
+    const mbedtls_cipher_info_t *cipher =
+        mbedtls_cipher_info_from_type(suite->cipher);
+    if (cipher != NULL) {
+        base_mode =
+            mbedtls_ssl_get_base_mode(
+                mbedtls_cipher_info_get_mode(cipher));
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if !defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+    int encrypt_then_mac = 0;
+#endif
+    return mbedtls_ssl_get_actual_mode(base_mode, encrypt_then_mac);
+}
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+/* Serialization of TLS 1.3 sessions:
+ *
+ *     struct {
+ *       opaque hostname<0..2^16-1>;
+ *       uint64 ticket_received;
+ *       uint32 ticket_lifetime;
+ *       opaque ticket<1..2^16-1>;
+ *     } ClientOnlyData;
+ *
+ *     struct {
+ *       uint8 endpoint;
+ *       uint8 ciphersuite[2];
+ *       uint32 ticket_age_add;
+ *       uint8 ticket_flags;
+ *       opaque resumption_key<0..255>;
+ *       select ( endpoint ) {
+ *            case client: ClientOnlyData;
+ *            case server: uint64 start_time;
+ *        };
+ *     } serialized_session_tls13;
+ *
+ */
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_session_save(const mbedtls_ssl_session *session,
+                                  unsigned char *buf,
+                                  size_t buf_len,
+                                  size_t *olen)
+{
+    unsigned char *p = buf;
+#if defined(MBEDTLS_SSL_CLI_C) && \
+    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    size_t hostname_len = (session->hostname == NULL) ?
+                          0 : strlen(session->hostname) + 1;
+#endif
+    size_t needed =   1                             /* endpoint */
+                    + 2                             /* ciphersuite */
+                    + 4                             /* ticket_age_add */
+                    + 1                             /* ticket_flags */
+                    + 1;                            /* resumption_key length */
+    *olen = 0;
+
+    if (session->resumption_key_len > MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+    needed += session->resumption_key_len;  /* resumption_key */
+
+#if defined(MBEDTLS_HAVE_TIME)
+    needed += 8; /* start_time or ticket_received */
+#endif
+
+#if defined(MBEDTLS_SSL_CLI_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+        needed +=  2                        /* hostname_len */
+                  + hostname_len;           /* hostname */
+#endif
+
+        needed +=   4                       /* ticket_lifetime */
+                  + 2;                      /* ticket_len */
+
+        /* Check size_t overflow */
+        if (session->ticket_len > SIZE_MAX - needed) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+
+        needed += session->ticket_len;      /* ticket */
+    }
+#endif /* MBEDTLS_SSL_CLI_C */
+
+    *olen = needed;
+    if (needed > buf_len) {
+        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+    }
+
+    p[0] = session->endpoint;
+    MBEDTLS_PUT_UINT16_BE(session->ciphersuite, p, 1);
+    MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 3);
+    p[7] = session->ticket_flags;
+
+    /* save resumption_key */
+    p[8] = session->resumption_key_len;
+    p += 9;
+    memcpy(p, session->resumption_key, session->resumption_key_len);
+    p += session->resumption_key_len;
+
+#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
+        MBEDTLS_PUT_UINT64_BE((uint64_t) session->start, p, 0);
+        p += 8;
+    }
+#endif /* MBEDTLS_HAVE_TIME */
+
+#if defined(MBEDTLS_SSL_CLI_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+        MBEDTLS_PUT_UINT16_BE(hostname_len, p, 0);
+        p += 2;
+        if (hostname_len > 0) {
+            /* save host name */
+            memcpy(p, session->hostname, hostname_len);
+            p += hostname_len;
+        }
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+
+#if defined(MBEDTLS_HAVE_TIME)
+        MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_received, p, 0);
+        p += 8;
+#endif
+        MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0);
+        p += 4;
+
+        MBEDTLS_PUT_UINT16_BE(session->ticket_len, p, 0);
+        p += 2;
+
+        if (session->ticket != NULL && session->ticket_len > 0) {
+            memcpy(p, session->ticket, session->ticket_len);
+            p += session->ticket_len;
+        }
+    }
+#endif /* MBEDTLS_SSL_CLI_C */
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_session_load(mbedtls_ssl_session *session,
+                                  const unsigned char *buf,
+                                  size_t len)
+{
+    const unsigned char *p = buf;
+    const unsigned char *end = buf + len;
+
+    if (end - p < 9) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+    session->endpoint = p[0];
+    session->ciphersuite = MBEDTLS_GET_UINT16_BE(p, 1);
+    session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 3);
+    session->ticket_flags = p[7];
+
+    /* load resumption_key */
+    session->resumption_key_len = p[8];
+    p += 9;
+
+    if (end - p < session->resumption_key_len) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    if (sizeof(session->resumption_key) < session->resumption_key_len) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+    memcpy(session->resumption_key, p, session->resumption_key_len);
+    p += session->resumption_key_len;
+
+#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
+        if (end - p < 8) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+        session->start = MBEDTLS_GET_UINT64_BE(p, 0);
+        p += 8;
+    }
+#endif /* MBEDTLS_HAVE_TIME */
+
+#if defined(MBEDTLS_SSL_CLI_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \
+        defined(MBEDTLS_SSL_SESSION_TICKETS)
+        size_t hostname_len;
+        /* load host name */
+        if (end - p < 2) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+        hostname_len = MBEDTLS_GET_UINT16_BE(p, 0);
+        p += 2;
+
+        if (end - p < (long int) hostname_len) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+        if (hostname_len > 0) {
+            session->hostname = mbedtls_calloc(1, hostname_len);
+            if (session->hostname == NULL) {
+                return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+            }
+            memcpy(session->hostname, p, hostname_len);
+            p += hostname_len;
+        }
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION &&
+          MBEDTLS_SSL_SESSION_TICKETS */
+
+#if defined(MBEDTLS_HAVE_TIME)
+        if (end - p < 8) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+        session->ticket_received = MBEDTLS_GET_UINT64_BE(p, 0);
+        p += 8;
+#endif
+        if (end - p < 4) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+        session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0);
+        p += 4;
+
+        if (end - p <  2) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+        session->ticket_len = MBEDTLS_GET_UINT16_BE(p, 0);
+        p += 2;
+
+        if (end - p < (long int) session->ticket_len) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+        if (session->ticket_len > 0) {
+            session->ticket = mbedtls_calloc(1, session->ticket_len);
+            if (session->ticket == NULL) {
+                return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+            }
+            memcpy(session->ticket, p, session->ticket_len);
+            p += session->ticket_len;
+        }
+    }
+#endif /* MBEDTLS_SSL_CLI_C */
+
+    return 0;
+
+}
+#else /* MBEDTLS_SSL_SESSION_TICKETS */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_session_save(const mbedtls_ssl_session *session,
+                                  unsigned char *buf,
+                                  size_t buf_len,
+                                  size_t *olen)
+{
+    ((void) session);
+    ((void) buf);
+    ((void) buf_len);
+    *olen = 0;
+    return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+}
+
+static int ssl_tls13_session_load(const mbedtls_ssl_session *session,
+                                  unsigned char *buf,
+                                  size_t buf_len)
+{
+    ((void) session);
+    ((void) buf);
+    ((void) buf_len);
+    return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+}
+#endif /* !MBEDTLS_SSL_SESSION_TICKETS */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+psa_status_t mbedtls_ssl_cipher_to_psa(mbedtls_cipher_type_t mbedtls_cipher_type,
+                                       size_t taglen,
+                                       psa_algorithm_t *alg,
+                                       psa_key_type_t *key_type,
+                                       size_t *key_size)
+{
+    switch (mbedtls_cipher_type) {
+        case MBEDTLS_CIPHER_AES_128_CBC:
+            *alg = PSA_ALG_CBC_NO_PADDING;
+            *key_type = PSA_KEY_TYPE_AES;
+            *key_size = 128;
+            break;
+        case MBEDTLS_CIPHER_AES_128_CCM:
+            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
+            *key_type = PSA_KEY_TYPE_AES;
+            *key_size = 128;
+            break;
+        case MBEDTLS_CIPHER_AES_128_GCM:
+            *alg = PSA_ALG_GCM;
+            *key_type = PSA_KEY_TYPE_AES;
+            *key_size = 128;
+            break;
+        case MBEDTLS_CIPHER_AES_192_CCM:
+            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
+            *key_type = PSA_KEY_TYPE_AES;
+            *key_size = 192;
+            break;
+        case MBEDTLS_CIPHER_AES_192_GCM:
+            *alg = PSA_ALG_GCM;
+            *key_type = PSA_KEY_TYPE_AES;
+            *key_size = 192;
+            break;
+        case MBEDTLS_CIPHER_AES_256_CBC:
+            *alg = PSA_ALG_CBC_NO_PADDING;
+            *key_type = PSA_KEY_TYPE_AES;
+            *key_size = 256;
+            break;
+        case MBEDTLS_CIPHER_AES_256_CCM:
+            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
+            *key_type = PSA_KEY_TYPE_AES;
+            *key_size = 256;
+            break;
+        case MBEDTLS_CIPHER_AES_256_GCM:
+            *alg = PSA_ALG_GCM;
+            *key_type = PSA_KEY_TYPE_AES;
+            *key_size = 256;
+            break;
+        case MBEDTLS_CIPHER_ARIA_128_CBC:
+            *alg = PSA_ALG_CBC_NO_PADDING;
+            *key_type = PSA_KEY_TYPE_ARIA;
+            *key_size = 128;
+            break;
+        case MBEDTLS_CIPHER_ARIA_128_CCM:
+            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
+            *key_type = PSA_KEY_TYPE_ARIA;
+            *key_size = 128;
+            break;
+        case MBEDTLS_CIPHER_ARIA_128_GCM:
+            *alg = PSA_ALG_GCM;
+            *key_type = PSA_KEY_TYPE_ARIA;
+            *key_size = 128;
+            break;
+        case MBEDTLS_CIPHER_ARIA_192_CCM:
+            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
+            *key_type = PSA_KEY_TYPE_ARIA;
+            *key_size = 192;
+            break;
+        case MBEDTLS_CIPHER_ARIA_192_GCM:
+            *alg = PSA_ALG_GCM;
+            *key_type = PSA_KEY_TYPE_ARIA;
+            *key_size = 192;
+            break;
+        case MBEDTLS_CIPHER_ARIA_256_CBC:
+            *alg = PSA_ALG_CBC_NO_PADDING;
+            *key_type = PSA_KEY_TYPE_ARIA;
+            *key_size = 256;
+            break;
+        case MBEDTLS_CIPHER_ARIA_256_CCM:
+            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
+            *key_type = PSA_KEY_TYPE_ARIA;
+            *key_size = 256;
+            break;
+        case MBEDTLS_CIPHER_ARIA_256_GCM:
+            *alg = PSA_ALG_GCM;
+            *key_type = PSA_KEY_TYPE_ARIA;
+            *key_size = 256;
+            break;
+        case MBEDTLS_CIPHER_CAMELLIA_128_CBC:
+            *alg = PSA_ALG_CBC_NO_PADDING;
+            *key_type = PSA_KEY_TYPE_CAMELLIA;
+            *key_size = 128;
+            break;
+        case MBEDTLS_CIPHER_CAMELLIA_128_CCM:
+            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
+            *key_type = PSA_KEY_TYPE_CAMELLIA;
+            *key_size = 128;
+            break;
+        case MBEDTLS_CIPHER_CAMELLIA_128_GCM:
+            *alg = PSA_ALG_GCM;
+            *key_type = PSA_KEY_TYPE_CAMELLIA;
+            *key_size = 128;
+            break;
+        case MBEDTLS_CIPHER_CAMELLIA_192_CCM:
+            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
+            *key_type = PSA_KEY_TYPE_CAMELLIA;
+            *key_size = 192;
+            break;
+        case MBEDTLS_CIPHER_CAMELLIA_192_GCM:
+            *alg = PSA_ALG_GCM;
+            *key_type = PSA_KEY_TYPE_CAMELLIA;
+            *key_size = 192;
+            break;
+        case MBEDTLS_CIPHER_CAMELLIA_256_CBC:
+            *alg = PSA_ALG_CBC_NO_PADDING;
+            *key_type = PSA_KEY_TYPE_CAMELLIA;
+            *key_size = 256;
+            break;
+        case MBEDTLS_CIPHER_CAMELLIA_256_CCM:
+            *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
+            *key_type = PSA_KEY_TYPE_CAMELLIA;
+            *key_size = 256;
+            break;
+        case MBEDTLS_CIPHER_CAMELLIA_256_GCM:
+            *alg = PSA_ALG_GCM;
+            *key_type = PSA_KEY_TYPE_CAMELLIA;
+            *key_size = 256;
+            break;
+        case MBEDTLS_CIPHER_CHACHA20_POLY1305:
+            *alg = PSA_ALG_CHACHA20_POLY1305;
+            *key_type = PSA_KEY_TYPE_CHACHA20;
+            *key_size = 256;
+            break;
+        case MBEDTLS_CIPHER_NULL:
+            *alg = MBEDTLS_SSL_NULL_CIPHER;
+            *key_type = 0;
+            *key_size = 0;
+            break;
+        default:
+            return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return PSA_SUCCESS;
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */
 
 #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G )
+int mbedtls_ssl_conf_dh_param_bin(mbedtls_ssl_config *conf,
+                                  const unsigned char *dhm_P, size_t P_len,
+                                  const unsigned char *dhm_G, size_t G_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( ( ret = mbedtls_mpi_read_string( &conf->dhm_P, 16, dhm_P ) ) != 0 ||
-        ( ret = mbedtls_mpi_read_string( &conf->dhm_G, 16, dhm_G ) ) != 0 )
-    {
-        mbedtls_mpi_free( &conf->dhm_P );
-        mbedtls_mpi_free( &conf->dhm_G );
-        return( ret );
+    mbedtls_mpi_free(&conf->dhm_P);
+    mbedtls_mpi_free(&conf->dhm_G);
+
+    if ((ret = mbedtls_mpi_read_binary(&conf->dhm_P, dhm_P, P_len)) != 0 ||
+        (ret = mbedtls_mpi_read_binary(&conf->dhm_G, dhm_G, G_len)) != 0) {
+        mbedtls_mpi_free(&conf->dhm_P);
+        mbedtls_mpi_free(&conf->dhm_G);
+        return ret;
     }
 
-    return( 0 );
-}
-#endif /* MBEDTLS_DEPRECATED_REMOVED */
-
-int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf,
-                                   const unsigned char *dhm_P, size_t P_len,
-                                   const unsigned char *dhm_G, size_t G_len )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    mbedtls_mpi_free( &conf->dhm_P );
-    mbedtls_mpi_free( &conf->dhm_G );
-
-    if( ( ret = mbedtls_mpi_read_binary( &conf->dhm_P, dhm_P, P_len ) ) != 0 ||
-        ( ret = mbedtls_mpi_read_binary( &conf->dhm_G, dhm_G, G_len ) ) != 0 )
-    {
-        mbedtls_mpi_free( &conf->dhm_P );
-        mbedtls_mpi_free( &conf->dhm_G );
-        return( ret );
-    }
-
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx )
+int mbedtls_ssl_conf_dh_param_ctx(mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    mbedtls_mpi_free( &conf->dhm_P );
-    mbedtls_mpi_free( &conf->dhm_G );
+    mbedtls_mpi_free(&conf->dhm_P);
+    mbedtls_mpi_free(&conf->dhm_G);
 
-    if( ( ret = mbedtls_mpi_copy( &conf->dhm_P, &dhm_ctx->P ) ) != 0 ||
-        ( ret = mbedtls_mpi_copy( &conf->dhm_G, &dhm_ctx->G ) ) != 0 )
-    {
-        mbedtls_mpi_free( &conf->dhm_P );
-        mbedtls_mpi_free( &conf->dhm_G );
-        return( ret );
+    if ((ret = mbedtls_dhm_get_value(dhm_ctx, MBEDTLS_DHM_PARAM_P,
+                                     &conf->dhm_P)) != 0 ||
+        (ret = mbedtls_dhm_get_value(dhm_ctx, MBEDTLS_DHM_PARAM_G,
+                                     &conf->dhm_G)) != 0) {
+        mbedtls_mpi_free(&conf->dhm_P);
+        mbedtls_mpi_free(&conf->dhm_G);
+        return ret;
     }
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_SRV_C */
 
@@ -4697,86 +2899,115 @@
 /*
  * Set the minimum length for Diffie-Hellman parameters
  */
-void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf,
-                                      unsigned int bitlen )
+void mbedtls_ssl_conf_dhm_min_bitlen(mbedtls_ssl_config *conf,
+                                     unsigned int bitlen)
 {
     conf->dhm_min_bitlen = bitlen;
 }
 #endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */
 
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED) && defined(MBEDTLS_SSL_PROTO_TLS1_2)
 /*
  * Set allowed/preferred hashes for handshake signatures
  */
-void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf,
-                                  const int *hashes )
+void mbedtls_ssl_conf_sig_hashes(mbedtls_ssl_config *conf,
+                                 const int *hashes)
 {
     conf->sig_hashes = hashes;
 }
-#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+#endif /* !MBEDTLS_DEPRECATED_REMOVED && MBEDTLS_SSL_PROTO_TLS1_2 */
+
+/* Configure allowed signature algorithms for handshake */
+void mbedtls_ssl_conf_sig_algs(mbedtls_ssl_config *conf,
+                               const uint16_t *sig_algs)
+{
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+    conf->sig_hashes = NULL;
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+    conf->sig_algs = sig_algs;
+}
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
 
 #if defined(MBEDTLS_ECP_C)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
 /*
  * Set the allowed elliptic curves
+ *
+ * mbedtls_ssl_setup() takes the provided list
+ * and translates it to a list of IANA TLS group identifiers,
+ * stored in ssl->handshake->group_list.
+ *
  */
-void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf,
-                             const mbedtls_ecp_group_id *curve_list )
+void mbedtls_ssl_conf_curves(mbedtls_ssl_config *conf,
+                             const mbedtls_ecp_group_id *curve_list)
 {
     conf->curve_list = curve_list;
+    conf->group_list = NULL;
 }
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
 #endif /* MBEDTLS_ECP_C */
 
+/*
+ * Set the allowed groups
+ */
+void mbedtls_ssl_conf_groups(mbedtls_ssl_config *conf,
+                             const uint16_t *group_list)
+{
+#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
+    conf->curve_list = NULL;
+#endif
+    conf->group_list = group_list;
+}
+
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
-int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname )
+int mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname)
 {
     /* Initialize to suppress unnecessary compiler warning */
     size_t hostname_len = 0;
 
     /* Check if new hostname is valid before
      * making any change to current one */
-    if( hostname != NULL )
-    {
-        hostname_len = strlen( hostname );
+    if (hostname != NULL) {
+        hostname_len = strlen(hostname);
 
-        if( hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN )
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+        if (hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
     }
 
     /* Now it's clear that we will overwrite the old hostname,
      * so we can free it safely */
 
-    if( ssl->hostname != NULL )
-    {
-        mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) );
-        mbedtls_free( ssl->hostname );
+    if (ssl->hostname != NULL) {
+        mbedtls_platform_zeroize(ssl->hostname, strlen(ssl->hostname));
+        mbedtls_free(ssl->hostname);
     }
 
     /* Passing NULL as hostname shall clear the old one */
 
-    if( hostname == NULL )
-    {
+    if (hostname == NULL) {
         ssl->hostname = NULL;
-    }
-    else
-    {
-        ssl->hostname = mbedtls_calloc( 1, hostname_len + 1 );
-        if( ssl->hostname == NULL )
-            return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+    } else {
+        ssl->hostname = mbedtls_calloc(1, hostname_len + 1);
+        if (ssl->hostname == NULL) {
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        }
 
-        memcpy( ssl->hostname, hostname, hostname_len );
+        memcpy(ssl->hostname, hostname, hostname_len);
 
         ssl->hostname[hostname_len] = '\0';
     }
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf,
-                  int (*f_sni)(void *, mbedtls_ssl_context *,
-                                const unsigned char *, size_t),
-                  void *p_sni )
+void mbedtls_ssl_conf_sni(mbedtls_ssl_config *conf,
+                          int (*f_sni)(void *, mbedtls_ssl_context *,
+                                       const unsigned char *, size_t),
+                          void *p_sni)
 {
     conf->f_sni = f_sni;
     conf->p_sni = p_sni;
@@ -4784,7 +3015,7 @@
 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
 
 #if defined(MBEDTLS_SSL_ALPN)
-int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos )
+int mbedtls_ssl_conf_alpn_protocols(mbedtls_ssl_config *conf, const char **protos)
 {
     size_t cur_len, tot_len;
     const char **p;
@@ -4795,221 +3026,191 @@
      * We check lengths now rather than later.
      */
     tot_len = 0;
-    for( p = protos; *p != NULL; p++ )
-    {
-        cur_len = strlen( *p );
+    for (p = protos; *p != NULL; p++) {
+        cur_len = strlen(*p);
         tot_len += cur_len;
 
-        if( ( cur_len == 0 ) ||
-            ( cur_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN ) ||
-            ( tot_len > MBEDTLS_SSL_MAX_ALPN_LIST_LEN ) )
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+        if ((cur_len == 0) ||
+            (cur_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN) ||
+            (tot_len > MBEDTLS_SSL_MAX_ALPN_LIST_LEN)) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
     }
 
     conf->alpn_list = protos;
 
-    return( 0 );
+    return 0;
 }
 
-const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl )
+const char *mbedtls_ssl_get_alpn_protocol(const mbedtls_ssl_context *ssl)
 {
-    return( ssl->alpn_chosen );
+    return ssl->alpn_chosen;
 }
 #endif /* MBEDTLS_SSL_ALPN */
 
 #if defined(MBEDTLS_SSL_DTLS_SRTP)
-void mbedtls_ssl_conf_srtp_mki_value_supported( mbedtls_ssl_config *conf,
-                                                int support_mki_value )
+void mbedtls_ssl_conf_srtp_mki_value_supported(mbedtls_ssl_config *conf,
+                                               int support_mki_value)
 {
     conf->dtls_srtp_mki_support = support_mki_value;
 }
 
-int mbedtls_ssl_dtls_srtp_set_mki_value( mbedtls_ssl_context *ssl,
-                                         unsigned char *mki_value,
-                                         uint16_t mki_len )
+int mbedtls_ssl_dtls_srtp_set_mki_value(mbedtls_ssl_context *ssl,
+                                        unsigned char *mki_value,
+                                        uint16_t mki_len)
 {
-    if( mki_len > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH )
-    {
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (mki_len > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED )
-    {
-        return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+    if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED) {
+        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
     }
 
-    memcpy( ssl->dtls_srtp_info.mki_value, mki_value, mki_len );
+    memcpy(ssl->dtls_srtp_info.mki_value, mki_value, mki_len);
     ssl->dtls_srtp_info.mki_len = mki_len;
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_ssl_conf_dtls_srtp_protection_profiles( mbedtls_ssl_config *conf,
-                                                    const mbedtls_ssl_srtp_profile *profiles )
+int mbedtls_ssl_conf_dtls_srtp_protection_profiles(mbedtls_ssl_config *conf,
+                                                   const mbedtls_ssl_srtp_profile *profiles)
 {
     const mbedtls_ssl_srtp_profile *p;
     size_t list_size = 0;
 
     /* check the profiles list: all entry must be valid,
      * its size cannot be more than the total number of supported profiles, currently 4 */
-    for( p = profiles; *p != MBEDTLS_TLS_SRTP_UNSET &&
-                       list_size <= MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH;
-         p++ )
-    {
-        if( mbedtls_ssl_check_srtp_profile_value( *p ) != MBEDTLS_TLS_SRTP_UNSET )
-        {
+    for (p = profiles; *p != MBEDTLS_TLS_SRTP_UNSET &&
+         list_size <= MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH;
+         p++) {
+        if (mbedtls_ssl_check_srtp_profile_value(*p) != MBEDTLS_TLS_SRTP_UNSET) {
             list_size++;
-        }
-        else
-        {
+        } else {
             /* unsupported value, stop parsing and set the size to an error value */
             list_size = MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH + 1;
         }
     }
 
-    if( list_size > MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH )
-    {
-                conf->dtls_srtp_profile_list = NULL;
-                conf->dtls_srtp_profile_list_len = 0;
-                return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (list_size > MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH) {
+        conf->dtls_srtp_profile_list = NULL;
+        conf->dtls_srtp_profile_list_len = 0;
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
     conf->dtls_srtp_profile_list = profiles;
     conf->dtls_srtp_profile_list_len = list_size;
 
-    return( 0 );
+    return 0;
 }
 
-void mbedtls_ssl_get_dtls_srtp_negotiation_result( const mbedtls_ssl_context *ssl,
-                                                   mbedtls_dtls_srtp_info *dtls_srtp_info )
+void mbedtls_ssl_get_dtls_srtp_negotiation_result(const mbedtls_ssl_context *ssl,
+                                                  mbedtls_dtls_srtp_info *dtls_srtp_info)
 {
     dtls_srtp_info->chosen_dtls_srtp_profile = ssl->dtls_srtp_info.chosen_dtls_srtp_profile;
     /* do not copy the mki value if there is no chosen profile */
-    if( dtls_srtp_info->chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET )
-    {
+    if (dtls_srtp_info->chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET) {
         dtls_srtp_info->mki_len = 0;
-    }
-    else
-    {
+    } else {
         dtls_srtp_info->mki_len = ssl->dtls_srtp_info.mki_len;
-        memcpy( dtls_srtp_info->mki_value, ssl->dtls_srtp_info.mki_value,
-                ssl->dtls_srtp_info.mki_len );
+        memcpy(dtls_srtp_info->mki_value, ssl->dtls_srtp_info.mki_value,
+               ssl->dtls_srtp_info.mki_len);
     }
 }
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
 
-void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor )
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+void mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, int major, int minor)
 {
-    conf->max_major_ver = major;
-    conf->max_minor_ver = minor;
+    conf->max_tls_version = (major << 8) | minor;
 }
 
-void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor )
+void mbedtls_ssl_conf_min_version(mbedtls_ssl_config *conf, int major, int minor)
 {
-    conf->min_major_ver = major;
-    conf->min_minor_ver = minor;
+    conf->min_tls_version = (major << 8) | minor;
 }
-
-#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C)
-void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback )
-{
-    conf->fallback = fallback;
-}
-#endif
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
 
 #if defined(MBEDTLS_SSL_SRV_C)
-void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf,
-                                          char cert_req_ca_list )
+void mbedtls_ssl_conf_cert_req_ca_list(mbedtls_ssl_config *conf,
+                                       char cert_req_ca_list)
 {
     conf->cert_req_ca_list = cert_req_ca_list;
 }
 #endif
 
 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm )
+void mbedtls_ssl_conf_encrypt_then_mac(mbedtls_ssl_config *conf, char etm)
 {
     conf->encrypt_then_mac = etm;
 }
 #endif
 
 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems )
+void mbedtls_ssl_conf_extended_master_secret(mbedtls_ssl_config *conf, char ems)
 {
     conf->extended_ms = ems;
 }
 #endif
 
-#if defined(MBEDTLS_ARC4_C)
-void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 )
-{
-    conf->arc4_disabled = arc4;
-}
-#endif
-
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code )
+int mbedtls_ssl_conf_max_frag_len(mbedtls_ssl_config *conf, unsigned char mfl_code)
 {
-    if( mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ||
-        ssl_mfl_code_to_length( mfl_code ) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN )
-    {
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ||
+        ssl_mfl_code_to_length(mfl_code) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
     conf->mfl_code = mfl_code;
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
 
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate )
-{
-    conf->trunc_hmac = truncate;
-}
-#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
-
-#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
-void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split )
-{
-    conf->cbc_record_splitting = split;
-}
-#endif
-
-void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy )
+void mbedtls_ssl_conf_legacy_renegotiation(mbedtls_ssl_config *conf, int allow_legacy)
 {
     conf->allow_legacy_renegotiation = allow_legacy;
 }
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
-void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation )
+void mbedtls_ssl_conf_renegotiation(mbedtls_ssl_config *conf, int renegotiation)
 {
     conf->disable_renegotiation = renegotiation;
 }
 
-void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records )
+void mbedtls_ssl_conf_renegotiation_enforced(mbedtls_ssl_config *conf, int max_records)
 {
     conf->renego_max_records = max_records;
 }
 
-void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf,
-                                   const unsigned char period[8] )
+void mbedtls_ssl_conf_renegotiation_period(mbedtls_ssl_config *conf,
+                                           const unsigned char period[8])
 {
-    memcpy( conf->renego_period, period, 8 );
+    memcpy(conf->renego_period, period, 8);
 }
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
 #if defined(MBEDTLS_SSL_CLI_C)
-void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets )
+void mbedtls_ssl_conf_session_tickets(mbedtls_ssl_config *conf, int use_tickets)
 {
     conf->session_tickets = use_tickets;
 }
 #endif
 
 #if defined(MBEDTLS_SSL_SRV_C)
-void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf,
-        mbedtls_ssl_ticket_write_t *f_ticket_write,
-        mbedtls_ssl_ticket_parse_t *f_ticket_parse,
-        void *p_ticket )
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)
+void mbedtls_ssl_conf_new_session_tickets(mbedtls_ssl_config *conf,
+                                          uint16_t num_tickets)
+{
+    conf->new_session_tickets_count = num_tickets;
+}
+#endif
+
+void mbedtls_ssl_conf_session_tickets_cb(mbedtls_ssl_config *conf,
+                                         mbedtls_ssl_ticket_write_t *f_ticket_write,
+                                         mbedtls_ssl_ticket_parse_t *f_ticket_parse,
+                                         void *p_ticket)
 {
     conf->f_ticket_write = f_ticket_write;
     conf->f_ticket_parse = f_ticket_parse;
@@ -5018,24 +3219,14 @@
 #endif
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
-void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf,
-        mbedtls_ssl_export_keys_t *f_export_keys,
-        void *p_export_keys )
+void mbedtls_ssl_set_export_keys_cb(mbedtls_ssl_context *ssl,
+                                    mbedtls_ssl_export_keys_t *f_export_keys,
+                                    void *p_export_keys)
 {
-    conf->f_export_keys = f_export_keys;
-    conf->p_export_keys = p_export_keys;
+    ssl->f_export_keys = f_export_keys;
+    ssl->p_export_keys = p_export_keys;
 }
 
-void mbedtls_ssl_conf_export_keys_ext_cb( mbedtls_ssl_config *conf,
-        mbedtls_ssl_export_keys_ext_t *f_export_keys_ext,
-        void *p_export_keys )
-{
-    conf->f_export_keys_ext = f_export_keys_ext;
-    conf->p_export_keys = p_export_keys;
-}
-#endif
-
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
 void mbedtls_ssl_conf_async_private_cb(
     mbedtls_ssl_config *conf,
@@ -5043,7 +3234,7 @@
     mbedtls_ssl_async_decrypt_t *f_async_decrypt,
     mbedtls_ssl_async_resume_t *f_async_resume,
     mbedtls_ssl_async_cancel_t *f_async_cancel,
-    void *async_config_data )
+    void *async_config_data)
 {
     conf->f_async_sign_start = f_async_sign;
     conf->f_async_decrypt_start = f_async_decrypt;
@@ -5052,178 +3243,168 @@
     conf->p_async_config_data = async_config_data;
 }
 
-void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf )
+void *mbedtls_ssl_conf_get_async_config_data(const mbedtls_ssl_config *conf)
 {
-    return( conf->p_async_config_data );
+    return conf->p_async_config_data;
 }
 
-void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl )
+void *mbedtls_ssl_get_async_operation_data(const mbedtls_ssl_context *ssl)
 {
-    if( ssl->handshake == NULL )
-        return( NULL );
-    else
-        return( ssl->handshake->user_async_ctx );
+    if (ssl->handshake == NULL) {
+        return NULL;
+    } else {
+        return ssl->handshake->user_async_ctx;
+    }
 }
 
-void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl,
-                                 void *ctx )
+void mbedtls_ssl_set_async_operation_data(mbedtls_ssl_context *ssl,
+                                          void *ctx)
 {
-    if( ssl->handshake != NULL )
+    if (ssl->handshake != NULL) {
         ssl->handshake->user_async_ctx = ctx;
+    }
 }
 #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
 
 /*
  * SSL get accessors
  */
-uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl )
+uint32_t mbedtls_ssl_get_verify_result(const mbedtls_ssl_context *ssl)
 {
-    if( ssl->session != NULL )
-        return( ssl->session->verify_result );
+    if (ssl->session != NULL) {
+        return ssl->session->verify_result;
+    }
 
-    if( ssl->session_negotiate != NULL )
-        return( ssl->session_negotiate->verify_result );
+    if (ssl->session_negotiate != NULL) {
+        return ssl->session_negotiate->verify_result;
+    }
 
-    return( 0xFFFFFFFF );
+    return 0xFFFFFFFF;
 }
 
-const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl )
+int mbedtls_ssl_get_ciphersuite_id_from_ssl(const mbedtls_ssl_context *ssl)
 {
-    if( ssl == NULL || ssl->session == NULL )
-        return( NULL );
+    if (ssl == NULL || ssl->session == NULL) {
+        return 0;
+    }
 
-    return mbedtls_ssl_get_ciphersuite_name( ssl->session->ciphersuite );
+    return ssl->session->ciphersuite;
 }
 
-const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl )
+const char *mbedtls_ssl_get_ciphersuite(const mbedtls_ssl_context *ssl)
+{
+    if (ssl == NULL || ssl->session == NULL) {
+        return NULL;
+    }
+
+    return mbedtls_ssl_get_ciphersuite_name(ssl->session->ciphersuite);
+}
+
+const char *mbedtls_ssl_get_version(const mbedtls_ssl_context *ssl)
 {
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        switch( ssl->minor_ver )
-        {
-            case MBEDTLS_SSL_MINOR_VERSION_2:
-                return( "DTLSv1.0" );
-
-            case MBEDTLS_SSL_MINOR_VERSION_3:
-                return( "DTLSv1.2" );
-
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        switch (ssl->tls_version) {
+            case MBEDTLS_SSL_VERSION_TLS1_2:
+                return "DTLSv1.2";
             default:
-                return( "unknown (DTLS)" );
+                return "unknown (DTLS)";
         }
     }
 #endif
 
-    switch( ssl->minor_ver )
-    {
-        case MBEDTLS_SSL_MINOR_VERSION_0:
-            return( "SSLv3.0" );
-
-        case MBEDTLS_SSL_MINOR_VERSION_1:
-            return( "TLSv1.0" );
-
-        case MBEDTLS_SSL_MINOR_VERSION_2:
-            return( "TLSv1.1" );
-
-        case MBEDTLS_SSL_MINOR_VERSION_3:
-            return( "TLSv1.2" );
-
+    switch (ssl->tls_version) {
+        case MBEDTLS_SSL_VERSION_TLS1_2:
+            return "TLSv1.2";
+        case MBEDTLS_SSL_VERSION_TLS1_3:
+            return "TLSv1.3";
         default:
-            return( "unknown" );
+            return "unknown";
     }
 }
 
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-size_t mbedtls_ssl_get_input_max_frag_len( const mbedtls_ssl_context *ssl )
+size_t mbedtls_ssl_get_input_max_frag_len(const mbedtls_ssl_context *ssl)
 {
-    size_t max_len = MBEDTLS_SSL_MAX_CONTENT_LEN;
+    size_t max_len = MBEDTLS_SSL_IN_CONTENT_LEN;
     size_t read_mfl;
 
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
     /* Use the configured MFL for the client if we're past SERVER_HELLO_DONE */
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
-        ssl->state >= MBEDTLS_SSL_SERVER_HELLO_DONE )
-    {
-        return ssl_mfl_code_to_length( ssl->conf->mfl_code );
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
+        ssl->state >= MBEDTLS_SSL_SERVER_HELLO_DONE) {
+        return ssl_mfl_code_to_length(ssl->conf->mfl_code);
     }
+#endif
 
     /* Check if a smaller max length was negotiated */
-    if( ssl->session_out != NULL )
-    {
-        read_mfl = ssl_mfl_code_to_length( ssl->session_out->mfl_code );
-        if( read_mfl < max_len )
-        {
+    if (ssl->session_out != NULL) {
+        read_mfl = ssl_mfl_code_to_length(ssl->session_out->mfl_code);
+        if (read_mfl < max_len) {
             max_len = read_mfl;
         }
     }
 
-    // During a handshake, use the value being negotiated
-    if( ssl->session_negotiate != NULL )
-    {
-        read_mfl = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code );
-        if( read_mfl < max_len )
-        {
+    /* During a handshake, use the value being negotiated */
+    if (ssl->session_negotiate != NULL) {
+        read_mfl = ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code);
+        if (read_mfl < max_len) {
             max_len = read_mfl;
         }
     }
 
-    return( max_len );
+    return max_len;
 }
 
-size_t mbedtls_ssl_get_output_max_frag_len( const mbedtls_ssl_context *ssl )
+size_t mbedtls_ssl_get_output_max_frag_len(const mbedtls_ssl_context *ssl)
 {
     size_t max_len;
 
     /*
      * Assume mfl_code is correct since it was checked when set
      */
-    max_len = ssl_mfl_code_to_length( ssl->conf->mfl_code );
+    max_len = ssl_mfl_code_to_length(ssl->conf->mfl_code);
 
     /* Check if a smaller max length was negotiated */
-    if( ssl->session_out != NULL &&
-        ssl_mfl_code_to_length( ssl->session_out->mfl_code ) < max_len )
-    {
-        max_len = ssl_mfl_code_to_length( ssl->session_out->mfl_code );
+    if (ssl->session_out != NULL &&
+        ssl_mfl_code_to_length(ssl->session_out->mfl_code) < max_len) {
+        max_len = ssl_mfl_code_to_length(ssl->session_out->mfl_code);
     }
 
     /* During a handshake, use the value being negotiated */
-    if( ssl->session_negotiate != NULL &&
-        ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ) < max_len )
-    {
-        max_len = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code );
+    if (ssl->session_negotiate != NULL &&
+        ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code) < max_len) {
+        max_len = ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code);
     }
 
-    return( max_len );
+    return max_len;
 }
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl )
-{
-    return mbedtls_ssl_get_output_max_frag_len( ssl );
-}
-#endif /* !MBEDTLS_DEPRECATED_REMOVED */
 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-size_t mbedtls_ssl_get_current_mtu( const mbedtls_ssl_context *ssl )
+size_t mbedtls_ssl_get_current_mtu(const mbedtls_ssl_context *ssl)
 {
     /* Return unlimited mtu for client hello messages to avoid fragmentation. */
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
-        ( ssl->state == MBEDTLS_SSL_CLIENT_HELLO ||
-          ssl->state == MBEDTLS_SSL_SERVER_HELLO ) )
-        return ( 0 );
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
+        (ssl->state == MBEDTLS_SSL_CLIENT_HELLO ||
+         ssl->state == MBEDTLS_SSL_SERVER_HELLO)) {
+        return 0;
+    }
 
-    if( ssl->handshake == NULL || ssl->handshake->mtu == 0 )
-        return( ssl->mtu );
+    if (ssl->handshake == NULL || ssl->handshake->mtu == 0) {
+        return ssl->mtu;
+    }
 
-    if( ssl->mtu == 0 )
-        return( ssl->handshake->mtu );
+    if (ssl->mtu == 0) {
+        return ssl->handshake->mtu;
+    }
 
-    return( ssl->mtu < ssl->handshake->mtu ?
-            ssl->mtu : ssl->handshake->mtu );
+    return ssl->mtu < ssl->handshake->mtu ?
+           ssl->mtu : ssl->handshake->mtu;
 }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl )
+int mbedtls_ssl_get_max_out_record_payload(const mbedtls_ssl_context *ssl)
 {
     size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
 
@@ -5233,30 +3414,31 @@
 #endif
 
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-    const size_t mfl = mbedtls_ssl_get_output_max_frag_len( ssl );
+    const size_t mfl = mbedtls_ssl_get_output_max_frag_len(ssl);
 
-    if( max_len > mfl )
+    if (max_len > mfl) {
         max_len = mfl;
+    }
 #endif
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( mbedtls_ssl_get_current_mtu( ssl ) != 0 )
-    {
-        const size_t mtu = mbedtls_ssl_get_current_mtu( ssl );
-        const int ret = mbedtls_ssl_get_record_expansion( ssl );
+    if (mbedtls_ssl_get_current_mtu(ssl) != 0) {
+        const size_t mtu = mbedtls_ssl_get_current_mtu(ssl);
+        const int ret = mbedtls_ssl_get_record_expansion(ssl);
         const size_t overhead = (size_t) ret;
 
-        if( ret < 0 )
-            return( ret );
-
-        if( mtu <= overhead )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "MTU too low for record expansion" ) );
-            return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+        if (ret < 0) {
+            return ret;
         }
 
-        if( max_len > mtu - overhead )
+        if (mtu <= overhead) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("MTU too low for record expansion"));
+            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+        }
+
+        if (max_len > mtu - overhead) {
             max_len = mtu - overhead;
+        }
     }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
@@ -5265,47 +3447,82 @@
     ((void) ssl);
 #endif
 
-    return( (int) max_len );
+    return (int) max_len;
+}
+
+int mbedtls_ssl_get_max_in_record_payload(const mbedtls_ssl_context *ssl)
+{
+    size_t max_len = MBEDTLS_SSL_IN_CONTENT_LEN;
+
+#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+    (void) ssl;
+#endif
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+    const size_t mfl = mbedtls_ssl_get_input_max_frag_len(ssl);
+
+    if (max_len > mfl) {
+        max_len = mfl;
+    }
+#endif
+
+    return (int) max_len;
 }
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
-const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl )
+const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert(const mbedtls_ssl_context *ssl)
 {
-    if( ssl == NULL || ssl->session == NULL )
-        return( NULL );
+    if (ssl == NULL || ssl->session == NULL) {
+        return NULL;
+    }
 
 #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    return( ssl->session->peer_cert );
+    return ssl->session->peer_cert;
 #else
-    return( NULL );
+    return NULL;
 #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 }
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
 #if defined(MBEDTLS_SSL_CLI_C)
-int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl,
-                             mbedtls_ssl_session *dst )
+int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl,
+                            mbedtls_ssl_session *dst)
 {
-    if( ssl == NULL ||
+    int ret;
+
+    if (ssl == NULL ||
         dst == NULL ||
         ssl->session == NULL ||
-        ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT )
-    {
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+        ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    return( mbedtls_ssl_session_copy( dst, ssl->session ) );
+    /* Since Mbed TLS 3.0, mbedtls_ssl_get_session() is no longer
+     * idempotent: Each session can only be exported once.
+     *
+     * (This is in preparation for TLS 1.3 support where we will
+     * need the ability to export multiple sessions (aka tickets),
+     * which will be achieved by calling mbedtls_ssl_get_session()
+     * multiple times until it fails.)
+     *
+     * Check whether we have already exported the current session,
+     * and fail if so.
+     */
+    if (ssl->session->exported == 1) {
+        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    }
+
+    ret = mbedtls_ssl_session_copy(dst, ssl->session);
+    if (ret != 0) {
+        return ret;
+    }
+
+    /* Remember that we've exported the session. */
+    ssl->session->exported = 1;
+    return 0;
 }
 #endif /* MBEDTLS_SSL_CLI_C */
 
-const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_context *ssl )
-{
-    if( ssl == NULL )
-        return( NULL );
-
-    return( ssl->session );
-}
-
 /*
  * Define ticket header determining Mbed TLS version
  * and structure of the ticket.
@@ -5340,12 +3557,6 @@
 #define SSL_SERIALIZED_SESSION_CONFIG_MFL 0
 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
 
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC 1
-#else
-#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC 0
-#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
-
 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
 #define SSL_SERIALIZED_SESSION_CONFIG_ETM 1
 #else
@@ -5362,254 +3573,142 @@
 #define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT           1
 #define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 2
 #define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT           3
-#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT    4
-#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT           5
-#define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT        6
+#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT           4
+#define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT        5
 
 #define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG                           \
-    ( (uint16_t) (                                                      \
-        ( SSL_SERIALIZED_SESSION_CONFIG_TIME          << SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT          ) | \
-        ( SSL_SERIALIZED_SESSION_CONFIG_CRT           << SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT           ) | \
-        ( SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET << SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT ) | \
-        ( SSL_SERIALIZED_SESSION_CONFIG_MFL           << SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT           ) | \
-        ( SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC    << SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT    ) | \
-        ( SSL_SERIALIZED_SESSION_CONFIG_ETM           << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT           ) | \
-        ( SSL_SERIALIZED_SESSION_CONFIG_TICKET        << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT        ) ) )
+    ((uint16_t) (                                                      \
+         (SSL_SERIALIZED_SESSION_CONFIG_TIME << SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT) | \
+         (SSL_SERIALIZED_SESSION_CONFIG_CRT << SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT) | \
+         (SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET << \
+             SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT) | \
+         (SSL_SERIALIZED_SESSION_CONFIG_MFL << SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT) | \
+         (SSL_SERIALIZED_SESSION_CONFIG_ETM << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT) | \
+         (SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT)))
 
 static unsigned char ssl_serialized_session_header[] = {
     MBEDTLS_VERSION_MAJOR,
     MBEDTLS_VERSION_MINOR,
     MBEDTLS_VERSION_PATCH,
-    MBEDTLS_BYTE_1( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG ),
-    MBEDTLS_BYTE_0( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG ),
+    MBEDTLS_BYTE_1(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG),
+    MBEDTLS_BYTE_0(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG),
 };
 
 /*
  * Serialize a session in the following format:
  * (in the presentation language of TLS, RFC 8446 section 3)
  *
- *  opaque mbedtls_version[3];   // major, minor, patch
- *  opaque session_format[2];    // version-specific 16-bit field determining
- *                               // the format of the remaining
- *                               // serialized data.
+ *  struct {
  *
- *  Note: When updating the format, remember to keep
- *        these version+format bytes.
+ *    opaque mbedtls_version[3];   // library version: major, minor, patch
+ *    opaque session_format[2];    // library-version specific 16-bit field
+ *                                 // determining the format of the remaining
+ *                                 // serialized data.
  *
- *                               // In this version, `session_format` determines
- *                               // the setting of those compile-time
- *                               // configuration options which influence
- *                               // the structure of mbedtls_ssl_session.
- *  uint64 start_time;
- *  uint8 ciphersuite[2];        // defined by the standard
- *  uint8 compression;           // 0 or 1
- *  uint8 session_id_len;        // at most 32
- *  opaque session_id[32];
- *  opaque master[48];           // fixed length in the standard
- *  uint32 verify_result;
- *  opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
- *  opaque ticket<0..2^24-1>;    // length 0 means no ticket
- *  uint32 ticket_lifetime;
- *  uint8 mfl_code;              // up to 255 according to standard
- *  uint8 trunc_hmac;            // 0 or 1
- *  uint8 encrypt_then_mac;      // 0 or 1
+ *          Note: When updating the format, remember to keep
+ *          these version+format bytes.
  *
- * The order is the same as in the definition of the structure, except
- * verify_result is put before peer_cert so that all mandatory fields come
- * together in one block.
+ *                                 // In this version, `session_format` determines
+ *                                 // the setting of those compile-time
+ *                                 // configuration options which influence
+ *                                 // the structure of mbedtls_ssl_session.
+ *
+ *    uint8_t minor_ver;           // Protocol minor version. Possible values:
+ *                                 // - TLS 1.2 (0x0303)
+ *                                 // - TLS 1.3 (0x0304)
+ *
+ *    select (serialized_session.tls_version) {
+ *
+ *      case MBEDTLS_SSL_VERSION_TLS1_2:
+ *        serialized_session_tls12 data;
+ *      case MBEDTLS_SSL_VERSION_TLS1_3:
+ *        serialized_session_tls13 data;
+ *
+ *   };
+ *
+ * } serialized_session;
+ *
  */
+
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_session_save( const mbedtls_ssl_session *session,
-                             unsigned char omit_header,
-                             unsigned char *buf,
-                             size_t buf_len,
-                             size_t *olen )
+static int ssl_session_save(const mbedtls_ssl_session *session,
+                            unsigned char omit_header,
+                            unsigned char *buf,
+                            size_t buf_len,
+                            size_t *olen)
 {
     unsigned char *p = buf;
     size_t used = 0;
-#if defined(MBEDTLS_HAVE_TIME)
-    uint64_t start;
+    size_t remaining_len;
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    size_t out_len;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 #endif
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    size_t cert_len;
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
+    if (session == NULL) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
 
-
-    if( !omit_header )
-    {
+    if (!omit_header) {
         /*
-         * Add version identifier
+         * Add Mbed TLS version identifier
          */
+        used += sizeof(ssl_serialized_session_header);
 
-        used += sizeof( ssl_serialized_session_header );
-
-        if( used <= buf_len )
-        {
-            memcpy( p, ssl_serialized_session_header,
-                    sizeof( ssl_serialized_session_header ) );
-            p += sizeof( ssl_serialized_session_header );
+        if (used <= buf_len) {
+            memcpy(p, ssl_serialized_session_header,
+                   sizeof(ssl_serialized_session_header));
+            p += sizeof(ssl_serialized_session_header);
         }
     }
 
     /*
-     * Time
+     * TLS version identifier
      */
-#if defined(MBEDTLS_HAVE_TIME)
-    used += 8;
-
-    if( used <= buf_len )
-    {
-        start = (uint64_t) session->start;
-
-        MBEDTLS_PUT_UINT64_BE( start, p, 0 );
-        p += 8;
-    }
-#endif /* MBEDTLS_HAVE_TIME */
-
-    /*
-     * Basic mandatory fields
-     */
-    used += 2   /* ciphersuite */
-          + 1   /* compression */
-          + 1   /* id_len */
-          + sizeof( session->id )
-          + sizeof( session->master )
-          + 4;  /* verify_result */
-
-    if( used <= buf_len )
-    {
-        MBEDTLS_PUT_UINT16_BE( session->ciphersuite, p, 0 );
-        p += 2;
-
-        *p++ = MBEDTLS_BYTE_0( session->compression );
-
-        *p++ = MBEDTLS_BYTE_0( session->id_len );
-        memcpy( p, session->id, 32 );
-        p += 32;
-
-        memcpy( p, session->master, 48 );
-        p += 48;
-
-        MBEDTLS_PUT_UINT32_BE( session->verify_result, p, 0 );
-        p += 4;
-    }
-
-    /*
-     * Peer's end-entity certificate
-     */
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    if( session->peer_cert == NULL )
-        cert_len = 0;
-    else
-        cert_len = session->peer_cert->raw.len;
-
-    used += 3 + cert_len;
-
-    if( used <= buf_len )
-    {
-        *p++ = MBEDTLS_BYTE_2( cert_len );
-        *p++ = MBEDTLS_BYTE_1( cert_len );
-        *p++ = MBEDTLS_BYTE_0( cert_len );
-
-        if( session->peer_cert != NULL )
-        {
-            memcpy( p, session->peer_cert->raw.p, cert_len );
-            p += cert_len;
-        }
-    }
-#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-    if( session->peer_cert_digest != NULL )
-    {
-        used += 1 /* type */ + 1 /* length */ + session->peer_cert_digest_len;
-        if( used <= buf_len )
-        {
-            *p++ = (unsigned char) session->peer_cert_digest_type;
-            *p++ = (unsigned char) session->peer_cert_digest_len;
-            memcpy( p, session->peer_cert_digest,
-                    session->peer_cert_digest_len );
-            p += session->peer_cert_digest_len;
-        }
-    }
-    else
-    {
-        used += 2;
-        if( used <= buf_len )
-        {
-            *p++ = (unsigned char) MBEDTLS_MD_NONE;
-            *p++ = 0;
-        }
-    }
-#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
-
-    /*
-     * Session ticket if any, plus associated data
-     */
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
-    used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */
-
-    if( used <= buf_len )
-    {
-        *p++ = MBEDTLS_BYTE_2( session->ticket_len );
-        *p++ = MBEDTLS_BYTE_1( session->ticket_len );
-        *p++ = MBEDTLS_BYTE_0( session->ticket_len );
-
-        if( session->ticket != NULL )
-        {
-            memcpy( p, session->ticket, session->ticket_len );
-            p += session->ticket_len;
-        }
-
-        MBEDTLS_PUT_UINT32_BE( session->ticket_lifetime, p, 0 );
-        p += 4;
-    }
-#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
-
-    /*
-     * Misc extension-related info
-     */
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
     used += 1;
+    if (used <= buf_len) {
+        *p++ = MBEDTLS_BYTE_0(session->tls_version);
+    }
 
-    if( used <= buf_len )
-        *p++ = session->mfl_code;
-#endif
+    /* Forward to version-specific serialization routine. */
+    remaining_len = (buf_len >= used) ? buf_len - used : 0;
+    switch (session->tls_version) {
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        case MBEDTLS_SSL_VERSION_TLS1_2:
+            used += ssl_tls12_session_save(session, p, remaining_len);
+            break;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-    used += 1;
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        case MBEDTLS_SSL_VERSION_TLS1_3:
+            ret = ssl_tls13_session_save(session, p, remaining_len, &out_len);
+            if (ret != 0 && ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) {
+                return ret;
+            }
+            used += out_len;
+            break;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
-    if( used <= buf_len )
-        *p++ = (unsigned char)( ( session->trunc_hmac ) & 0xFF );
-#endif
+        default:
+            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    }
 
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-    used += 1;
-
-    if( used <= buf_len )
-        *p++ = MBEDTLS_BYTE_0( session->encrypt_then_mac );
-#endif
-
-    /* Done */
     *olen = used;
+    if (used > buf_len) {
+        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+    }
 
-    if( used > buf_len )
-        return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
-
-    return( 0 );
+    return 0;
 }
 
 /*
  * Public wrapper for ssl_session_save()
  */
-int mbedtls_ssl_session_save( const mbedtls_ssl_session *session,
-                              unsigned char *buf,
-                              size_t buf_len,
-                              size_t *olen )
+int mbedtls_ssl_session_save(const mbedtls_ssl_session *session,
+                             unsigned char *buf,
+                             size_t buf_len,
+                             size_t *olen)
 {
-    return( ssl_session_save( session, 0, buf, buf_len, olen ) );
+    return ssl_session_save(session, 0, buf, buf_len, olen);
 }
 
 /*
@@ -5619,302 +3718,238 @@
  * case of error, and has an extra option omit_header.
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_session_load( mbedtls_ssl_session *session,
-                             unsigned char omit_header,
-                             const unsigned char *buf,
-                             size_t len )
+static int ssl_session_load(mbedtls_ssl_session *session,
+                            unsigned char omit_header,
+                            const unsigned char *buf,
+                            size_t len)
 {
     const unsigned char *p = buf;
     const unsigned char * const end = buf + len;
-#if defined(MBEDTLS_HAVE_TIME)
-    uint64_t start;
-#endif
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    size_t cert_len;
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
+    size_t remaining_len;
 
-    if( !omit_header )
-    {
+
+    if (session == NULL) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    if (!omit_header) {
         /*
-         * Check version identifier
+         * Check Mbed TLS version identifier
          */
 
-        if( (size_t)( end - p ) < sizeof( ssl_serialized_session_header ) )
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-        if( memcmp( p, ssl_serialized_session_header,
-                    sizeof( ssl_serialized_session_header ) ) != 0 )
-        {
-            return( MBEDTLS_ERR_SSL_VERSION_MISMATCH );
-        }
-        p += sizeof( ssl_serialized_session_header );
-    }
-
-    /*
-     * Time
-     */
-#if defined(MBEDTLS_HAVE_TIME)
-    if( 8 > (size_t)( end - p ) )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    start = ( (uint64_t) p[0] << 56 ) |
-            ( (uint64_t) p[1] << 48 ) |
-            ( (uint64_t) p[2] << 40 ) |
-            ( (uint64_t) p[3] << 32 ) |
-            ( (uint64_t) p[4] << 24 ) |
-            ( (uint64_t) p[5] << 16 ) |
-            ( (uint64_t) p[6] <<  8 ) |
-            ( (uint64_t) p[7]       );
-    p += 8;
-
-    session->start = (time_t) start;
-#endif /* MBEDTLS_HAVE_TIME */
-
-    /*
-     * Basic mandatory fields
-     */
-    if( 2 + 1 + 1 + 32 + 48 + 4 > (size_t)( end - p ) )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    session->ciphersuite = ( p[0] << 8 ) | p[1];
-    p += 2;
-
-    session->compression = *p++;
-
-    session->id_len = *p++;
-    memcpy( session->id, p, 32 );
-    p += 32;
-
-    memcpy( session->master, p, 48 );
-    p += 48;
-
-    session->verify_result = ( (uint32_t) p[0] << 24 ) |
-                             ( (uint32_t) p[1] << 16 ) |
-                             ( (uint32_t) p[2] <<  8 ) |
-                             ( (uint32_t) p[3]       );
-    p += 4;
-
-    /* Immediately clear invalid pointer values that have been read, in case
-     * we exit early before we replaced them with valid ones. */
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    session->peer_cert = NULL;
-#else
-    session->peer_cert_digest = NULL;
-#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
-    session->ticket = NULL;
-#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
-
-    /*
-     * Peer certificate
-     */
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    /* Deserialize CRT from the end of the ticket. */
-    if( 3 > (size_t)( end - p ) )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2];
-    p += 3;
-
-    if( cert_len != 0 )
-    {
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-        if( cert_len > (size_t)( end - p ) )
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-        session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
-
-        if( session->peer_cert == NULL )
-            return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
-
-        mbedtls_x509_crt_init( session->peer_cert );
-
-        if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert,
-                                                p, cert_len ) ) != 0 )
-        {
-            mbedtls_x509_crt_free( session->peer_cert );
-            mbedtls_free( session->peer_cert );
-            session->peer_cert = NULL;
-            return( ret );
+        if ((size_t) (end - p) < sizeof(ssl_serialized_session_header)) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
         }
 
-        p += cert_len;
+        if (memcmp(p, ssl_serialized_session_header,
+                   sizeof(ssl_serialized_session_header)) != 0) {
+            return MBEDTLS_ERR_SSL_VERSION_MISMATCH;
+        }
+        p += sizeof(ssl_serialized_session_header);
     }
-#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-    /* Deserialize CRT digest from the end of the ticket. */
-    if( 2 > (size_t)( end - p ) )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    session->peer_cert_digest_type = (mbedtls_md_type_t) *p++;
-    session->peer_cert_digest_len  = (size_t) *p++;
-
-    if( session->peer_cert_digest_len != 0 )
-    {
-        const mbedtls_md_info_t *md_info =
-            mbedtls_md_info_from_type( session->peer_cert_digest_type );
-        if( md_info == NULL )
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-        if( session->peer_cert_digest_len != mbedtls_md_get_size( md_info ) )
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-        if( session->peer_cert_digest_len > (size_t)( end - p ) )
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-        session->peer_cert_digest =
-            mbedtls_calloc( 1, session->peer_cert_digest_len );
-        if( session->peer_cert_digest == NULL )
-            return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
-
-        memcpy( session->peer_cert_digest, p,
-                session->peer_cert_digest_len );
-        p += session->peer_cert_digest_len;
-    }
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
 
     /*
-     * Session ticket and associated data
+     * TLS version identifier
      */
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
-    if( 3 > (size_t)( end - p ) )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    session->ticket_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2];
-    p += 3;
-
-    if( session->ticket_len != 0 )
-    {
-        if( session->ticket_len > (size_t)( end - p ) )
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-        session->ticket = mbedtls_calloc( 1, session->ticket_len );
-        if( session->ticket == NULL )
-            return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
-
-        memcpy( session->ticket, p, session->ticket_len );
-        p += session->ticket_len;
+    if (1 > (size_t) (end - p)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
+    session->tls_version = 0x0300 | *p++;
 
-    if( 4 > (size_t)( end - p ) )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    /* Dispatch according to TLS version. */
+    remaining_len = (end - p);
+    switch (session->tls_version) {
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        case MBEDTLS_SSL_VERSION_TLS1_2:
+            return ssl_tls12_session_load(session, p, remaining_len);
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
-    session->ticket_lifetime = ( (uint32_t) p[0] << 24 ) |
-                               ( (uint32_t) p[1] << 16 ) |
-                               ( (uint32_t) p[2] <<  8 ) |
-                               ( (uint32_t) p[3]       );
-    p += 4;
-#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        case MBEDTLS_SSL_VERSION_TLS1_3:
+            return ssl_tls13_session_load(session, p, remaining_len);
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
-    /*
-     * Misc extension-related info
-     */
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-    if( 1 > (size_t)( end - p ) )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    session->mfl_code = *p++;
-#endif
-
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-    if( 1 > (size_t)( end - p ) )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    session->trunc_hmac = *p++;
-#endif
-
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-    if( 1 > (size_t)( end - p ) )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    session->encrypt_then_mac = *p++;
-#endif
-
-    /* Done, should have consumed entire buffer */
-    if( p != end )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    return( 0 );
+        default:
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 }
 
 /*
  * Deserialize session: public wrapper for error cleaning
  */
-int mbedtls_ssl_session_load( mbedtls_ssl_session *session,
-                              const unsigned char *buf,
-                              size_t len )
+int mbedtls_ssl_session_load(mbedtls_ssl_session *session,
+                             const unsigned char *buf,
+                             size_t len)
 {
-    int ret = ssl_session_load( session, 0, buf, len );
+    int ret = ssl_session_load(session, 0, buf, len);
 
-    if( ret != 0 )
-        mbedtls_ssl_session_free( session );
+    if (ret != 0) {
+        mbedtls_ssl_session_free(session);
+    }
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Perform a single step of the SSL handshake
  */
-int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl )
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_prepare_handshake_step(mbedtls_ssl_context *ssl)
 {
-    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( ssl == NULL || ssl->conf == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    /*
+     * We may have not been able to send to the peer all the handshake data
+     * that were written into the output buffer by the previous handshake step,
+     * if the write to the network callback returned with the
+     * #MBEDTLS_ERR_SSL_WANT_WRITE error code.
+     * We proceed to the next handshake step only when all data from the
+     * previous one have been sent to the peer, thus we make sure that this is
+     * the case here by calling `mbedtls_ssl_flush_output()`. The function may
+     * return with the #MBEDTLS_ERR_SSL_WANT_WRITE error code in which case
+     * we have to wait before to go ahead.
+     * In the case of TLS 1.3, handshake step handlers do not send data to the
+     * peer. Data are only sent here and through
+     * `mbedtls_ssl_handle_pending_alert` in case an error that triggered an
+     * alert occurred.
+     */
+    if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) {
+        return ret;
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) {
+        if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) {
+            return ret;
+        }
+    }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+    return ret;
+}
+
+int mbedtls_ssl_handshake_step(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if (ssl            == NULL                       ||
+        ssl->conf      == NULL                       ||
+        ssl->handshake == NULL                       ||
+        ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    ret = ssl_prepare_handshake_step(ssl);
+    if (ret != 0) {
+        return ret;
+    }
+
+    ret = mbedtls_ssl_handle_pending_alert(ssl);
+    if (ret != 0) {
+        goto cleanup;
+    }
+
+    /* If ssl->conf->endpoint is not one of MBEDTLS_SSL_IS_CLIENT or
+     * MBEDTLS_SSL_IS_SERVER, this is the return code we give */
+    ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
 
 #if defined(MBEDTLS_SSL_CLI_C)
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
-        ret = mbedtls_ssl_handshake_client_step( ssl );
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("client state: %s",
+                                  mbedtls_ssl_states_str(ssl->state)));
+
+        switch (ssl->state) {
+            case MBEDTLS_SSL_HELLO_REQUEST:
+                ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
+                ret = 0;
+                break;
+
+            case MBEDTLS_SSL_CLIENT_HELLO:
+                ret = mbedtls_ssl_write_client_hello(ssl);
+                break;
+
+            default:
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
+                if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
+                    ret = mbedtls_ssl_tls13_handshake_client_step(ssl);
+                } else {
+                    ret = mbedtls_ssl_handshake_client_step(ssl);
+                }
+#elif defined(MBEDTLS_SSL_PROTO_TLS1_2)
+                ret = mbedtls_ssl_handshake_client_step(ssl);
+#else
+                ret = mbedtls_ssl_tls13_handshake_client_step(ssl);
+#endif
+        }
+    }
 #endif
 #if defined(MBEDTLS_SSL_SRV_C)
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
-        ret = mbedtls_ssl_handshake_server_step( ssl );
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        if (mbedtls_ssl_conf_is_tls13_only(ssl->conf)) {
+            ret = mbedtls_ssl_tls13_handshake_server_step(ssl);
+        }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        if (mbedtls_ssl_conf_is_tls12_only(ssl->conf)) {
+            ret = mbedtls_ssl_handshake_server_step(ssl);
+        }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+    }
 #endif
 
-    return( ret );
+    if (ret != 0) {
+        /* handshake_step return error. And it is same
+         * with alert_reason.
+         */
+        if (ssl->send_alert) {
+            ret = mbedtls_ssl_handle_pending_alert(ssl);
+            goto cleanup;
+        }
+    }
+
+cleanup:
+    return ret;
 }
 
 /*
  * Perform the SSL handshake
  */
-int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl)
 {
     int ret = 0;
 
     /* Sanity checks */
 
-    if( ssl == NULL || ssl->conf == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl == NULL || ssl->conf == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL ) )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use "
-                                     "mbedtls_ssl_set_timer_cb() for DTLS" ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        (ssl->f_set_timer == NULL || ssl->f_get_timer == NULL)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("You must use "
+                                  "mbedtls_ssl_set_timer_cb() for DTLS"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> handshake" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> handshake"));
 
     /* Main handshake loop */
-    while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
-    {
-        ret = mbedtls_ssl_handshake_step( ssl );
+    while (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) {
+        ret = mbedtls_ssl_handshake_step(ssl);
 
-        if( ret != 0 )
+        if (ret != 0) {
             break;
+        }
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= handshake" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= handshake"));
 
-    return( ret );
+    return ret;
 }
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
@@ -5923,25 +3958,24 @@
  * Write HelloRequest to request renegotiation on server
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_hello_request( mbedtls_ssl_context *ssl )
+static int ssl_write_hello_request(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello request" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write hello request"));
 
     ssl->out_msglen  = 4;
     ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
     ssl->out_msg[0]  = MBEDTLS_SSL_HS_HELLO_REQUEST;
 
-    if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
-        return( ret );
+    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret);
+        return ret;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello request" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write hello request"));
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_SSL_SRV_C */
 
@@ -5954,67 +3988,69 @@
  * If the handshake doesn't complete due to waiting for I/O, it will continue
  * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively.
  */
-int mbedtls_ssl_start_renegotiation( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_start_renegotiation(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> renegotiate"));
 
-    if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
-        return( ret );
+    if ((ret = ssl_handshake_init(ssl)) != 0) {
+        return ret;
+    }
 
     /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and
      * the ServerHello will have message_seq = 1" */
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
-    {
-        if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) {
+        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
             ssl->handshake->out_msg_seq = 1;
-        else
+        } else {
             ssl->handshake->in_msg_seq = 1;
+        }
     }
 #endif
 
     ssl->state = MBEDTLS_SSL_HELLO_REQUEST;
     ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS;
 
-    if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret );
-        return( ret );
+    if ((ret = mbedtls_ssl_handshake(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret);
+        return ret;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= renegotiate"));
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Renegotiate current connection on client,
  * or request renegotiation on server
  */
-int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
 
-    if( ssl == NULL || ssl->conf == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl == NULL || ssl->conf == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
 #if defined(MBEDTLS_SSL_SRV_C)
     /* On server, just send the request */
-    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
-    {
-        if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
+        if (mbedtls_ssl_is_handshake_over(ssl) == 0) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
 
         ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;
 
         /* Did we already try/start sending HelloRequest? */
-        if( ssl->out_left != 0 )
-            return( mbedtls_ssl_flush_output( ssl ) );
+        if (ssl->out_left != 0) {
+            return mbedtls_ssl_flush_output(ssl);
+        }
 
-        return( ssl_write_hello_request( ssl ) );
+        return ssl_write_hello_request(ssl);
     }
 #endif /* MBEDTLS_SSL_SRV_C */
 
@@ -6023,92 +4059,104 @@
      * On client, either start the renegotiation process or,
      * if already in progress, continue the handshake
      */
-    if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
-    {
-        if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-        if( ( ret = mbedtls_ssl_start_renegotiation( ssl ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation", ret );
-            return( ret );
+    if (ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {
+        if (mbedtls_ssl_is_handshake_over(ssl) == 0) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
         }
-    }
-    else
-    {
-        if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret );
-            return( ret );
+
+        if ((ret = mbedtls_ssl_start_renegotiation(ssl)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_start_renegotiation", ret);
+            return ret;
+        }
+    } else {
+        if ((ret = mbedtls_ssl_handshake(ssl)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret);
+            return ret;
         }
     }
 #endif /* MBEDTLS_SSL_CLI_C */
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
 
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert )
-{
-    mbedtls_ssl_key_cert *cur = key_cert, *next;
-
-    while( cur != NULL )
-    {
-        next = cur->next;
-        mbedtls_free( cur );
-        cur = next;
-    }
-}
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
-
-void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl )
+void mbedtls_ssl_handshake_free(mbedtls_ssl_context *ssl)
 {
     mbedtls_ssl_handshake_params *handshake = ssl->handshake;
 
-    if( handshake == NULL )
+    if (handshake == NULL) {
         return;
+    }
+
+#if defined(MBEDTLS_ECP_C)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+    if (ssl->handshake->group_list_heap_allocated) {
+        mbedtls_free((void *) handshake->group_list);
+    }
+    handshake->group_list = NULL;
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+#endif /* MBEDTLS_ECP_C */
+
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+    if (ssl->handshake->sig_algs_heap_allocated) {
+        mbedtls_free((void *) handshake->sig_algs);
+    }
+    handshake->sig_algs = NULL;
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    if (ssl->handshake->certificate_request_context) {
+        mbedtls_free((void *) handshake->certificate_request_context);
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
 
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
-    if( ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0 )
-    {
-        ssl->conf->f_async_cancel( ssl );
+    if (ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0) {
+        ssl->conf->f_async_cancel(ssl);
         handshake->async_in_progress = 0;
     }
 #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
 
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_1)
-    mbedtls_md5_free(    &handshake->fin_md5  );
-    mbedtls_sha1_free(   &handshake->fin_sha1 );
-#endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_abort( &handshake->fin_sha256_psa );
+    psa_hash_abort(&handshake->fin_sha256_psa);
 #else
-    mbedtls_sha256_free(   &handshake->fin_sha256    );
+    mbedtls_md_free(&handshake->fin_sha256);
 #endif
 #endif
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_abort( &handshake->fin_sha384_psa );
+    psa_hash_abort(&handshake->fin_sha384_psa);
 #else
-    mbedtls_sha512_free(   &handshake->fin_sha512    );
+    mbedtls_md_free(&handshake->fin_sha384);
 #endif
 #endif
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
 #if defined(MBEDTLS_DHM_C)
-    mbedtls_dhm_free( &handshake->dhm_ctx );
+    mbedtls_dhm_free(&handshake->dhm_ctx);
 #endif
-#if defined(MBEDTLS_ECDH_C)
-    mbedtls_ecdh_free( &handshake->ecdh_ctx );
+#if !defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ECDH_C)
+    mbedtls_ecdh_free(&handshake->ecdh_ctx);
 #endif
+
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    mbedtls_ecjpake_free( &handshake->ecjpake_ctx );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_pake_abort(&handshake->psa_pake_ctx);
+    /*
+     * 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);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 #if defined(MBEDTLS_SSL_CLI_C)
-    mbedtls_free( handshake->ecjpake_cache );
+    mbedtls_free(handshake->ecjpake_cache);
     handshake->ecjpake_cache = NULL;
     handshake->ecjpake_cache_len = 0;
 #endif
@@ -6117,16 +4165,27 @@
 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
     /* explicit void pointer cast for buggy MS compiler */
-    mbedtls_free( (void *) handshake->curves );
+    mbedtls_free((void *) handshake->curves_tls_id);
 #endif
 
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
-    if( handshake->psk != NULL )
-    {
-        mbedtls_platform_zeroize( handshake->psk, handshake->psk_len );
-        mbedtls_free( handshake->psk );
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) {
+        /* The maintenance of the external PSK key slot is the
+         * user's responsibility. */
+        if (ssl->handshake->psk_opaque_is_internal) {
+            psa_destroy_key(ssl->handshake->psk_opaque);
+            ssl->handshake->psk_opaque_is_internal = 0;
+        }
+        ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT;
     }
-#endif
+#else
+    if (handshake->psk != NULL) {
+        mbedtls_platform_zeroize(handshake->psk, handshake->psk_len);
+        mbedtls_free(handshake->psk);
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C) && \
     defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
@@ -6134,71 +4193,83 @@
      * Free only the linked list wrapper, not the keys themselves
      * since the belong to the SNI callback
      */
-    if( handshake->sni_key_cert != NULL )
-    {
-        mbedtls_ssl_key_cert *cur = handshake->sni_key_cert, *next;
-
-        while( cur != NULL )
-        {
-            next = cur->next;
-            mbedtls_free( cur );
-            cur = next;
-        }
-    }
+    ssl_key_cert_free(handshake->sni_key_cert);
 #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */
 
 #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    mbedtls_x509_crt_restart_free( &handshake->ecrs_ctx );
-    if( handshake->ecrs_peer_cert != NULL )
-    {
-        mbedtls_x509_crt_free( handshake->ecrs_peer_cert );
-        mbedtls_free( handshake->ecrs_peer_cert );
+    mbedtls_x509_crt_restart_free(&handshake->ecrs_ctx);
+    if (handshake->ecrs_peer_cert != NULL) {
+        mbedtls_x509_crt_free(handshake->ecrs_peer_cert);
+        mbedtls_free(handshake->ecrs_peer_cert);
     }
 #endif
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C) &&        \
     !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    mbedtls_pk_free( &handshake->peer_pubkey );
+    mbedtls_pk_free(&handshake->peer_pubkey);
 #endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    mbedtls_free( handshake->verify_cookie );
-    mbedtls_ssl_flight_free( handshake->flight );
-    mbedtls_ssl_buffering_free( ssl );
-#endif
+#if defined(MBEDTLS_SSL_CLI_C) && \
+    (defined(MBEDTLS_SSL_PROTO_DTLS) || defined(MBEDTLS_SSL_PROTO_TLS1_3))
+    mbedtls_free(handshake->cookie);
+#endif /* MBEDTLS_SSL_CLI_C &&
+          ( MBEDTLS_SSL_PROTO_DTLS || MBEDTLS_SSL_PROTO_TLS1_3 ) */
 
-#if defined(MBEDTLS_ECDH_C) &&                  \
-    defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_destroy_key( handshake->ecdh_psa_privkey );
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    mbedtls_ssl_flight_free(handshake->flight);
+    mbedtls_ssl_buffering_free(ssl);
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+#if defined(MBEDTLS_ECDH_C) && \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3))
+    if (handshake->ecdh_psa_privkey_is_external == 0) {
+        psa_destroy_key(handshake->ecdh_psa_privkey);
+    }
 #endif /* MBEDTLS_ECDH_C && MBEDTLS_USE_PSA_CRYPTO */
 
-    mbedtls_platform_zeroize( handshake,
-                              sizeof( mbedtls_ssl_handshake_params ) );
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    mbedtls_ssl_transform_free(handshake->transform_handshake);
+    mbedtls_free(handshake->transform_handshake);
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    mbedtls_ssl_transform_free(handshake->transform_earlydata);
+    mbedtls_free(handshake->transform_earlydata);
+#endif
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
 
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
     /* If the buffers are too big - reallocate. Because of the way Mbed TLS
      * processes datagrams and the fact that a datagram is allowed to have
      * several records in it, it is possible that the I/O buffers are not
      * empty at this stage */
-    handle_buffer_resizing( ssl, 1, mbedtls_ssl_get_input_buflen( ssl ),
-                                    mbedtls_ssl_get_output_buflen( ssl ) );
+    handle_buffer_resizing(ssl, 1, mbedtls_ssl_get_input_buflen(ssl),
+                           mbedtls_ssl_get_output_buflen(ssl));
 #endif
+
+    /* mbedtls_platform_zeroize MUST be last one in this function */
+    mbedtls_platform_zeroize(handshake,
+                             sizeof(mbedtls_ssl_handshake_params));
 }
 
-void mbedtls_ssl_session_free( mbedtls_ssl_session *session )
+void mbedtls_ssl_session_free(mbedtls_ssl_session *session)
 {
-    if( session == NULL )
+    if (session == NULL) {
         return;
+    }
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
-    ssl_clear_peer_cert( session );
+    ssl_clear_peer_cert(session);
 #endif
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
-    mbedtls_free( session->ticket );
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
+    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    mbedtls_free(session->hostname);
+#endif
+    mbedtls_free(session->ticket);
 #endif
 
-    mbedtls_platform_zeroize( session, sizeof( mbedtls_ssl_session ) );
+    mbedtls_platform_zeroize(session, sizeof(mbedtls_ssl_session));
 }
 
 #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
@@ -6209,11 +4280,7 @@
 #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 0u
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
-#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
 #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 1u
-#else
-#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 0u
-#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
 
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
 #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 1u
@@ -6233,22 +4300,25 @@
 #define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT                  3
 
 #define SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG   \
-    ( (uint32_t) (                              \
-        ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID     << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT     ) | \
-        ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT      << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT      ) | \
-        ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY       << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT       ) | \
-        ( SSL_SERIALIZED_CONTEXT_CONFIG_ALPN                   << SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT                   ) | \
-        0u ) )
+    ((uint32_t) (                              \
+         (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID << \
+             SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT) | \
+         (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT << \
+             SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT) | \
+         (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY << \
+             SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT) | \
+         (SSL_SERIALIZED_CONTEXT_CONFIG_ALPN << SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT) | \
+         0u))
 
 static unsigned char ssl_serialized_context_header[] = {
     MBEDTLS_VERSION_MAJOR,
     MBEDTLS_VERSION_MINOR,
     MBEDTLS_VERSION_PATCH,
-    MBEDTLS_BYTE_1( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG ),
-    MBEDTLS_BYTE_0( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG ),
-    MBEDTLS_BYTE_2( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG ),
-    MBEDTLS_BYTE_1( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG ),
-    MBEDTLS_BYTE_0( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG ),
+    MBEDTLS_BYTE_1(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG),
+    MBEDTLS_BYTE_0(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG),
+    MBEDTLS_BYTE_2(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG),
+    MBEDTLS_BYTE_1(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG),
+    MBEDTLS_BYTE_0(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG),
 };
 
 /*
@@ -6289,10 +4359,10 @@
  *  4. value was temporary (eg content of input buffer)
  *  5. value will be provided by the user again (eg I/O callbacks and context)
  */
-int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl,
-                              unsigned char *buf,
-                              size_t buf_len,
-                              size_t *olen )
+int mbedtls_ssl_context_save(mbedtls_ssl_context *ssl,
+                             unsigned char *buf,
+                             size_t buf_len,
+                             size_t *olen)
 {
     unsigned char *p = buf;
     size_t used = 0;
@@ -6308,94 +4378,80 @@
      * (only DTLS) but are currently used to simplify the implementation.
      */
     /* The initial handshake must be over */
-    if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Initial handshake isn't over" ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (mbedtls_ssl_is_handshake_over(ssl) == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Initial handshake isn't over"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-    if( ssl->handshake != NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Handshake isn't completed" ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl->handshake != NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Handshake isn't completed"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
     /* Double-check that sub-structures are indeed ready */
-    if( ssl->transform == NULL || ssl->session == NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Serialised structures aren't ready" ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl->transform == NULL || ssl->session == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Serialised structures aren't ready"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
     /* There must be no pending incoming or outgoing data */
-    if( mbedtls_ssl_check_pending( ssl ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "There is pending incoming data" ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (mbedtls_ssl_check_pending(ssl) != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("There is pending incoming data"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-    if( ssl->out_left != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "There is pending outgoing data" ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl->out_left != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("There is pending outgoing data"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-    /* Protocol must be DLTS, not TLS */
-    if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only DTLS is supported" ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    /* Protocol must be DTLS, not TLS */
+    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Only DTLS is supported"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
     /* Version must be 1.2 */
-    if( ssl->major_ver != MBEDTLS_SSL_MAJOR_VERSION_3 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only version 1.2 supported" ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-    }
-    if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only version 1.2 supported" ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_2) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Only version 1.2 supported"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
     /* We must be using an AEAD ciphersuite */
-    if( mbedtls_ssl_transform_uses_aead( ssl->transform ) != 1 )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only AEAD ciphersuites supported" ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (mbedtls_ssl_transform_uses_aead(ssl->transform) != 1) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Only AEAD ciphersuites supported"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
     /* Renegotiation must not be enabled */
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if( ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Renegotiation must not be enabled" ) );
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Renegotiation must not be enabled"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 #endif
 
     /*
      * Version and format identifier
      */
-    used += sizeof( ssl_serialized_context_header );
+    used += sizeof(ssl_serialized_context_header);
 
-    if( used <= buf_len )
-    {
-        memcpy( p, ssl_serialized_context_header,
-                sizeof( ssl_serialized_context_header ) );
-        p += sizeof( ssl_serialized_context_header );
+    if (used <= buf_len) {
+        memcpy(p, ssl_serialized_context_header,
+               sizeof(ssl_serialized_context_header));
+        p += sizeof(ssl_serialized_context_header);
     }
 
     /*
      * Session (length + data)
      */
-    ret = ssl_session_save( ssl->session, 1, NULL, 0, &session_len );
-    if( ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL )
-        return( ret );
+    ret = ssl_session_save(ssl->session, 1, NULL, 0, &session_len);
+    if (ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) {
+        return ret;
+    }
 
     used += 4 + session_len;
-    if( used <= buf_len )
-    {
-        MBEDTLS_PUT_UINT32_BE( session_len, p, 0 );
+    if (used <= buf_len) {
+        MBEDTLS_PUT_UINT32_BE(session_len, p, 0);
         p += 4;
 
-        ret = ssl_session_save( ssl->session, 1,
-                                p, session_len, &session_len );
-        if( ret != 0 )
-            return( ret );
+        ret = ssl_session_save(ssl->session, 1,
+                               p, session_len, &session_len);
+        if (ret != 0) {
+            return ret;
+        }
 
         p += session_len;
     }
@@ -6403,24 +4459,22 @@
     /*
      * Transform
      */
-    used += sizeof( ssl->transform->randbytes );
-    if( used <= buf_len )
-    {
-        memcpy( p, ssl->transform->randbytes,
-           sizeof( ssl->transform->randbytes ) );
-        p += sizeof( ssl->transform->randbytes );
+    used += sizeof(ssl->transform->randbytes);
+    if (used <= buf_len) {
+        memcpy(p, ssl->transform->randbytes,
+               sizeof(ssl->transform->randbytes));
+        p += sizeof(ssl->transform->randbytes);
     }
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
     used += 2 + ssl->transform->in_cid_len + ssl->transform->out_cid_len;
-    if( used <= buf_len )
-    {
+    if (used <= buf_len) {
         *p++ = ssl->transform->in_cid_len;
-        memcpy( p, ssl->transform->in_cid, ssl->transform->in_cid_len );
+        memcpy(p, ssl->transform->in_cid, ssl->transform->in_cid_len);
         p += ssl->transform->in_cid_len;
 
         *p++ = ssl->transform->out_cid_len;
-        memcpy( p, ssl->transform->out_cid, ssl->transform->out_cid_len );
+        memcpy(p, ssl->transform->out_cid, ssl->transform->out_cid_len);
         p += ssl->transform->out_cid_len;
     }
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
@@ -6428,47 +4482,40 @@
     /*
      * Saved fields from top-level ssl_context structure
      */
-#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
     used += 4;
-    if( used <= buf_len )
-    {
-        MBEDTLS_PUT_UINT32_BE( ssl->badmac_seen, p, 0 );
+    if (used <= buf_len) {
+        MBEDTLS_PUT_UINT32_BE(ssl->badmac_seen, p, 0);
         p += 4;
     }
-#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
 
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
     used += 16;
-    if( used <= buf_len )
-    {
-        MBEDTLS_PUT_UINT64_BE( ssl->in_window_top, p, 0 );
+    if (used <= buf_len) {
+        MBEDTLS_PUT_UINT64_BE(ssl->in_window_top, p, 0);
         p += 8;
 
-        MBEDTLS_PUT_UINT64_BE( ssl->in_window, p, 0 );
+        MBEDTLS_PUT_UINT64_BE(ssl->in_window, p, 0);
         p += 8;
     }
 #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     used += 1;
-    if( used <= buf_len )
-    {
+    if (used <= buf_len) {
         *p++ = ssl->disable_datagram_packing;
     }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-    used += 8;
-    if( used <= buf_len )
-    {
-        memcpy( p, ssl->cur_out_ctr, 8 );
-        p += 8;
+    used += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
+    if (used <= buf_len) {
+        memcpy(p, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN);
+        p += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
     }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     used += 2;
-    if( used <= buf_len )
-    {
-        MBEDTLS_PUT_UINT16_BE( ssl->mtu, p, 0 );
+    if (used <= buf_len) {
+        MBEDTLS_PUT_UINT16_BE(ssl->mtu, p, 0);
         p += 2;
     }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
@@ -6476,17 +4523,15 @@
 #if defined(MBEDTLS_SSL_ALPN)
     {
         const uint8_t alpn_len = ssl->alpn_chosen
-                               ? (uint8_t) strlen( ssl->alpn_chosen )
+                               ? (uint8_t) strlen(ssl->alpn_chosen)
                                : 0;
 
         used += 1 + alpn_len;
-        if( used <= buf_len )
-        {
+        if (used <= buf_len) {
             *p++ = alpn_len;
 
-            if( ssl->alpn_chosen != NULL )
-            {
-                memcpy( p, ssl->alpn_chosen, alpn_len );
+            if (ssl->alpn_chosen != NULL) {
+                memcpy(p, ssl->alpn_chosen, alpn_len);
                 p += alpn_len;
             }
         }
@@ -6498,34 +4543,13 @@
      */
     *olen = used;
 
-    if( used > buf_len )
-        return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+    if (used > buf_len) {
+        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+    }
 
-    MBEDTLS_SSL_DEBUG_BUF( 4, "saved context", buf, used );
+    MBEDTLS_SSL_DEBUG_BUF(4, "saved context", buf, used);
 
-    return( mbedtls_ssl_session_reset_int( ssl, 0 ) );
-}
-
-/*
- * Helper to get TLS 1.2 PRF from ciphersuite
- * (Duplicates bits of logic from ssl_set_handshake_prfs().)
- */
-typedef int (*tls_prf_fn)( const unsigned char *secret, size_t slen,
-                           const char *label,
-                           const unsigned char *random, size_t rlen,
-                           unsigned char *dstbuf, size_t dlen );
-static tls_prf_fn ssl_tls12prf_from_cs( int ciphersuite_id )
-{
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
-    const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
-         mbedtls_ssl_ciphersuite_from_id( ciphersuite_id );
-
-    if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 )
-        return( tls_prf_sha384 );
-#else
-    (void) ciphersuite_id;
-#endif
-    return( tls_prf_sha256 );
+    return mbedtls_ssl_session_reset_int(ssl, 0);
 }
 
 /*
@@ -6535,14 +4559,17 @@
  * case of error.
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_context_load( mbedtls_ssl_context *ssl,
-                             const unsigned char *buf,
-                             size_t len )
+static int ssl_context_load(mbedtls_ssl_context *ssl,
+                            const unsigned char *buf,
+                            size_t len)
 {
     const unsigned char *p = buf;
     const unsigned char * const end = buf + len;
     size_t session_len;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    tls_prf_fn prf_func = NULL;
+#endif
 
     /*
      * The context should have been freshly setup or reset.
@@ -6550,54 +4577,51 @@
      * (Checking session is useful because it won't be NULL if we're
      * renegotiating, or if the user mistakenly loaded a session first.)
      */
-    if( ssl->state != MBEDTLS_SSL_HELLO_REQUEST ||
-        ssl->session != NULL )
-    {
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (ssl->state != MBEDTLS_SSL_HELLO_REQUEST ||
+        ssl->session != NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
     /*
      * We can't check that the config matches the initial one, but we can at
      * least check it matches the requirements for serializing.
      */
-    if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
-        ssl->conf->max_major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 ||
-        ssl->conf->min_major_ver > MBEDTLS_SSL_MAJOR_VERSION_3 ||
-        ssl->conf->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ||
-        ssl->conf->min_minor_ver > MBEDTLS_SSL_MINOR_VERSION_3 ||
+    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
+        ssl->conf->max_tls_version < MBEDTLS_SSL_VERSION_TLS1_2 ||
+        ssl->conf->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2 ||
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
         ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
 #endif
-        0 )
-    {
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+        0) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    MBEDTLS_SSL_DEBUG_BUF( 4, "context to load", buf, len );
+    MBEDTLS_SSL_DEBUG_BUF(4, "context to load", buf, len);
 
     /*
      * Check version identifier
      */
-    if( (size_t)( end - p ) < sizeof( ssl_serialized_context_header ) )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    if( memcmp( p, ssl_serialized_context_header,
-                sizeof( ssl_serialized_context_header ) ) != 0 )
-    {
-        return( MBEDTLS_ERR_SSL_VERSION_MISMATCH );
+    if ((size_t) (end - p) < sizeof(ssl_serialized_context_header)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-    p += sizeof( ssl_serialized_context_header );
+
+    if (memcmp(p, ssl_serialized_context_header,
+               sizeof(ssl_serialized_context_header)) != 0) {
+        return MBEDTLS_ERR_SSL_VERSION_MISMATCH;
+    }
+    p += sizeof(ssl_serialized_context_header);
 
     /*
      * Session
      */
-    if( (size_t)( end - p ) < 4 )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if ((size_t) (end - p) < 4) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    session_len = ( (size_t) p[0] << 24 ) |
-                  ( (size_t) p[1] << 16 ) |
-                  ( (size_t) p[2] <<  8 ) |
-                  ( (size_t) p[3]       );
+    session_len = ((size_t) p[0] << 24) |
+                  ((size_t) p[1] << 16) |
+                  ((size_t) p[2] <<  8) |
+                  ((size_t) p[3]);
     p += 4;
 
     /* This has been allocated by ssl_handshake_init(), called by
@@ -6607,14 +4631,14 @@
     ssl->session_out = ssl->session;
     ssl->session_negotiate = NULL;
 
-    if( (size_t)( end - p ) < session_len )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if ((size_t) (end - p) < session_len) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    ret = ssl_session_load( ssl->session, 1, p, session_len );
-    if( ret != 0 )
-    {
-        mbedtls_ssl_session_free( ssl->session );
-        return( ret );
+    ret = ssl_session_load(ssl->session, 1, p, session_len);
+    if (ret != 0) {
+        mbedtls_ssl_session_free(ssl->session);
+        return ret;
     }
 
     p += session_len;
@@ -6625,118 +4649,125 @@
 
     /* This has been allocated by ssl_handshake_init(), called by
      * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
     ssl->transform = ssl->transform_negotiate;
     ssl->transform_in = ssl->transform;
     ssl->transform_out = ssl->transform;
     ssl->transform_negotiate = NULL;
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    prf_func = ssl_tls12prf_from_cs(ssl->session->ciphersuite);
+    if (prf_func == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
     /* Read random bytes and populate structure */
-    if( (size_t)( end - p ) < sizeof( ssl->transform->randbytes ) )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if ((size_t) (end - p) < sizeof(ssl->transform->randbytes)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    ret = ssl_populate_transform( ssl->transform,
-                  ssl->session->ciphersuite,
-                  ssl->session->master,
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-                  ssl->session->encrypt_then_mac,
-#endif
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-                  ssl->session->trunc_hmac,
-#endif
-#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-                  ssl->session->compression,
-#endif
-                  ssl_tls12prf_from_cs( ssl->session->ciphersuite ),
-                  p, /* currently pointing to randbytes */
-                  MBEDTLS_SSL_MINOR_VERSION_3, /* (D)TLS 1.2 is forced */
-                  ssl->conf->endpoint,
-                  ssl );
-    if( ret != 0 )
-        return( ret );
-
-    p += sizeof( ssl->transform->randbytes );
+    ret = ssl_tls12_populate_transform(ssl->transform,
+                                       ssl->session->ciphersuite,
+                                       ssl->session->master,
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+                                       ssl->session->encrypt_then_mac,
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
+                                       prf_func,
+                                       p, /* currently pointing to randbytes */
+                                       MBEDTLS_SSL_VERSION_TLS1_2, /* (D)TLS 1.2 is forced */
+                                       ssl->conf->endpoint,
+                                       ssl);
+    if (ret != 0) {
+        return ret;
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+    p += sizeof(ssl->transform->randbytes);
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
     /* Read connection IDs and store them */
-    if( (size_t)( end - p ) < 1 )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if ((size_t) (end - p) < 1) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
     ssl->transform->in_cid_len = *p++;
 
-    if( (size_t)( end - p ) < ssl->transform->in_cid_len + 1u )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if ((size_t) (end - p) < ssl->transform->in_cid_len + 1u) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    memcpy( ssl->transform->in_cid, p, ssl->transform->in_cid_len );
+    memcpy(ssl->transform->in_cid, p, ssl->transform->in_cid_len);
     p += ssl->transform->in_cid_len;
 
     ssl->transform->out_cid_len = *p++;
 
-    if( (size_t)( end - p ) < ssl->transform->out_cid_len )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if ((size_t) (end - p) < ssl->transform->out_cid_len) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    memcpy( ssl->transform->out_cid, p, ssl->transform->out_cid_len );
+    memcpy(ssl->transform->out_cid, p, ssl->transform->out_cid_len);
     p += ssl->transform->out_cid_len;
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
     /*
      * Saved fields from top-level ssl_context structure
      */
-#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
-    if( (size_t)( end - p ) < 4 )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if ((size_t) (end - p) < 4) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    ssl->badmac_seen = ( (uint32_t) p[0] << 24 ) |
-                       ( (uint32_t) p[1] << 16 ) |
-                       ( (uint32_t) p[2] <<  8 ) |
-                       ( (uint32_t) p[3]       );
+    ssl->badmac_seen = ((uint32_t) p[0] << 24) |
+                       ((uint32_t) p[1] << 16) |
+                       ((uint32_t) p[2] <<  8) |
+                       ((uint32_t) p[3]);
     p += 4;
-#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
 
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-    if( (size_t)( end - p ) < 16 )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if ((size_t) (end - p) < 16) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    ssl->in_window_top = ( (uint64_t) p[0] << 56 ) |
-                         ( (uint64_t) p[1] << 48 ) |
-                         ( (uint64_t) p[2] << 40 ) |
-                         ( (uint64_t) p[3] << 32 ) |
-                         ( (uint64_t) p[4] << 24 ) |
-                         ( (uint64_t) p[5] << 16 ) |
-                         ( (uint64_t) p[6] <<  8 ) |
-                         ( (uint64_t) p[7]       );
+    ssl->in_window_top = ((uint64_t) p[0] << 56) |
+                         ((uint64_t) p[1] << 48) |
+                         ((uint64_t) p[2] << 40) |
+                         ((uint64_t) p[3] << 32) |
+                         ((uint64_t) p[4] << 24) |
+                         ((uint64_t) p[5] << 16) |
+                         ((uint64_t) p[6] <<  8) |
+                         ((uint64_t) p[7]);
     p += 8;
 
-    ssl->in_window = ( (uint64_t) p[0] << 56 ) |
-                     ( (uint64_t) p[1] << 48 ) |
-                     ( (uint64_t) p[2] << 40 ) |
-                     ( (uint64_t) p[3] << 32 ) |
-                     ( (uint64_t) p[4] << 24 ) |
-                     ( (uint64_t) p[5] << 16 ) |
-                     ( (uint64_t) p[6] <<  8 ) |
-                     ( (uint64_t) p[7]       );
+    ssl->in_window = ((uint64_t) p[0] << 56) |
+                     ((uint64_t) p[1] << 48) |
+                     ((uint64_t) p[2] << 40) |
+                     ((uint64_t) p[3] << 32) |
+                     ((uint64_t) p[4] << 24) |
+                     ((uint64_t) p[5] << 16) |
+                     ((uint64_t) p[6] <<  8) |
+                     ((uint64_t) p[7]);
     p += 8;
 #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( (size_t)( end - p ) < 1 )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if ((size_t) (end - p) < 1) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
     ssl->disable_datagram_packing = *p++;
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-    if( (size_t)( end - p ) < 8 )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    memcpy( ssl->cur_out_ctr, p, 8 );
-    p += 8;
+    if ((size_t) (end - p) < sizeof(ssl->cur_out_ctr)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+    memcpy(ssl->cur_out_ctr, p, sizeof(ssl->cur_out_ctr));
+    p += sizeof(ssl->cur_out_ctr);
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if( (size_t)( end - p ) < 2 )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if ((size_t) (end - p) < 2) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    ssl->mtu = ( p[0] << 8 ) | p[1];
+    ssl->mtu = (p[0] << 8) | p[1];
     p += 2;
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
@@ -6745,19 +4776,17 @@
         uint8_t alpn_len;
         const char **cur;
 
-        if( (size_t)( end - p ) < 1 )
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+        if ((size_t) (end - p) < 1) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
 
         alpn_len = *p++;
 
-        if( alpn_len != 0 && ssl->conf->alpn_list != NULL )
-        {
+        if (alpn_len != 0 && ssl->conf->alpn_list != NULL) {
             /* alpn_chosen should point to an item in the configured list */
-            for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ )
-            {
-                if( strlen( *cur ) == alpn_len &&
-                    memcmp( p, cur, alpn_len ) == 0 )
-                {
+            for (cur = ssl->conf->alpn_list; *cur != NULL; cur++) {
+                if (strlen(*cur) == alpn_len &&
+                    memcmp(p, cur, alpn_len) == 0) {
                     ssl->alpn_chosen = *cur;
                     break;
                 }
@@ -6765,8 +4794,9 @@
         }
 
         /* can only happen on conf mismatch */
-        if( alpn_len != 0 && ssl->alpn_chosen == NULL )
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+        if (alpn_len != 0 && ssl->alpn_chosen == NULL) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
 
         p += alpn_len;
     }
@@ -6779,13 +4809,11 @@
      * mbedtls_ssl_reset(), so we only need to set the remaining ones.
      */
     ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER;
-
-    ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3;
-    ssl->minor_ver = MBEDTLS_SSL_MINOR_VERSION_3;
+    ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
 
     /* Adjust pointers for header fields of outgoing records to
      * the given transform, accounting for explicit IV and CID. */
-    mbedtls_ssl_update_out_pointers( ssl, ssl->transform );
+    mbedtls_ssl_update_out_pointers(ssl, ssl->transform);
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     ssl->in_epoch = 1;
@@ -6795,157 +4823,160 @@
      * which we don't want - otherwise we'd end up freeing the wrong transform
      * by calling mbedtls_ssl_handshake_wrapup_free_hs_transform()
      * inappropriately. */
-    if( ssl->handshake != NULL )
-    {
-        mbedtls_ssl_handshake_free( ssl );
-        mbedtls_free( ssl->handshake );
+    if (ssl->handshake != NULL) {
+        mbedtls_ssl_handshake_free(ssl);
+        mbedtls_free(ssl->handshake);
         ssl->handshake = NULL;
     }
 
     /*
      * Done - should have consumed entire buffer
      */
-    if( p != end )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (p != end) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Deserialize context: public wrapper for error cleaning
  */
-int mbedtls_ssl_context_load( mbedtls_ssl_context *context,
-                              const unsigned char *buf,
-                              size_t len )
+int mbedtls_ssl_context_load(mbedtls_ssl_context *context,
+                             const unsigned char *buf,
+                             size_t len)
 {
-    int ret = ssl_context_load( context, buf, len );
+    int ret = ssl_context_load(context, buf, len);
 
-    if( ret != 0 )
-        mbedtls_ssl_free( context );
+    if (ret != 0) {
+        mbedtls_ssl_free(context);
+    }
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
 
 /*
  * Free an SSL context
  */
-void mbedtls_ssl_free( mbedtls_ssl_context *ssl )
+void mbedtls_ssl_free(mbedtls_ssl_context *ssl)
 {
-    if( ssl == NULL )
+    if (ssl == NULL) {
         return;
+    }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> free" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> free"));
 
-    if( ssl->out_buf != NULL )
-    {
+    if (ssl->out_buf != NULL) {
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
         size_t out_buf_len = ssl->out_buf_len;
 #else
         size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
 #endif
 
-        mbedtls_platform_zeroize( ssl->out_buf, out_buf_len );
-        mbedtls_free( ssl->out_buf );
+        mbedtls_platform_zeroize(ssl->out_buf, out_buf_len);
+        mbedtls_free(ssl->out_buf);
         ssl->out_buf = NULL;
     }
 
-    if( ssl->in_buf != NULL )
-    {
+    if (ssl->in_buf != NULL) {
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
         size_t in_buf_len = ssl->in_buf_len;
 #else
         size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
 #endif
 
-        mbedtls_platform_zeroize( ssl->in_buf, in_buf_len );
-        mbedtls_free( ssl->in_buf );
+        mbedtls_platform_zeroize(ssl->in_buf, in_buf_len);
+        mbedtls_free(ssl->in_buf);
         ssl->in_buf = NULL;
     }
 
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-    if( ssl->compress_buf != NULL )
-    {
-        mbedtls_platform_zeroize( ssl->compress_buf, MBEDTLS_SSL_COMPRESS_BUFFER_LEN );
-        mbedtls_free( ssl->compress_buf );
+    if (ssl->transform) {
+        mbedtls_ssl_transform_free(ssl->transform);
+        mbedtls_free(ssl->transform);
     }
+
+    if (ssl->handshake) {
+        mbedtls_ssl_handshake_free(ssl);
+        mbedtls_free(ssl->handshake);
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        mbedtls_ssl_transform_free(ssl->transform_negotiate);
+        mbedtls_free(ssl->transform_negotiate);
 #endif
 
-    if( ssl->transform )
-    {
-        mbedtls_ssl_transform_free( ssl->transform );
-        mbedtls_free( ssl->transform );
+        mbedtls_ssl_session_free(ssl->session_negotiate);
+        mbedtls_free(ssl->session_negotiate);
     }
 
-    if( ssl->handshake )
-    {
-        mbedtls_ssl_handshake_free( ssl );
-        mbedtls_ssl_transform_free( ssl->transform_negotiate );
-        mbedtls_ssl_session_free( ssl->session_negotiate );
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    mbedtls_ssl_transform_free(ssl->transform_application);
+    mbedtls_free(ssl->transform_application);
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
-        mbedtls_free( ssl->handshake );
-        mbedtls_free( ssl->transform_negotiate );
-        mbedtls_free( ssl->session_negotiate );
-    }
-
-    if( ssl->session )
-    {
-        mbedtls_ssl_session_free( ssl->session );
-        mbedtls_free( ssl->session );
+    if (ssl->session) {
+        mbedtls_ssl_session_free(ssl->session);
+        mbedtls_free(ssl->session);
     }
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
-    if( ssl->hostname != NULL )
-    {
-        mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) );
-        mbedtls_free( ssl->hostname );
-    }
-#endif
-
-#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
-    if( mbedtls_ssl_hw_record_finish != NULL )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_finish()" ) );
-        mbedtls_ssl_hw_record_finish( ssl );
+    if (ssl->hostname != NULL) {
+        mbedtls_platform_zeroize(ssl->hostname, strlen(ssl->hostname));
+        mbedtls_free(ssl->hostname);
     }
 #endif
 
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
-    mbedtls_free( ssl->cli_id );
+    mbedtls_free(ssl->cli_id);
 #endif
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= free" ) );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= free"));
 
     /* Actually clear after last debug message */
-    mbedtls_platform_zeroize( ssl, sizeof( mbedtls_ssl_context ) );
+    mbedtls_platform_zeroize(ssl, sizeof(mbedtls_ssl_context));
 }
 
 /*
- * Initialze mbedtls_ssl_config
+ * Initialize mbedtls_ssl_config
  */
-void mbedtls_ssl_config_init( mbedtls_ssl_config *conf )
+void mbedtls_ssl_config_init(mbedtls_ssl_config *conf)
 {
-    memset( conf, 0, sizeof( mbedtls_ssl_config ) );
+    memset(conf, 0, sizeof(mbedtls_ssl_config));
 }
 
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-static int ssl_preset_default_hashes[] = {
-#if defined(MBEDTLS_SHA512_C)
-    MBEDTLS_MD_SHA512,
+/* The selection should be the same as mbedtls_x509_crt_profile_default in
+ * x509_crt.c, plus Montgomery curves for ECDHE. Here, the order matters:
+ * curves with a lower resource usage come first.
+ * See the documentation of mbedtls_ssl_conf_curves() for what we promise
+ * about this list.
+ */
+static uint16_t ssl_preset_default_groups[] = {
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+    MBEDTLS_SSL_IANA_TLS_GROUP_X25519,
 #endif
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
-    MBEDTLS_MD_SHA384,
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+    MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1,
 #endif
-#if defined(MBEDTLS_SHA256_C)
-    MBEDTLS_MD_SHA256,
-    MBEDTLS_MD_SHA224,
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+    MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1,
 #endif
-#if defined(MBEDTLS_SHA1_C) && defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE)
-    MBEDTLS_MD_SHA1,
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+    MBEDTLS_SSL_IANA_TLS_GROUP_X448,
 #endif
-    MBEDTLS_MD_NONE
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+    MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1,
+#endif
+#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
+    MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1,
+#endif
+#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
+    MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1,
+#endif
+#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
+    MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1,
+#endif
+    MBEDTLS_SSL_IANA_TLS_GROUP_NONE
 };
-#endif
 
 static int ssl_preset_suiteb_ciphersuites[] = {
     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
@@ -6953,47 +4984,243 @@
     0
 };
 
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-static int ssl_preset_suiteb_hashes[] = {
-    MBEDTLS_MD_SHA256,
-    MBEDTLS_MD_SHA384,
-    MBEDTLS_MD_NONE
-};
-#endif
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
 
-#if defined(MBEDTLS_ECP_C)
-static mbedtls_ecp_group_id ssl_preset_suiteb_curves[] = {
+/* NOTICE:
+ *   For ssl_preset_*_sig_algs and ssl_tls12_preset_*_sig_algs, the following
+ *   rules SHOULD be upheld.
+ *   - No duplicate entries.
+ *   - But if there is a good reason, do not change the order of the algorithms.
+ *   - ssl_tls12_preset* is for TLS 1.2 use only.
+ *   - ssl_preset_* is for TLS 1.3 only or hybrid TLS 1.3/1.2 handshakes.
+ */
+static uint16_t ssl_preset_default_sig_algs[] = {
+
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) &&  \
+    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
+    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+    MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256,
+#endif /* MBEDTLS_PK_CAN_ECDSA_SOME && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA &&
+          MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) && \
+    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
+    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+    MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384,
+#endif /* MBEDTLS_PK_CAN_ECDSA_SOME && MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA&&
+          MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) && \
+    defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
+    defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+    MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512,
+#endif /* MBEDTLS_PK_CAN_ECDSA_SOME && MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA&&
+          MBEDTLS_ECP_DP_SECP521R1_ENABLED */
+
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
+    defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512,
+#endif \
+    /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
+    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384,
+#endif \
+    /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
+    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256,
+#endif \
+    /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+
+#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512,
+#endif /* MBEDTLS_RSA_C && MBEDTLS_SHA512_C */
+
+#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384,
+#endif /* MBEDTLS_RSA_C && MBEDTLS_SHA384_C */
+
+#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256,
+#endif /* MBEDTLS_RSA_C && MBEDTLS_SHA256_C */
+
+    MBEDTLS_TLS_SIG_NONE
+};
+
+/* NOTICE: see above */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+static uint16_t ssl_tls12_preset_default_sig_algs[] = {
+#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512),
+#endif
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512,
+#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
+#if defined(MBEDTLS_RSA_C)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA512),
+#endif
+#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384),
+#endif
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384,
+#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
+#if defined(MBEDTLS_RSA_C)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA384),
+#endif
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256),
+#endif
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256,
+#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
+#if defined(MBEDTLS_RSA_C)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA256),
+#endif
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+    MBEDTLS_TLS_SIG_NONE
+};
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+/* NOTICE: see above */
+static uint16_t ssl_preset_suiteb_sig_algs[] = {
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
+    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+    MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256,
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA&&
+          MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
+    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+    MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384,
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA&&
+          MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
+    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256,
+#endif \
+    /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+
+#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256,
+#endif /* MBEDTLS_RSA_C && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+
+    MBEDTLS_TLS_SIG_NONE
+};
+
+/* NOTICE: see above */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+static uint16_t ssl_tls12_preset_suiteb_sig_algs[] = {
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_ECDSA_C)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256),
+#endif
+#if defined(MBEDTLS_RSA_C)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA256),
+#endif
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_ECDSA_C)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384),
+#endif
+#if defined(MBEDTLS_RSA_C)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA384),
+#endif
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+    MBEDTLS_TLS_SIG_NONE
+};
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
+
+static uint16_t ssl_preset_suiteb_groups[] = {
 #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
-    MBEDTLS_ECP_DP_SECP256R1,
+    MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1,
 #endif
 #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
-    MBEDTLS_ECP_DP_SECP384R1,
+    MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1,
 #endif
-    MBEDTLS_ECP_DP_NONE
+    MBEDTLS_SSL_IANA_TLS_GROUP_NONE
 };
-#endif
+
+#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+/* Function for checking `ssl_preset_*_sig_algs` and `ssl_tls12_preset_*_sig_algs`
+ * to make sure there are no duplicated signature algorithm entries. */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_check_no_sig_alg_duplication(uint16_t *sig_algs)
+{
+    size_t i, j;
+    int ret = 0;
+
+    for (i = 0; sig_algs[i] != MBEDTLS_TLS_SIG_NONE; i++) {
+        for (j = 0; j < i; j++) {
+            if (sig_algs[i] != sig_algs[j]) {
+                continue;
+            }
+            mbedtls_printf(" entry(%04x,%" MBEDTLS_PRINTF_SIZET
+                           ") is duplicated at %" MBEDTLS_PRINTF_SIZET "\n",
+                           sig_algs[i], j, i);
+            ret = -1;
+        }
+    }
+    return ret;
+}
+
+#endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
 
 /*
  * Load default in mbedtls_ssl_config
  */
-int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf,
-                                 int endpoint, int transport, int preset )
+int mbedtls_ssl_config_defaults(mbedtls_ssl_config *conf,
+                                int endpoint, int transport, int preset)
 {
 #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 #endif
 
+#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+    if (ssl_check_no_sig_alg_duplication(ssl_preset_suiteb_sig_algs)) {
+        mbedtls_printf("ssl_preset_suiteb_sig_algs has duplicated entries\n");
+        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    }
+
+    if (ssl_check_no_sig_alg_duplication(ssl_preset_default_sig_algs)) {
+        mbedtls_printf("ssl_preset_default_sig_algs has duplicated entries\n");
+        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    if (ssl_check_no_sig_alg_duplication(ssl_tls12_preset_suiteb_sig_algs)) {
+        mbedtls_printf("ssl_tls12_preset_suiteb_sig_algs has duplicated entries\n");
+        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    }
+
+    if (ssl_check_no_sig_alg_duplication(ssl_tls12_preset_default_sig_algs)) {
+        mbedtls_printf("ssl_tls12_preset_default_sig_algs has duplicated entries\n");
+        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+#endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
+
     /* Use the functions here so that they are covered in tests,
      * but otherwise access member directly for efficiency */
-    mbedtls_ssl_conf_endpoint( conf, endpoint );
-    mbedtls_ssl_conf_transport( conf, transport );
+    mbedtls_ssl_conf_endpoint(conf, endpoint);
+    mbedtls_ssl_conf_transport(conf, transport);
 
     /*
      * Things that are common to all presets
      */
 #if defined(MBEDTLS_SSL_CLI_C)
-    if( endpoint == MBEDTLS_SSL_IS_CLIENT )
-    {
+    if (endpoint == MBEDTLS_SSL_IS_CLIENT) {
         conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED;
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
         conf->session_tickets = MBEDTLS_SSL_SESSION_TICKETS_ENABLED;
@@ -7001,10 +5228,6 @@
     }
 #endif
 
-#if defined(MBEDTLS_ARC4_C)
-    conf->arc4_disabled = MBEDTLS_SSL_ARC4_DISABLED;
-#endif
-
 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
     conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED;
 #endif
@@ -7013,10 +5236,6 @@
     conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED;
 #endif
 
-#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
-    conf->cbc_record_splitting = MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED;
-#endif
-
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
     conf->f_cookie_write = ssl_cookie_write_dummy;
     conf->f_cookie_check = ssl_cookie_check_dummy;
@@ -7028,6 +5247,7 @@
 
 #if defined(MBEDTLS_SSL_SRV_C)
     conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED;
+    conf->respect_cli_pref = MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER;
 #endif
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
@@ -7037,390 +5257,456 @@
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
     conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT;
-    memset( conf->renego_period,     0x00, 2 );
-    memset( conf->renego_period + 2, 0xFF, 6 );
+    memset(conf->renego_period,     0x00, 2);
+    memset(conf->renego_period + 2, 0xFF, 6);
 #endif
 
 #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)
-            if( endpoint == MBEDTLS_SSL_IS_SERVER )
-            {
-                const unsigned char dhm_p[] =
-                    MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN;
-                const unsigned char dhm_g[] =
-                    MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN;
+    if (endpoint == MBEDTLS_SSL_IS_SERVER) {
+        const unsigned char dhm_p[] =
+            MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN;
+        const unsigned char dhm_g[] =
+            MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN;
 
-                if ( ( ret = mbedtls_ssl_conf_dh_param_bin( conf,
-                                               dhm_p, sizeof( dhm_p ),
-                                               dhm_g, sizeof( dhm_g ) ) ) != 0 )
-                {
-                    return( ret );
-                }
-            }
+        if ((ret = mbedtls_ssl_conf_dh_param_bin(conf,
+                                                 dhm_p, sizeof(dhm_p),
+                                                 dhm_g, sizeof(dhm_g))) != 0) {
+            return ret;
+        }
+    }
 #endif
 
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    mbedtls_ssl_tls13_conf_early_data(conf, MBEDTLS_SSL_EARLY_DATA_DISABLED);
+#if defined(MBEDTLS_SSL_SRV_C)
+    mbedtls_ssl_tls13_conf_max_early_data_size(
+        conf, MBEDTLS_SSL_MAX_EARLY_DATA_SIZE);
+#endif
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SESSION_TICKETS)
+    mbedtls_ssl_conf_new_session_tickets(
+        conf, MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS);
+#endif
+    /*
+     * Allow all TLS 1.3 key exchange modes by default.
+     */
+    conf->tls13_kex_modes = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+    if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+        conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+#else
+        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+#endif
+    } else {
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        if (endpoint == MBEDTLS_SSL_IS_CLIENT) {
+            conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+            conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
+        } else {
+            /* Hybrid TLS 1.2 / 1.3 is not supported on server side yet */
+            conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+            conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+        }
+#elif defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
+        conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
+#elif defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+        conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+#else
+        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+#endif
+    }
+
     /*
      * Preset-specific defaults
      */
-    switch( preset )
-    {
+    switch (preset) {
         /*
          * NSA Suite B
          */
         case MBEDTLS_SSL_PRESET_SUITEB:
-            conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3;
-            conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */
-            conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION;
-            conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION;
 
-            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] =
-            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] =
-            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] =
-            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] =
-                                   ssl_preset_suiteb_ciphersuites;
+            conf->ciphersuite_list = ssl_preset_suiteb_ciphersuites;
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
             conf->cert_profile = &mbedtls_x509_crt_profile_suiteb;
 #endif
 
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-            conf->sig_hashes = ssl_preset_suiteb_hashes;
-#endif
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+            if (mbedtls_ssl_conf_is_tls12_only(conf)) {
+                conf->sig_algs = ssl_tls12_preset_suiteb_sig_algs;
+            } else
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+            conf->sig_algs = ssl_preset_suiteb_sig_algs;
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
 
-#if defined(MBEDTLS_ECP_C)
-            conf->curve_list = ssl_preset_suiteb_curves;
+#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
+            conf->curve_list = NULL;
 #endif
+            conf->group_list = ssl_preset_suiteb_groups;
             break;
 
         /*
          * Default
          */
         default:
-            conf->min_major_ver = ( MBEDTLS_SSL_MIN_MAJOR_VERSION >
-                                    MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION ) ?
-                                    MBEDTLS_SSL_MIN_MAJOR_VERSION :
-                                    MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION;
-            conf->min_minor_ver = ( MBEDTLS_SSL_MIN_MINOR_VERSION >
-                                    MBEDTLS_SSL_MIN_VALID_MINOR_VERSION ) ?
-                                    MBEDTLS_SSL_MIN_MINOR_VERSION :
-                                    MBEDTLS_SSL_MIN_VALID_MINOR_VERSION;
-            conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION;
-            conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION;
 
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-            if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-                conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_2;
-#endif
-
-            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] =
-            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] =
-            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] =
-            conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] =
-                                   mbedtls_ssl_list_ciphersuites();
+            conf->ciphersuite_list = mbedtls_ssl_list_ciphersuites();
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
             conf->cert_profile = &mbedtls_x509_crt_profile_default;
 #endif
 
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-            conf->sig_hashes = ssl_preset_default_hashes;
-#endif
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+            if (mbedtls_ssl_conf_is_tls12_only(conf)) {
+                conf->sig_algs = ssl_tls12_preset_default_sig_algs;
+            } else
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+            conf->sig_algs = ssl_preset_default_sig_algs;
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
 
-#if defined(MBEDTLS_ECP_C)
-            conf->curve_list = mbedtls_ecp_grp_id_list();
+#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
+            conf->curve_list = NULL;
 #endif
+            conf->group_list = ssl_preset_default_groups;
 
 #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C)
             conf->dhm_min_bitlen = 1024;
 #endif
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Free mbedtls_ssl_config
  */
-void mbedtls_ssl_config_free( mbedtls_ssl_config *conf )
+void mbedtls_ssl_config_free(mbedtls_ssl_config *conf)
 {
 #if defined(MBEDTLS_DHM_C)
-    mbedtls_mpi_free( &conf->dhm_P );
-    mbedtls_mpi_free( &conf->dhm_G );
+    mbedtls_mpi_free(&conf->dhm_P);
+    mbedtls_mpi_free(&conf->dhm_G);
 #endif
 
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
-    if( conf->psk != NULL )
-    {
-        mbedtls_platform_zeroize( conf->psk, conf->psk_len );
-        mbedtls_free( conf->psk );
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) {
+        conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    if (conf->psk != NULL) {
+        mbedtls_platform_zeroize(conf->psk, conf->psk_len);
+        mbedtls_free(conf->psk);
         conf->psk = NULL;
         conf->psk_len = 0;
     }
 
-    if( conf->psk_identity != NULL )
-    {
-        mbedtls_platform_zeroize( conf->psk_identity, conf->psk_identity_len );
-        mbedtls_free( conf->psk_identity );
+    if (conf->psk_identity != NULL) {
+        mbedtls_platform_zeroize(conf->psk_identity, conf->psk_identity_len);
+        mbedtls_free(conf->psk_identity);
         conf->psk_identity = NULL;
         conf->psk_identity_len = 0;
     }
-#endif
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
-    ssl_key_cert_free( conf->key_cert );
+    ssl_key_cert_free(conf->key_cert);
 #endif
 
-    mbedtls_platform_zeroize( conf, sizeof( mbedtls_ssl_config ) );
+    mbedtls_platform_zeroize(conf, sizeof(mbedtls_ssl_config));
 }
 
 #if defined(MBEDTLS_PK_C) && \
-    ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) )
+    (defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_CAN_ECDSA_SOME))
 /*
  * Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX
  */
-unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk )
+unsigned char mbedtls_ssl_sig_from_pk(mbedtls_pk_context *pk)
 {
 #if defined(MBEDTLS_RSA_C)
-    if( mbedtls_pk_can_do( pk, MBEDTLS_PK_RSA ) )
-        return( MBEDTLS_SSL_SIG_RSA );
+    if (mbedtls_pk_can_do(pk, MBEDTLS_PK_RSA)) {
+        return MBEDTLS_SSL_SIG_RSA;
+    }
 #endif
-#if defined(MBEDTLS_ECDSA_C)
-    if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECDSA ) )
-        return( MBEDTLS_SSL_SIG_ECDSA );
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
+    if (mbedtls_pk_can_do(pk, MBEDTLS_PK_ECDSA)) {
+        return MBEDTLS_SSL_SIG_ECDSA;
+    }
 #endif
-    return( MBEDTLS_SSL_SIG_ANON );
+    return MBEDTLS_SSL_SIG_ANON;
 }
 
-unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type )
+unsigned char mbedtls_ssl_sig_from_pk_alg(mbedtls_pk_type_t type)
 {
-    switch( type ) {
+    switch (type) {
         case MBEDTLS_PK_RSA:
-            return( MBEDTLS_SSL_SIG_RSA );
+            return MBEDTLS_SSL_SIG_RSA;
         case MBEDTLS_PK_ECDSA:
         case MBEDTLS_PK_ECKEY:
-            return( MBEDTLS_SSL_SIG_ECDSA );
+            return MBEDTLS_SSL_SIG_ECDSA;
         default:
-            return( MBEDTLS_SSL_SIG_ANON );
+            return MBEDTLS_SSL_SIG_ANON;
     }
 }
 
-mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig )
+mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig(unsigned char sig)
 {
-    switch( sig )
-    {
+    switch (sig) {
 #if defined(MBEDTLS_RSA_C)
         case MBEDTLS_SSL_SIG_RSA:
-            return( MBEDTLS_PK_RSA );
+            return MBEDTLS_PK_RSA;
 #endif
-#if defined(MBEDTLS_ECDSA_C)
+#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
         case MBEDTLS_SSL_SIG_ECDSA:
-            return( MBEDTLS_PK_ECDSA );
+            return MBEDTLS_PK_ECDSA;
 #endif
         default:
-            return( MBEDTLS_PK_NONE );
+            return MBEDTLS_PK_NONE;
     }
 }
-#endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_ECDSA_C ) */
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
-    defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-
-/* Find an entry in a signature-hash set matching a given hash algorithm. */
-mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set,
-                                                 mbedtls_pk_type_t sig_alg )
-{
-    switch( sig_alg )
-    {
-        case MBEDTLS_PK_RSA:
-            return( set->rsa );
-        case MBEDTLS_PK_ECDSA:
-            return( set->ecdsa );
-        default:
-            return( MBEDTLS_MD_NONE );
-    }
-}
-
-/* Add a signature-hash-pair to a signature-hash set */
-void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set,
-                                   mbedtls_pk_type_t sig_alg,
-                                   mbedtls_md_type_t md_alg )
-{
-    switch( sig_alg )
-    {
-        case MBEDTLS_PK_RSA:
-            if( set->rsa == MBEDTLS_MD_NONE )
-                set->rsa = md_alg;
-            break;
-
-        case MBEDTLS_PK_ECDSA:
-            if( set->ecdsa == MBEDTLS_MD_NONE )
-                set->ecdsa = md_alg;
-            break;
-
-        default:
-            break;
-    }
-}
-
-/* Allow exactly one hash algorithm for each signature. */
-void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set,
-                                          mbedtls_md_type_t md_alg )
-{
-    set->rsa   = md_alg;
-    set->ecdsa = md_alg;
-}
-
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2) &&
-          MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+#endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_PK_CAN_ECDSA_SOME ) */
 
 /*
  * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX
  */
-mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash )
+mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash(unsigned char hash)
 {
-    switch( hash )
-    {
-#if defined(MBEDTLS_MD5_C)
+    switch (hash) {
+#if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
         case MBEDTLS_SSL_HASH_MD5:
-            return( MBEDTLS_MD_MD5 );
+            return MBEDTLS_MD_MD5;
 #endif
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
         case MBEDTLS_SSL_HASH_SHA1:
-            return( MBEDTLS_MD_SHA1 );
+            return MBEDTLS_MD_SHA1;
 #endif
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
         case MBEDTLS_SSL_HASH_SHA224:
-            return( MBEDTLS_MD_SHA224 );
+            return MBEDTLS_MD_SHA224;
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
         case MBEDTLS_SSL_HASH_SHA256:
-            return( MBEDTLS_MD_SHA256 );
+            return MBEDTLS_MD_SHA256;
 #endif
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
         case MBEDTLS_SSL_HASH_SHA384:
-            return( MBEDTLS_MD_SHA384 );
+            return MBEDTLS_MD_SHA384;
 #endif
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
         case MBEDTLS_SSL_HASH_SHA512:
-            return( MBEDTLS_MD_SHA512 );
+            return MBEDTLS_MD_SHA512;
 #endif
         default:
-            return( MBEDTLS_MD_NONE );
+            return MBEDTLS_MD_NONE;
     }
 }
 
 /*
  * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX
  */
-unsigned char mbedtls_ssl_hash_from_md_alg( int md )
+unsigned char mbedtls_ssl_hash_from_md_alg(int md)
 {
-    switch( md )
-    {
-#if defined(MBEDTLS_MD5_C)
+    switch (md) {
+#if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
         case MBEDTLS_MD_MD5:
-            return( MBEDTLS_SSL_HASH_MD5 );
+            return MBEDTLS_SSL_HASH_MD5;
 #endif
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
         case MBEDTLS_MD_SHA1:
-            return( MBEDTLS_SSL_HASH_SHA1 );
+            return MBEDTLS_SSL_HASH_SHA1;
 #endif
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
         case MBEDTLS_MD_SHA224:
-            return( MBEDTLS_SSL_HASH_SHA224 );
+            return MBEDTLS_SSL_HASH_SHA224;
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
         case MBEDTLS_MD_SHA256:
-            return( MBEDTLS_SSL_HASH_SHA256 );
+            return MBEDTLS_SSL_HASH_SHA256;
 #endif
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
         case MBEDTLS_MD_SHA384:
-            return( MBEDTLS_SSL_HASH_SHA384 );
+            return MBEDTLS_SSL_HASH_SHA384;
 #endif
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
         case MBEDTLS_MD_SHA512:
-            return( MBEDTLS_SSL_HASH_SHA512 );
+            return MBEDTLS_SSL_HASH_SHA512;
 #endif
         default:
-            return( MBEDTLS_SSL_HASH_NONE );
+            return MBEDTLS_SSL_HASH_NONE;
     }
 }
 
-#if defined(MBEDTLS_ECP_C)
 /*
  * Check if a curve proposed by the peer is in our list.
  * Return 0 if we're willing to use it, -1 otherwise.
  */
-int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id )
+int mbedtls_ssl_check_curve_tls_id(const mbedtls_ssl_context *ssl, uint16_t tls_id)
 {
-    const mbedtls_ecp_group_id *gid;
+    const uint16_t *group_list = mbedtls_ssl_get_groups(ssl);
 
-    if( ssl->conf->curve_list == NULL )
-        return( -1 );
+    if (group_list == NULL) {
+        return -1;
+    }
 
-    for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ )
-        if( *gid == grp_id )
-            return( 0 );
+    for (; *group_list != 0; group_list++) {
+        if (*group_list == tls_id) {
+            return 0;
+        }
+    }
 
-    return( -1 );
+    return -1;
 }
 
+#if defined(MBEDTLS_ECP_C)
 /*
- * Same as mbedtls_ssl_check_curve() but takes a TLS ID for the curve.
+ * Same as mbedtls_ssl_check_curve_tls_id() but with a mbedtls_ecp_group_id.
  */
-int mbedtls_ssl_check_curve_tls_id( const mbedtls_ssl_context *ssl, uint16_t tls_id )
+int mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id)
 {
-    const mbedtls_ecp_curve_info *curve_info =
-        mbedtls_ecp_curve_info_from_tls_id( tls_id );
-    if( curve_info == NULL )
-        return( -1 );
-    return( mbedtls_ssl_check_curve( ssl, curve_info->grp_id ) );
+    uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id);
+
+    if (tls_id == 0) {
+        return -1;
+    }
+
+    return mbedtls_ssl_check_curve_tls_id(ssl, tls_id);
 }
 #endif /* MBEDTLS_ECP_C */
 
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-/*
- * Check if a hash proposed by the peer is in our list.
- * Return 0 if we're willing to use it, -1 otherwise.
- */
-int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl,
-                                mbedtls_md_type_t md )
+#if defined(MBEDTLS_DEBUG_C)
+#define EC_NAME(_name_)     _name_
+#else
+#define EC_NAME(_name_)     NULL
+#endif
+
+static const struct {
+    uint16_t tls_id;
+    mbedtls_ecp_group_id ecp_group_id;
+    psa_ecc_family_t psa_family;
+    uint16_t bits;
+    const char *name;
+} tls_id_match_table[] =
 {
-    const int *cur;
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_521)
+    { 25, MBEDTLS_ECP_DP_SECP521R1, PSA_ECC_FAMILY_SECP_R1, 521, EC_NAME("secp521r1") },
+#endif
+#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
+    { 28, MBEDTLS_ECP_DP_BP512R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 512, EC_NAME("brainpoolP512r1") },
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_384)
+    { 24, MBEDTLS_ECP_DP_SECP384R1, PSA_ECC_FAMILY_SECP_R1, 384, EC_NAME("secp384r1") },
+#endif
+#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
+    { 27, MBEDTLS_ECP_DP_BP384R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 384, EC_NAME("brainpoolP384r1") },
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_256)
+    { 23, MBEDTLS_ECP_DP_SECP256R1, PSA_ECC_FAMILY_SECP_R1, 256, EC_NAME("secp256r1") },
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_256)
+    { 22, MBEDTLS_ECP_DP_SECP256K1, PSA_ECC_FAMILY_SECP_K1, 256, EC_NAME("secp256k1") },
+#endif
+#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
+    { 26, MBEDTLS_ECP_DP_BP256R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 256, EC_NAME("brainpoolP256r1") },
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_224)
+    { 21, MBEDTLS_ECP_DP_SECP224R1, PSA_ECC_FAMILY_SECP_R1, 224, EC_NAME("secp224r1") },
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_224)
+    { 20, MBEDTLS_ECP_DP_SECP224K1, PSA_ECC_FAMILY_SECP_K1, 224, EC_NAME("secp224k1") },
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_192)
+    { 19, MBEDTLS_ECP_DP_SECP192R1, PSA_ECC_FAMILY_SECP_R1, 192, EC_NAME("secp192r1") },
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_192)
+    { 18, MBEDTLS_ECP_DP_SECP192K1, PSA_ECC_FAMILY_SECP_K1, 192, EC_NAME("secp192k1") },
+#endif
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_255)
+    { 29, MBEDTLS_ECP_DP_CURVE25519, PSA_ECC_FAMILY_MONTGOMERY, 255, EC_NAME("x25519") },
+#endif
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_448)
+    { 30, MBEDTLS_ECP_DP_CURVE448, PSA_ECC_FAMILY_MONTGOMERY, 448, EC_NAME("x448") },
+#endif
+    { 0, MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
+};
 
-    if( ssl->conf->sig_hashes == NULL )
-        return( -1 );
+int mbedtls_ssl_get_psa_curve_info_from_tls_id(uint16_t tls_id,
+                                               psa_ecc_family_t *family,
+                                               size_t *bits)
+{
+    for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) {
+        if (tls_id_match_table[i].tls_id == tls_id) {
+            if (family != NULL) {
+                *family = tls_id_match_table[i].psa_family;
+            }
+            if (bits != NULL) {
+                *bits = tls_id_match_table[i].bits;
+            }
+            return PSA_SUCCESS;
+        }
+    }
 
-    for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ )
-        if( *cur == (int) md )
-            return( 0 );
-
-    return( -1 );
+    return PSA_ERROR_NOT_SUPPORTED;
 }
-#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
+mbedtls_ecp_group_id mbedtls_ssl_get_ecp_group_id_from_tls_id(uint16_t tls_id)
+{
+    for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) {
+        if (tls_id_match_table[i].tls_id == tls_id) {
+            return tls_id_match_table[i].ecp_group_id;
+        }
+    }
+
+    return MBEDTLS_ECP_DP_NONE;
+}
+
+uint16_t mbedtls_ssl_get_tls_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id)
+{
+    for (int i = 0; tls_id_match_table[i].ecp_group_id != MBEDTLS_ECP_DP_NONE;
+         i++) {
+        if (tls_id_match_table[i].ecp_group_id == grp_id) {
+            return tls_id_match_table[i].tls_id;
+        }
+    }
+
+    return 0;
+}
+
+#if defined(MBEDTLS_DEBUG_C)
+const char *mbedtls_ssl_get_curve_name_from_tls_id(uint16_t tls_id)
+{
+    for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) {
+        if (tls_id_match_table[i].tls_id == tls_id) {
+            return tls_id_match_table[i].name;
+        }
+    }
+
+    return NULL;
+}
+#endif
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
-int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert,
-                          const mbedtls_ssl_ciphersuite_t *ciphersuite,
-                          int cert_endpoint,
-                          uint32_t *flags )
+int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert,
+                                 const mbedtls_ssl_ciphersuite_t *ciphersuite,
+                                 int cert_endpoint,
+                                 uint32_t *flags)
 {
     int ret = 0;
-#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
     int usage = 0;
-#endif
-#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
     const char *ext_oid;
     size_t ext_len;
-#endif
 
-#if !defined(MBEDTLS_X509_CHECK_KEY_USAGE) &&          \
-    !defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
-    ((void) cert);
-    ((void) cert_endpoint);
-    ((void) flags);
-#endif
-
-#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
-    if( cert_endpoint == MBEDTLS_SSL_IS_SERVER )
-    {
+    if (cert_endpoint == MBEDTLS_SSL_IS_SERVER) {
         /* Server part of the key exchange */
-        switch( ciphersuite->key_exchange )
-        {
+        switch (ciphersuite->key_exchange) {
             case MBEDTLS_KEY_EXCHANGE_RSA:
             case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
                 usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT;
@@ -7445,252 +5731,3111 @@
             case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
                 usage = 0;
         }
-    }
-    else
-    {
+    } else {
         /* Client auth: we only implement rsa_sign and mbedtls_ecdsa_sign for now */
         usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
     }
 
-    if( mbedtls_x509_crt_check_key_usage( cert, usage ) != 0 )
-    {
+    if (mbedtls_x509_crt_check_key_usage(cert, usage) != 0) {
         *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE;
         ret = -1;
     }
-#else
-    ((void) ciphersuite);
-#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */
 
-#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
-    if( cert_endpoint == MBEDTLS_SSL_IS_SERVER )
-    {
+    if (cert_endpoint == MBEDTLS_SSL_IS_SERVER) {
         ext_oid = MBEDTLS_OID_SERVER_AUTH;
-        ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_SERVER_AUTH );
-    }
-    else
-    {
+        ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH);
+    } else {
         ext_oid = MBEDTLS_OID_CLIENT_AUTH;
-        ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_CLIENT_AUTH );
+        ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH);
     }
 
-    if( mbedtls_x509_crt_check_extended_key_usage( cert, ext_oid, ext_len ) != 0 )
-    {
+    if (mbedtls_x509_crt_check_extended_key_usage(cert, ext_oid, ext_len) != 0) {
         *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE;
         ret = -1;
     }
-#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
-int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md )
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl,
+                                         const mbedtls_md_type_t md,
+                                         unsigned char *dst,
+                                         size_t dst_len,
+                                         size_t *olen)
 {
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 )
-        return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_hash_operation_t *hash_operation_to_clone;
+    psa_hash_operation_t hash_operation = psa_hash_operation_init();
 
-    switch( md )
-    {
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
-#if defined(MBEDTLS_MD5_C)
-        case MBEDTLS_SSL_HASH_MD5:
-            return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH;
-#endif
-#if defined(MBEDTLS_SHA1_C)
-        case MBEDTLS_SSL_HASH_SHA1:
-            ssl->handshake->calc_verify = ssl_calc_verify_tls;
+    *olen = 0;
+
+    switch (md) {
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_MD_SHA384:
+            hash_operation_to_clone = &ssl->handshake->fin_sha384_psa;
             break;
 #endif
-#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
+
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_MD_SHA256:
+            hash_operation_to_clone = &ssl->handshake->fin_sha256_psa;
+            break;
+#endif
+
+        default:
+            goto exit;
+    }
+
+    status = psa_hash_clone(hash_operation_to_clone, &hash_operation);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_finish(&hash_operation, dst, dst_len, olen);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+exit:
+#if !defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
+    !defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    (void) ssl;
+#endif
+    return PSA_TO_MBEDTLS_ERR(status);
+}
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_get_handshake_transcript_sha384(mbedtls_ssl_context *ssl,
+                                               unsigned char *dst,
+                                               size_t dst_len,
+                                               size_t *olen)
+{
+    int ret;
+    mbedtls_md_context_t sha384;
+
+    if (dst_len < 48) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    mbedtls_md_init(&sha384);
+    ret = mbedtls_md_setup(&sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_md_clone(&sha384, &ssl->handshake->fin_sha384);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    if ((ret = mbedtls_md_finish(&sha384, dst)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret);
+        goto exit;
+    }
+
+    *olen = 48;
+
+exit:
+
+    mbedtls_md_free(&sha384);
+    return ret;
+}
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_get_handshake_transcript_sha256(mbedtls_ssl_context *ssl,
+                                               unsigned char *dst,
+                                               size_t dst_len,
+                                               size_t *olen)
+{
+    int ret;
+    mbedtls_md_context_t sha256;
+
+    if (dst_len < 32) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    mbedtls_md_init(&sha256);
+    ret = mbedtls_md_setup(&sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_md_clone(&sha256, &ssl->handshake->fin_sha256);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    if ((ret = mbedtls_md_finish(&sha256, dst)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret);
+        goto exit;
+    }
+
+    *olen = 32;
+
+exit:
+
+    mbedtls_md_free(&sha256);
+    return ret;
+}
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+
+int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl,
+                                         const mbedtls_md_type_t md,
+                                         unsigned char *dst,
+                                         size_t dst_len,
+                                         size_t *olen)
+{
+    switch (md) {
+
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_MD_SHA384:
+            return ssl_get_handshake_transcript_sha384(ssl, dst, dst_len, olen);
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+        case MBEDTLS_MD_SHA256:
+            return ssl_get_handshake_transcript_sha256(ssl, dst, dst_len, olen);
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+
+        default:
+#if !defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
+            !defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+            (void) ssl;
+            (void) dst;
+            (void) dst_len;
+            (void) olen;
+#endif
+            break;
+    }
+    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+}
+
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+/* mbedtls_ssl_parse_sig_alg_ext()
+ *
+ * The `extension_data` field of signature algorithm contains  a `SignatureSchemeList`
+ * value (TLS 1.3 RFC8446):
+ *      enum {
+ *         ....
+ *        ecdsa_secp256r1_sha256( 0x0403 ),
+ *        ecdsa_secp384r1_sha384( 0x0503 ),
+ *        ecdsa_secp521r1_sha512( 0x0603 ),
+ *         ....
+ *      } SignatureScheme;
+ *
+ *      struct {
+ *         SignatureScheme supported_signature_algorithms<2..2^16-2>;
+ *      } SignatureSchemeList;
+ *
+ * The `extension_data` field of signature algorithm contains a `SignatureAndHashAlgorithm`
+ * value (TLS 1.2 RFC5246):
+ *      enum {
+ *          none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
+ *          sha512(6), (255)
+ *      } HashAlgorithm;
+ *
+ *      enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
+ *        SignatureAlgorithm;
+ *
+ *      struct {
+ *          HashAlgorithm hash;
+ *          SignatureAlgorithm signature;
+ *      } SignatureAndHashAlgorithm;
+ *
+ *      SignatureAndHashAlgorithm
+ *        supported_signature_algorithms<2..2^16-2>;
+ *
+ * The TLS 1.3 signature algorithm extension was defined to be a compatible
+ * generalization of the TLS 1.2 signature algorithm extension.
+ * `SignatureAndHashAlgorithm` field of TLS 1.2 can be represented by
+ * `SignatureScheme` field of TLS 1.3
+ *
+ */
+int mbedtls_ssl_parse_sig_alg_ext(mbedtls_ssl_context *ssl,
+                                  const unsigned char *buf,
+                                  const unsigned char *end)
+{
+    const unsigned char *p = buf;
+    size_t supported_sig_algs_len = 0;
+    const unsigned char *supported_sig_algs_end;
+    uint16_t sig_alg;
+    uint32_t common_idx = 0;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    supported_sig_algs_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+
+    memset(ssl->handshake->received_sig_algs, 0,
+           sizeof(ssl->handshake->received_sig_algs));
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, supported_sig_algs_len);
+    supported_sig_algs_end = p + supported_sig_algs_len;
+    while (p < supported_sig_algs_end) {
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, supported_sig_algs_end, 2);
+        sig_alg = MBEDTLS_GET_UINT16_BE(p, 0);
+        p += 2;
+        MBEDTLS_SSL_DEBUG_MSG(4, ("received signature algorithm: 0x%x %s",
+                                  sig_alg,
+                                  mbedtls_ssl_sig_alg_to_str(sig_alg)));
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2 &&
+            (!(mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg) &&
+               mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg)))) {
+            continue;
+        }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+        MBEDTLS_SSL_DEBUG_MSG(4, ("valid signature algorithm: %s",
+                                  mbedtls_ssl_sig_alg_to_str(sig_alg)));
+
+        if (common_idx + 1 < MBEDTLS_RECEIVED_SIG_ALGS_SIZE) {
+            ssl->handshake->received_sig_algs[common_idx] = sig_alg;
+            common_idx += 1;
+        }
+    }
+    /* Check that we consumed all the message. */
+    if (p != end) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("Signature algorithms extension length misaligned"));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
+                                     MBEDTLS_ERR_SSL_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    if (common_idx == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("no signature algorithm in common"));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
+                                     MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+    ssl->handshake->received_sig_algs[common_idx] = MBEDTLS_TLS_SIG_NONE;
+    return 0;
+}
+
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+
+static psa_status_t setup_psa_key_derivation(psa_key_derivation_operation_t *derivation,
+                                             mbedtls_svc_key_id_t key,
+                                             psa_algorithm_t alg,
+                                             const unsigned char *raw_psk, size_t raw_psk_length,
+                                             const unsigned char *seed, size_t seed_length,
+                                             const unsigned char *label, size_t label_length,
+                                             const unsigned char *other_secret,
+                                             size_t other_secret_length,
+                                             size_t capacity)
+{
+    psa_status_t status;
+
+    status = psa_key_derivation_setup(derivation, alg);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    if (PSA_ALG_IS_TLS12_PRF(alg) || PSA_ALG_IS_TLS12_PSK_TO_MS(alg)) {
+        status = psa_key_derivation_input_bytes(derivation,
+                                                PSA_KEY_DERIVATION_INPUT_SEED,
+                                                seed, seed_length);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+
+        if (other_secret != NULL) {
+            status = psa_key_derivation_input_bytes(derivation,
+                                                    PSA_KEY_DERIVATION_INPUT_OTHER_SECRET,
+                                                    other_secret, other_secret_length);
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+        }
+
+        if (mbedtls_svc_key_id_is_null(key)) {
+            status = psa_key_derivation_input_bytes(
+                derivation, PSA_KEY_DERIVATION_INPUT_SECRET,
+                raw_psk, raw_psk_length);
+        } else {
+            status = psa_key_derivation_input_key(
+                derivation, PSA_KEY_DERIVATION_INPUT_SECRET, key);
+        }
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+
+        status = psa_key_derivation_input_bytes(derivation,
+                                                PSA_KEY_DERIVATION_INPUT_LABEL,
+                                                label, label_length);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+    } else {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    status = psa_key_derivation_set_capacity(derivation, capacity);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    return PSA_SUCCESS;
+}
+
+#if defined(PSA_WANT_ALG_SHA_384) || \
+    defined(PSA_WANT_ALG_SHA_256)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int tls_prf_generic(mbedtls_md_type_t md_type,
+                           const unsigned char *secret, size_t slen,
+                           const char *label,
+                           const unsigned char *random, size_t rlen,
+                           unsigned char *dstbuf, size_t dlen)
+{
+    psa_status_t status;
+    psa_algorithm_t alg;
+    mbedtls_svc_key_id_t master_key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_derivation_operation_t derivation =
+        PSA_KEY_DERIVATION_OPERATION_INIT;
+
+    if (md_type == MBEDTLS_MD_SHA384) {
+        alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384);
+    } else {
+        alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256);
+    }
+
+    /* Normally a "secret" should be long enough to be impossible to
+     * find by brute force, and in particular should not be empty. But
+     * this PRF is also used to derive an IV, in particular in EAP-TLS,
+     * and for this use case it makes sense to have a 0-length "secret".
+     * Since the key API doesn't allow importing a key of length 0,
+     * keep master_key=0, which setup_psa_key_derivation() understands
+     * to mean a 0-length "secret" input. */
+    if (slen != 0) {
+        psa_key_attributes_t key_attributes = psa_key_attributes_init();
+        psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
+        psa_set_key_algorithm(&key_attributes, alg);
+        psa_set_key_type(&key_attributes, PSA_KEY_TYPE_DERIVE);
+
+        status = psa_import_key(&key_attributes, secret, slen, &master_key);
+        if (status != PSA_SUCCESS) {
+            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+        }
+    }
+
+    status = setup_psa_key_derivation(&derivation,
+                                      master_key, alg,
+                                      NULL, 0,
+                                      random, rlen,
+                                      (unsigned char const *) label,
+                                      (size_t) strlen(label),
+                                      NULL, 0,
+                                      dlen);
+    if (status != PSA_SUCCESS) {
+        psa_key_derivation_abort(&derivation);
+        psa_destroy_key(master_key);
+        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+    }
+
+    status = psa_key_derivation_output_bytes(&derivation, dstbuf, dlen);
+    if (status != PSA_SUCCESS) {
+        psa_key_derivation_abort(&derivation);
+        psa_destroy_key(master_key);
+        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+    }
+
+    status = psa_key_derivation_abort(&derivation);
+    if (status != PSA_SUCCESS) {
+        psa_destroy_key(master_key);
+        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+    }
+
+    if (!mbedtls_svc_key_id_is_null(master_key)) {
+        status = psa_destroy_key(master_key);
+    }
+    if (status != PSA_SUCCESS) {
+        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+    }
+
+    return 0;
+}
+#endif /* PSA_WANT_ALG_SHA_256 || PSA_WANT_ALG_SHA_384 */
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_MD_C) &&       \
+    (defined(MBEDTLS_SHA256_C) || \
+    defined(MBEDTLS_SHA384_C))
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int tls_prf_generic(mbedtls_md_type_t md_type,
+                           const unsigned char *secret, size_t slen,
+                           const char *label,
+                           const unsigned char *random, size_t rlen,
+                           unsigned char *dstbuf, size_t dlen)
+{
+    size_t nb;
+    size_t i, j, k, md_len;
+    unsigned char *tmp;
+    size_t tmp_len = 0;
+    unsigned char h_i[MBEDTLS_MD_MAX_SIZE];
+    const mbedtls_md_info_t *md_info;
+    mbedtls_md_context_t md_ctx;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    mbedtls_md_init(&md_ctx);
+
+    if ((md_info = mbedtls_md_info_from_type(md_type)) == NULL) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    md_len = mbedtls_md_get_size(md_info);
+
+    tmp_len = md_len + strlen(label) + rlen;
+    tmp = mbedtls_calloc(1, tmp_len);
+    if (tmp == NULL) {
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        goto exit;
+    }
+
+    nb = strlen(label);
+    memcpy(tmp + md_len, label, nb);
+    memcpy(tmp + md_len + nb, random, rlen);
+    nb += rlen;
+
+    /*
+     * Compute P_<hash>(secret, label + random)[0..dlen]
+     */
+    if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) {
+        goto exit;
+    }
+
+    ret = mbedtls_md_hmac_starts(&md_ctx, secret, slen);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_md_hmac_update(&md_ctx, tmp + md_len, nb);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_md_hmac_finish(&md_ctx, tmp);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    for (i = 0; i < dlen; i += md_len) {
+        ret = mbedtls_md_hmac_reset(&md_ctx);
+        if (ret != 0) {
+            goto exit;
+        }
+        ret = mbedtls_md_hmac_update(&md_ctx, tmp, md_len + nb);
+        if (ret != 0) {
+            goto exit;
+        }
+        ret = mbedtls_md_hmac_finish(&md_ctx, h_i);
+        if (ret != 0) {
+            goto exit;
+        }
+
+        ret = mbedtls_md_hmac_reset(&md_ctx);
+        if (ret != 0) {
+            goto exit;
+        }
+        ret = mbedtls_md_hmac_update(&md_ctx, tmp, md_len);
+        if (ret != 0) {
+            goto exit;
+        }
+        ret = mbedtls_md_hmac_finish(&md_ctx, tmp);
+        if (ret != 0) {
+            goto exit;
+        }
+
+        k = (i + md_len > dlen) ? dlen % md_len : md_len;
+
+        for (j = 0; j < k; j++) {
+            dstbuf[i + j]  = h_i[j];
+        }
+    }
+
+exit:
+    mbedtls_md_free(&md_ctx);
+
+    if (tmp != NULL) {
+        mbedtls_platform_zeroize(tmp, tmp_len);
+    }
+
+    mbedtls_platform_zeroize(h_i, sizeof(h_i));
+
+    mbedtls_free(tmp);
+
+    return ret;
+}
+#endif /* MBEDTLS_MD_C && ( MBEDTLS_SHA256_C || MBEDTLS_SHA384_C ) */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int tls_prf_sha256(const unsigned char *secret, size_t slen,
+                          const char *label,
+                          const unsigned char *random, size_t rlen,
+                          unsigned char *dstbuf, size_t dlen)
+{
+    return tls_prf_generic(MBEDTLS_MD_SHA256, secret, slen,
+                           label, random, rlen, dstbuf, dlen);
+}
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int tls_prf_sha384(const unsigned char *secret, size_t slen,
+                          const char *label,
+                          const unsigned char *random, size_t rlen,
+                          unsigned char *dstbuf, size_t dlen)
+{
+    return tls_prf_generic(MBEDTLS_MD_SHA384, secret, slen,
+                           label, random, rlen, dstbuf, dlen);
+}
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+
+/*
+ * Set appropriate PRF function and other SSL / TLS1.2 functions
+ *
+ * Inputs:
+ * - hash associated with the ciphersuite (only used by TLS 1.2)
+ *
+ * Outputs:
+ * - the tls_prf, calc_verify and calc_finished members of handshake structure
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_set_handshake_prfs(mbedtls_ssl_handshake_params *handshake,
+                                  mbedtls_md_type_t hash)
+{
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    if (hash == MBEDTLS_MD_SHA384) {
+        handshake->tls_prf = tls_prf_sha384;
+        handshake->calc_verify = ssl_calc_verify_tls_sha384;
+        handshake->calc_finished = ssl_calc_finished_tls_sha384;
+    } else
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    {
+        (void) hash;
+        handshake->tls_prf = tls_prf_sha256;
+        handshake->calc_verify = ssl_calc_verify_tls_sha256;
+        handshake->calc_finished = ssl_calc_finished_tls_sha256;
+    }
+#else
+    {
+        (void) handshake;
+        (void) hash;
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+#endif
+
+    return 0;
+}
+
+/*
+ * Compute master secret if needed
+ *
+ * Parameters:
+ * [in/out] handshake
+ *          [in] resume, premaster, extended_ms, calc_verify, tls_prf
+ *               (PSA-PSK) ciphersuite_info, psk_opaque
+ *          [out] premaster (cleared)
+ * [out] master
+ * [in] ssl: optionally used for debugging, EMS and PSA-PSK
+ *      debug: conf->f_dbg, conf->p_dbg
+ *      EMS: passed to calc_verify (debug + session_negotiate)
+ *      PSA-PSA: conf
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_compute_master(mbedtls_ssl_handshake_params *handshake,
+                              unsigned char *master,
+                              const mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    /* cf. RFC 5246, Section 8.1:
+     * "The master secret is always exactly 48 bytes in length." */
+    size_t const master_secret_len = 48;
+
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+    unsigned char session_hash[48];
+#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
+
+    /* The label for the KDF used for key expansion.
+     * This is either "master secret" or "extended master secret"
+     * depending on whether the Extended Master Secret extension
+     * is used. */
+    char const *lbl = "master secret";
+
+    /* The seed for the KDF used for key expansion.
+     * - If the Extended Master Secret extension is not used,
+     *   this is ClientHello.Random + ServerHello.Random
+     *   (see Sect. 8.1 in RFC 5246).
+     * - If the Extended Master Secret extension is used,
+     *   this is the transcript of the handshake so far.
+     *   (see Sect. 4 in RFC 7627). */
+    unsigned char const *seed = handshake->randbytes;
+    size_t seed_len = 64;
+
+#if !defined(MBEDTLS_DEBUG_C) &&                    \
+    !defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \
+    !(defined(MBEDTLS_USE_PSA_CRYPTO) &&            \
+    defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED))
+    ssl = NULL; /* make sure we don't use it except for those cases */
+    (void) ssl;
+#endif
+
+    if (handshake->resume != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("no premaster (session resumed)"));
+        return 0;
+    }
+
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+    if (handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED) {
+        lbl  = "extended master secret";
+        seed = session_hash;
+        ret = handshake->calc_verify(ssl, session_hash, &seed_len);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "calc_verify", ret);
+        }
+
+        MBEDTLS_SSL_DEBUG_BUF(3, "session hash for extended master secret",
+                              session_hash, seed_len);
+    }
+#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO) &&                   \
+    defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+    if (mbedtls_ssl_ciphersuite_uses_psk(handshake->ciphersuite_info) == 1) {
+        /* Perform PSK-to-MS expansion in a single step. */
+        psa_status_t status;
+        psa_algorithm_t alg;
+        mbedtls_svc_key_id_t psk;
+        psa_key_derivation_operation_t derivation =
+            PSA_KEY_DERIVATION_OPERATION_INIT;
+        mbedtls_md_type_t hash_alg = handshake->ciphersuite_info->mac;
+
+        MBEDTLS_SSL_DEBUG_MSG(2, ("perform PSA-based PSK-to-MS expansion"));
+
+        psk = mbedtls_ssl_get_opaque_psk(ssl);
+
+        if (hash_alg == MBEDTLS_MD_SHA384) {
+            alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384);
+        } else {
+            alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256);
+        }
+
+        size_t other_secret_len = 0;
+        unsigned char *other_secret = NULL;
+
+        switch (handshake->ciphersuite_info->key_exchange) {
+            /* Provide other secret.
+             * Other secret is stored in premaster, where first 2 bytes hold the
+             * length of the other key.
+             */
+            case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
+                /* For RSA-PSK other key length is always 48 bytes. */
+                other_secret_len = 48;
+                other_secret = handshake->premaster + 2;
+                break;
+            case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
+            case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
+                other_secret_len = MBEDTLS_GET_UINT16_BE(handshake->premaster, 0);
+                other_secret = handshake->premaster + 2;
+                break;
+            default:
+                break;
+        }
+
+        status = setup_psa_key_derivation(&derivation, psk, alg,
+                                          ssl->conf->psk, ssl->conf->psk_len,
+                                          seed, seed_len,
+                                          (unsigned char const *) lbl,
+                                          (size_t) strlen(lbl),
+                                          other_secret, other_secret_len,
+                                          master_secret_len);
+        if (status != PSA_SUCCESS) {
+            psa_key_derivation_abort(&derivation);
+            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+        }
+
+        status = psa_key_derivation_output_bytes(&derivation,
+                                                 master,
+                                                 master_secret_len);
+        if (status != PSA_SUCCESS) {
+            psa_key_derivation_abort(&derivation);
+            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+        }
+
+        status = psa_key_derivation_abort(&derivation);
+        if (status != PSA_SUCCESS) {
+            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+        }
+    } else
+#endif
+    {
+#if defined(MBEDTLS_USE_PSA_CRYPTO) &&                              \
+        defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+        if (handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) {
+            psa_status_t status;
+            psa_algorithm_t alg = PSA_ALG_TLS12_ECJPAKE_TO_PMS;
+            psa_key_derivation_operation_t derivation =
+                PSA_KEY_DERIVATION_OPERATION_INIT;
+
+            MBEDTLS_SSL_DEBUG_MSG(2, ("perform PSA-based PMS KDF for ECJPAKE"));
+
+            handshake->pmslen = PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE;
+
+            status = psa_key_derivation_setup(&derivation, alg);
+            if (status != PSA_SUCCESS) {
+                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+            }
+
+            status = psa_key_derivation_set_capacity(&derivation,
+                                                     PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE);
+            if (status != PSA_SUCCESS) {
+                psa_key_derivation_abort(&derivation);
+                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+            }
+
+            status = psa_pake_get_implicit_key(&handshake->psa_pake_ctx,
+                                               &derivation);
+            if (status != PSA_SUCCESS) {
+                psa_key_derivation_abort(&derivation);
+                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+            }
+
+            status = psa_key_derivation_output_bytes(&derivation,
+                                                     handshake->premaster,
+                                                     handshake->pmslen);
+            if (status != PSA_SUCCESS) {
+                psa_key_derivation_abort(&derivation);
+                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+            }
+
+            status = psa_key_derivation_abort(&derivation);
+            if (status != PSA_SUCCESS) {
+                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+            }
+        }
+#endif
+        ret = handshake->tls_prf(handshake->premaster, handshake->pmslen,
+                                 lbl, seed, seed_len,
+                                 master,
+                                 master_secret_len);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "prf", ret);
+            return ret;
+        }
+
+        MBEDTLS_SSL_DEBUG_BUF(3, "premaster secret",
+                              handshake->premaster,
+                              handshake->pmslen);
+
+        mbedtls_platform_zeroize(handshake->premaster,
+                                 sizeof(handshake->premaster));
+    }
+
+    return 0;
+}
+
+int mbedtls_ssl_derive_keys(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> derive keys"));
+
+    /* Set PRF, calc_verify and calc_finished function pointers */
+    ret = ssl_set_handshake_prfs(ssl->handshake,
+                                 ciphersuite_info->mac);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_set_handshake_prfs", ret);
+        return ret;
+    }
+
+    /* Compute master secret if needed */
+    ret = ssl_compute_master(ssl->handshake,
+                             ssl->session_negotiate->master,
+                             ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_compute_master", ret);
+        return ret;
+    }
+
+    /* Swap the client and server random values:
+     * - MS derivation wanted client+server (RFC 5246 8.1)
+     * - key derivation wants server+client (RFC 5246 6.3) */
+    {
+        unsigned char tmp[64];
+        memcpy(tmp, ssl->handshake->randbytes, 64);
+        memcpy(ssl->handshake->randbytes, tmp + 32, 32);
+        memcpy(ssl->handshake->randbytes + 32, tmp, 32);
+        mbedtls_platform_zeroize(tmp, sizeof(tmp));
+    }
+
+    /* Populate transform structure */
+    ret = ssl_tls12_populate_transform(ssl->transform_negotiate,
+                                       ssl->session_negotiate->ciphersuite,
+                                       ssl->session_negotiate->master,
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+                                       ssl->session_negotiate->encrypt_then_mac,
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
+                                       ssl->handshake->tls_prf,
+                                       ssl->handshake->randbytes,
+                                       ssl->tls_version,
+                                       ssl->conf->endpoint,
+                                       ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls12_populate_transform", ret);
+        return ret;
+    }
+
+    /* We no longer need Server/ClientHello.random values */
+    mbedtls_platform_zeroize(ssl->handshake->randbytes,
+                             sizeof(ssl->handshake->randbytes));
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= derive keys"));
+
+    return 0;
+}
+
+int mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md)
+{
+    switch (md) {
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
         case MBEDTLS_SSL_HASH_SHA384:
             ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384;
             break;
 #endif
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
         case MBEDTLS_SSL_HASH_SHA256:
             ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256;
             break;
 #endif
         default:
-            return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH;
+            return -1;
+    }
+#if !defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
+    !defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    (void) ssl;
+#endif
+    return 0;
+}
+
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+int ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *ssl,
+                               unsigned char *hash,
+                               size_t *hlen)
+{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    size_t hash_size;
+    psa_status_t status;
+    psa_hash_operation_t sha256_psa = psa_hash_operation_init();
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> PSA calc verify sha256"));
+    status = psa_hash_clone(&ssl->handshake->fin_sha256_psa, &sha256_psa);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_finish(&sha256_psa, hash, 32, &hash_size);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    *hlen = 32;
+    MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated verify result", hash, *hlen);
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= PSA calc verify"));
+
+exit:
+    psa_hash_abort(&sha256_psa);
+    return PSA_TO_MD_ERR(status);
+#else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_md_context_t sha256;
+
+    mbedtls_md_init(&sha256);
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify sha256"));
+
+    ret = mbedtls_md_setup(&sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_md_clone(&sha256, &ssl->handshake->fin_sha256);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    ret = mbedtls_md_finish(&sha256, hash);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    *hlen = 32;
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "calculated verify result", hash, *hlen);
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify"));
+
+exit:
+    mbedtls_md_free(&sha256);
+    return ret;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+}
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+int ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *ssl,
+                               unsigned char *hash,
+                               size_t *hlen)
+{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    size_t hash_size;
+    psa_status_t status;
+    psa_hash_operation_t sha384_psa = psa_hash_operation_init();
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> PSA calc verify sha384"));
+    status = psa_hash_clone(&ssl->handshake->fin_sha384_psa, &sha384_psa);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_finish(&sha384_psa, hash, 48, &hash_size);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    *hlen = 48;
+    MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated verify result", hash, *hlen);
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= PSA calc verify"));
+
+exit:
+    psa_hash_abort(&sha384_psa);
+    return PSA_TO_MD_ERR(status);
+#else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_md_context_t sha384;
+
+    mbedtls_md_init(&sha384);
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify sha384"));
+
+    ret = mbedtls_md_setup(&sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_md_clone(&sha384, &ssl->handshake->fin_sha384);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    ret = mbedtls_md_finish(&sha384, hash);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    *hlen = 48;
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "calculated verify result", hash, *hlen);
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify"));
+
+exit:
+    mbedtls_md_free(&sha384);
+    return ret;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+}
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+
+#if !defined(MBEDTLS_USE_PSA_CRYPTO) &&                      \
+    defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+int mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex)
+{
+    unsigned char *p = ssl->handshake->premaster;
+    unsigned char *end = p + sizeof(ssl->handshake->premaster);
+    const unsigned char *psk = NULL;
+    size_t psk_len = 0;
+    int psk_ret = mbedtls_ssl_get_psk(ssl, &psk, &psk_len);
+
+    if (psk_ret == MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) {
+        /*
+         * This should never happen because the existence of a PSK is always
+         * checked before calling this function.
+         *
+         * The exception is opaque DHE-PSK. For DHE-PSK fill premaster with
+         * the shared secret without PSK.
+         */
+        if (key_ex != MBEDTLS_KEY_EXCHANGE_DHE_PSK) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        }
+    }
+
+    /*
+     * PMS = struct {
+     *     opaque other_secret<0..2^16-1>;
+     *     opaque psk<0..2^16-1>;
+     * };
+     * with "other_secret" depending on the particular key exchange
+     */
+#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
+    if (key_ex == MBEDTLS_KEY_EXCHANGE_PSK) {
+        if (end - p < 2) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+
+        MBEDTLS_PUT_UINT16_BE(psk_len, p, 0);
+        p += 2;
+
+        if (end < p || (size_t) (end - p) < psk_len) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+
+        memset(p, 0, psk_len);
+        p += psk_len;
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
+    if (key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK) {
+        /*
+         * other_secret already set by the ClientKeyExchange message,
+         * and is 48 bytes long
+         */
+        if (end - p < 2) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+
+        *p++ = 0;
+        *p++ = 48;
+        p += 48;
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
+    if (key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK) {
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        size_t len;
+
+        /* Write length only when we know the actual value */
+        if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx,
+                                           p + 2, end - (p + 2), &len,
+                                           ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret);
+            return ret;
+        }
+        MBEDTLS_PUT_UINT16_BE(len, p, 0);
+        p += 2 + len;
+
+        MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K);
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+    if (key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) {
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        size_t zlen;
+
+        if ((ret = mbedtls_ecdh_calc_secret(&ssl->handshake->ecdh_ctx, &zlen,
+                                            p + 2, end - (p + 2),
+                                            ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_calc_secret", ret);
+            return ret;
+        }
+
+        MBEDTLS_PUT_UINT16_BE(zlen, p, 0);
+        p += 2 + zlen;
+
+        MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,
+                               MBEDTLS_DEBUG_ECDH_Z);
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+    {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    /* opaque psk<0..2^16-1>; */
+    if (end - p < 2) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    MBEDTLS_PUT_UINT16_BE(psk_len, p, 0);
+    p += 2;
+
+    if (end < p || (size_t) (end - p) < psk_len) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    memcpy(p, psk, psk_len);
+    p += psk_len;
+
+    ssl->handshake->pmslen = p - ssl->handshake->premaster;
+
+    return 0;
+}
+#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_hello_request(mbedtls_ssl_context *ssl);
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+int mbedtls_ssl_resend_hello_request(mbedtls_ssl_context *ssl)
+{
+    /* If renegotiation is not enforced, retransmit until we would reach max
+     * timeout if we were using the usual handshake doubling scheme */
+    if (ssl->conf->renego_max_records < 0) {
+        uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1;
+        unsigned char doublings = 1;
+
+        while (ratio != 0) {
+            ++doublings;
+            ratio >>= 1;
+        }
+
+        if (++ssl->renego_records_seen > doublings) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("no longer retransmitting hello request"));
+            return 0;
+        }
+    }
+
+    return ssl_write_hello_request(ssl);
+}
+#endif
+#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
+
+/*
+ * Handshake functions
+ */
+#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+/* No certificate support -> dummy functions */
+int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl)
+{
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate"));
+
+    if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate"));
+        ssl->state++;
+        return 0;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+}
+
+int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl)
+{
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate"));
+
+    if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate"));
+        ssl->state++;
+        return 0;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+}
+
+#else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+/* Some certificate support -> implement write and parse */
+
+int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    size_t i, n;
+    const mbedtls_x509_crt *crt;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate"));
+
+    if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate"));
+        ssl->state++;
+        return 0;
+    }
+
+#if defined(MBEDTLS_SSL_CLI_C)
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        if (ssl->handshake->client_auth == 0) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate"));
+            ssl->state++;
+            return 0;
+        }
+    }
+#endif /* MBEDTLS_SSL_CLI_C */
+#if defined(MBEDTLS_SSL_SRV_C)
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
+        if (mbedtls_ssl_own_cert(ssl) == NULL) {
+            /* Should never happen because we shouldn't have picked the
+             * ciphersuite if we don't have a certificate. */
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        }
+    }
+#endif
+
+    MBEDTLS_SSL_DEBUG_CRT(3, "own certificate", mbedtls_ssl_own_cert(ssl));
+
+    /*
+     *     0  .  0    handshake type
+     *     1  .  3    handshake length
+     *     4  .  6    length of all certs
+     *     7  .  9    length of cert. 1
+     *    10  . n-1   peer certificate
+     *     n  . n+2   length of cert. 2
+     *    n+3 . ...   upper level cert, etc.
+     */
+    i = 7;
+    crt = mbedtls_ssl_own_cert(ssl);
+
+    while (crt != NULL) {
+        n = crt->raw.len;
+        if (n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("certificate too large, %" MBEDTLS_PRINTF_SIZET
+                                      " > %" MBEDTLS_PRINTF_SIZET,
+                                      i + 3 + n, (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN));
+            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+        }
+
+        ssl->out_msg[i] = MBEDTLS_BYTE_2(n);
+        ssl->out_msg[i + 1] = MBEDTLS_BYTE_1(n);
+        ssl->out_msg[i + 2] = MBEDTLS_BYTE_0(n);
+
+        i += 3; memcpy(ssl->out_msg + i, crt->raw.p, n);
+        i += n; crt = crt->next;
+    }
+
+    ssl->out_msg[4]  = MBEDTLS_BYTE_2(i - 7);
+    ssl->out_msg[5]  = MBEDTLS_BYTE_1(i - 7);
+    ssl->out_msg[6]  = MBEDTLS_BYTE_0(i - 7);
+
+    ssl->out_msglen  = i;
+    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = MBEDTLS_SSL_HS_CERTIFICATE;
+
+    ssl->state++;
+
+    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret);
+        return ret;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate"));
+
+    return ret;
+}
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
+
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_check_peer_crt_unchanged(mbedtls_ssl_context *ssl,
+                                        unsigned char *crt_buf,
+                                        size_t crt_buf_len)
+{
+    mbedtls_x509_crt const * const peer_crt = ssl->session->peer_cert;
+
+    if (peer_crt == NULL) {
+        return -1;
+    }
+
+    if (peer_crt->raw.len != crt_buf_len) {
+        return -1;
+    }
+
+    return memcmp(peer_crt->raw.p, crt_buf, peer_crt->raw.len);
+}
+#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_check_peer_crt_unchanged(mbedtls_ssl_context *ssl,
+                                        unsigned char *crt_buf,
+                                        size_t crt_buf_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char const * const peer_cert_digest =
+        ssl->session->peer_cert_digest;
+    mbedtls_md_type_t const peer_cert_digest_type =
+        ssl->session->peer_cert_digest_type;
+    mbedtls_md_info_t const * const digest_info =
+        mbedtls_md_info_from_type(peer_cert_digest_type);
+    unsigned char tmp_digest[MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN];
+    size_t digest_len;
+
+    if (peer_cert_digest == NULL || digest_info == NULL) {
+        return -1;
+    }
+
+    digest_len = mbedtls_md_get_size(digest_info);
+    if (digest_len > MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN) {
+        return -1;
+    }
+
+    ret = mbedtls_md(digest_info, crt_buf, crt_buf_len, tmp_digest);
+    if (ret != 0) {
+        return -1;
+    }
+
+    return memcmp(tmp_digest, peer_cert_digest, digest_len);
+}
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
+
+/*
+ * Once the certificate message is read, parse it into a cert chain and
+ * perform basic checks, but leave actual verification to the caller
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_certificate_chain(mbedtls_ssl_context *ssl,
+                                       mbedtls_x509_crt *chain)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
+    int crt_cnt = 0;
+#endif
+    size_t i, n;
+    uint8_t alert;
+
+    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
+
+    if (ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE) {
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
+
+    if (ssl->in_hslen < mbedtls_ssl_hs_hdr_len(ssl) + 3 + 3) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    i = mbedtls_ssl_hs_hdr_len(ssl);
+
+    /*
+     * Same message structure as in mbedtls_ssl_write_certificate()
+     */
+    n = (ssl->in_msg[i+1] << 8) | ssl->in_msg[i+2];
+
+    if (ssl->in_msg[i] != 0 ||
+        ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len(ssl)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /* Make &ssl->in_msg[i] point to the beginning of the CRT chain. */
+    i += 3;
+
+    /* Iterate through and parse the CRTs in the provided chain. */
+    while (i < ssl->in_hslen) {
+        /* Check that there's room for the next CRT's length fields. */
+        if (i + 3 > ssl->in_hslen) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
+            mbedtls_ssl_send_alert_message(ssl,
+                                           MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+        /* In theory, the CRT can be up to 2**24 Bytes, but we don't support
+         * anything beyond 2**16 ~ 64K. */
+        if (ssl->in_msg[i] != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
+            mbedtls_ssl_send_alert_message(ssl,
+                                           MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                           MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT);
+            return MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
+        }
+
+        /* Read length of the next CRT in the chain. */
+        n = ((unsigned int) ssl->in_msg[i + 1] << 8)
+            | (unsigned int) ssl->in_msg[i + 2];
+        i += 3;
+
+        if (n < 128 || i + n > ssl->in_hslen) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
+            mbedtls_ssl_send_alert_message(ssl,
+                                           MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+
+        /* Check if we're handling the first CRT in the chain. */
+#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
+        if (crt_cnt++ == 0 &&
+            ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
+            ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {
+            /* During client-side renegotiation, check that the server's
+             * end-CRTs hasn't changed compared to the initial handshake,
+             * mitigating the triple handshake attack. On success, reuse
+             * the original end-CRT instead of parsing it again. */
+            MBEDTLS_SSL_DEBUG_MSG(3, ("Check that peer CRT hasn't changed during renegotiation"));
+            if (ssl_check_peer_crt_unchanged(ssl,
+                                             &ssl->in_msg[i],
+                                             n) != 0) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("new server cert during renegotiation"));
+                mbedtls_ssl_send_alert_message(ssl,
+                                               MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                               MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED);
+                return MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
+            }
+
+            /* Now we can safely free the original chain. */
+            ssl_clear_peer_cert(ssl->session);
+        }
+#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
+
+        /* Parse the next certificate in the chain. */
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+        ret = mbedtls_x509_crt_parse_der(chain, ssl->in_msg + i, n);
+#else
+        /* If we don't need to store the CRT chain permanently, parse
+         * it in-place from the input buffer instead of making a copy. */
+        ret = mbedtls_x509_crt_parse_der_nocopy(chain, ssl->in_msg + i, n);
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+        switch (ret) {
+            case 0: /*ok*/
+            case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND:
+                /* Ignore certificate with an unknown algorithm: maybe a
+                   prior certificate was already trusted. */
+                break;
+
+            case MBEDTLS_ERR_X509_ALLOC_FAILED:
+                alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR;
+                goto crt_parse_der_failed;
+
+            case MBEDTLS_ERR_X509_UNKNOWN_VERSION:
+                alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
+                goto crt_parse_der_failed;
+
+            default:
+                alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
+crt_parse_der_failed:
+                mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert);
+                MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret);
+                return ret;
+        }
+
+        i += n;
+    }
+
+    MBEDTLS_SSL_DEBUG_CRT(3, "peer certificate", chain);
+    return 0;
+}
+
+#if defined(MBEDTLS_SSL_SRV_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_srv_check_client_no_crt_notification(mbedtls_ssl_context *ssl)
+{
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        return -1;
+    }
+
+    if (ssl->in_hslen   == 3 + mbedtls_ssl_hs_hdr_len(ssl) &&
+        ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE    &&
+        ssl->in_msg[0]  == MBEDTLS_SSL_HS_CERTIFICATE   &&
+        memcmp(ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl), "\0\0\0", 3) == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("peer has no certificate"));
+        return 0;
+    }
+    return -1;
+}
+#endif /* MBEDTLS_SSL_SRV_C */
+
+/* Check if a certificate message is expected.
+ * Return either
+ * - SSL_CERTIFICATE_EXPECTED, or
+ * - SSL_CERTIFICATE_SKIP
+ * indicating whether a Certificate message is expected or not.
+ */
+#define SSL_CERTIFICATE_EXPECTED 0
+#define SSL_CERTIFICATE_SKIP     1
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_certificate_coordinate(mbedtls_ssl_context *ssl,
+                                            int authmode)
+{
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+
+    if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) {
+        return SSL_CERTIFICATE_SKIP;
+    }
+
+#if defined(MBEDTLS_SSL_SRV_C)
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
+        if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) {
+            return SSL_CERTIFICATE_SKIP;
+        }
+
+        if (authmode == MBEDTLS_SSL_VERIFY_NONE) {
+            ssl->session_negotiate->verify_result =
+                MBEDTLS_X509_BADCERT_SKIP_VERIFY;
+            return SSL_CERTIFICATE_SKIP;
+        }
+    }
+#else
+    ((void) authmode);
+#endif /* MBEDTLS_SSL_SRV_C */
+
+    return SSL_CERTIFICATE_EXPECTED;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl,
+                                        int authmode,
+                                        mbedtls_x509_crt *chain,
+                                        void *rs_ctx)
+{
+    int ret = 0;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+    int have_ca_chain = 0;
+
+    int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *);
+    void *p_vrfy;
+
+    if (authmode == MBEDTLS_SSL_VERIFY_NONE) {
+        return 0;
+    }
+
+    if (ssl->f_vrfy != NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("Use context-specific verification callback"));
+        f_vrfy = ssl->f_vrfy;
+        p_vrfy = ssl->p_vrfy;
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("Use configuration-specific verification callback"));
+        f_vrfy = ssl->conf->f_vrfy;
+        p_vrfy = ssl->conf->p_vrfy;
+    }
+
+    /*
+     * Main check: verify certificate
+     */
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+    if (ssl->conf->f_ca_cb != NULL) {
+        ((void) rs_ctx);
+        have_ca_chain = 1;
+
+        MBEDTLS_SSL_DEBUG_MSG(3, ("use CA callback for X.509 CRT verification"));
+        ret = mbedtls_x509_crt_verify_with_ca_cb(
+            chain,
+            ssl->conf->f_ca_cb,
+            ssl->conf->p_ca_cb,
+            ssl->conf->cert_profile,
+            ssl->hostname,
+            &ssl->session_negotiate->verify_result,
+            f_vrfy, p_vrfy);
+    } else
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
+    {
+        mbedtls_x509_crt *ca_chain;
+        mbedtls_x509_crl *ca_crl;
+
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+        if (ssl->handshake->sni_ca_chain != NULL) {
+            ca_chain = ssl->handshake->sni_ca_chain;
+            ca_crl   = ssl->handshake->sni_ca_crl;
+        } else
+#endif
+        {
+            ca_chain = ssl->conf->ca_chain;
+            ca_crl   = ssl->conf->ca_crl;
+        }
+
+        if (ca_chain != NULL) {
+            have_ca_chain = 1;
+        }
+
+        ret = mbedtls_x509_crt_verify_restartable(
+            chain,
+            ca_chain, ca_crl,
+            ssl->conf->cert_profile,
+            ssl->hostname,
+            &ssl->session_negotiate->verify_result,
+            f_vrfy, p_vrfy, rs_ctx);
+    }
+
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret);
+    }
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
+        return MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+    }
+#endif
+
+    /*
+     * Secondary checks: always done, but change 'ret' only if it was 0
+     */
+
+#if defined(MBEDTLS_ECP_C)
+    {
+        const mbedtls_pk_context *pk = &chain->pk;
+
+        /* If certificate uses an EC key, make sure the curve is OK.
+         * This is a public key, so it can't be opaque, so can_do() is a good
+         * enough check to ensure pk_ec() is safe to use here. */
+        if (mbedtls_pk_can_do(pk, MBEDTLS_PK_ECKEY)) {
+            /* and in the unlikely case the above assumption no longer holds
+             * we are making sure that pk_ec() here does not return a NULL
+             */
+            const mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk);
+            if (ec == NULL) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("mbedtls_pk_ec() returned NULL"));
+                return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+            }
+
+            if (mbedtls_ssl_check_curve(ssl, ec->grp.id) != 0) {
+                ssl->session_negotiate->verify_result |=
+                    MBEDTLS_X509_BADCERT_BAD_KEY;
+
+                MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (EC key curve)"));
+                if (ret == 0) {
+                    ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
+                }
+            }
+        }
+    }
+#endif /* MBEDTLS_ECP_C */
+
+    if (mbedtls_ssl_check_cert_usage(chain,
+                                     ciphersuite_info,
+                                     !ssl->conf->endpoint,
+                                     &ssl->session_negotiate->verify_result) != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)"));
+        if (ret == 0) {
+            ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
+        }
+    }
+
+    /* mbedtls_x509_crt_verify_with_profile is supposed to report a
+     * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED,
+     * with details encoded in the verification flags. All other kinds
+     * of error codes, including those from the user provided f_vrfy
+     * functions, are treated as fatal and lead to a failure of
+     * ssl_parse_certificate even if verification was optional. */
+    if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
+        (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
+         ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE)) {
+        ret = 0;
+    }
+
+    if (have_ca_chain == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("got no CA chain"));
+        ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
+    }
+
+    if (ret != 0) {
+        uint8_t alert;
+
+        /* The certificate may have been rejected for several reasons.
+           Pick one and send the corresponding alert. Which alert to send
+           may be a subject of debate in some cases. */
+        if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER) {
+            alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED;
+        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) {
+            alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
+        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE) {
+            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
+        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE) {
+            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
+        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE) {
+            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
+        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK) {
+            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
+        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY) {
+            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
+        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED) {
+            alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED;
+        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED) {
+            alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED;
+        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
+            alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA;
+        } else {
+            alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN;
+        }
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       alert);
+    }
+
+#if defined(MBEDTLS_DEBUG_C)
+    if (ssl->session_negotiate->verify_result != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x",
+                                  (unsigned int) ssl->session_negotiate->verify_result));
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear"));
+    }
+#endif /* MBEDTLS_DEBUG_C */
+
+    return ret;
+}
+
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_remember_peer_crt_digest(mbedtls_ssl_context *ssl,
+                                        unsigned char *start, size_t len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    /* Remember digest of the peer's end-CRT. */
+    ssl->session_negotiate->peer_cert_digest =
+        mbedtls_calloc(1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN);
+    if (ssl->session_negotiate->peer_cert_digest == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%d bytes) failed",
+                                  MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN));
+        mbedtls_ssl_send_alert_message(ssl,
+                                       MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);
+
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+    }
+
+    ret = mbedtls_md(mbedtls_md_info_from_type(
+                         MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE),
+                     start, len,
+                     ssl->session_negotiate->peer_cert_digest);
+
+    ssl->session_negotiate->peer_cert_digest_type =
+        MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE;
+    ssl->session_negotiate->peer_cert_digest_len =
+        MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN;
+
+    return ret;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_remember_peer_pubkey(mbedtls_ssl_context *ssl,
+                                    unsigned char *start, size_t len)
+{
+    unsigned char *end = start + len;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    /* Make a copy of the peer's raw public key. */
+    mbedtls_pk_init(&ssl->handshake->peer_pubkey);
+    ret = mbedtls_pk_parse_subpubkey(&start, end,
+                                     &ssl->handshake->peer_pubkey);
+    if (ret != 0) {
+        /* We should have parsed the public key before. */
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
     return 0;
-#else /* !MBEDTLS_SSL_PROTO_TLS1_2 */
-    (void) ssl;
-    (void) md;
-
-    return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH;
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 }
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_1)
-int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl,
-                                        unsigned char *output,
-                                        unsigned char *data, size_t data_len )
+int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl)
 {
     int ret = 0;
-    mbedtls_md5_context mbedtls_md5;
-    mbedtls_sha1_context mbedtls_sha1;
+    int crt_expected;
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
+                       ? ssl->handshake->sni_authmode
+                       : ssl->conf->authmode;
+#else
+    const int authmode = ssl->conf->authmode;
+#endif
+    void *rs_ctx = NULL;
+    mbedtls_x509_crt *chain = NULL;
 
-    mbedtls_md5_init( &mbedtls_md5 );
-    mbedtls_sha1_init( &mbedtls_sha1 );
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate"));
 
-    /*
-     * digitally-signed struct {
-     *     opaque md5_hash[16];
-     *     opaque sha_hash[20];
-     * };
-     *
-     * md5_hash
-     *     MD5(ClientHello.random + ServerHello.random
-     *                            + ServerParams);
-     * sha_hash
-     *     SHA(ClientHello.random + ServerHello.random
-     *                            + ServerParams);
-     */
-    if( ( ret = mbedtls_md5_starts_ret( &mbedtls_md5 ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_starts_ret", ret );
-        goto exit;
-    }
-    if( ( ret = mbedtls_md5_update_ret( &mbedtls_md5,
-                                        ssl->handshake->randbytes, 64 ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ret", ret );
-        goto exit;
-    }
-    if( ( ret = mbedtls_md5_update_ret( &mbedtls_md5, data, data_len ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ret", ret );
-        goto exit;
-    }
-    if( ( ret = mbedtls_md5_finish_ret( &mbedtls_md5, output ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_finish_ret", ret );
+    crt_expected = ssl_parse_certificate_coordinate(ssl, authmode);
+    if (crt_expected == SSL_CERTIFICATE_SKIP) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate"));
         goto exit;
     }
 
-    if( ( ret = mbedtls_sha1_starts_ret( &mbedtls_sha1 ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_starts_ret", ret );
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    if (ssl->handshake->ecrs_enabled &&
+        ssl->handshake->ecrs_state == ssl_ecrs_crt_verify) {
+        chain = ssl->handshake->ecrs_peer_cert;
+        ssl->handshake->ecrs_peer_cert = NULL;
+        goto crt_verify;
+    }
+#endif
+
+    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {
+        /* mbedtls_ssl_read_record may have sent an alert already. We
+           let it decide whether to alert. */
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
         goto exit;
     }
-    if( ( ret = mbedtls_sha1_update_ret( &mbedtls_sha1,
-                                         ssl->handshake->randbytes, 64 ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ret", ret );
+
+#if defined(MBEDTLS_SSL_SRV_C)
+    if (ssl_srv_check_client_no_crt_notification(ssl) == 0) {
+        ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
+
+        if (authmode != MBEDTLS_SSL_VERIFY_OPTIONAL) {
+            ret = MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE;
+        }
+
         goto exit;
     }
-    if( ( ret = mbedtls_sha1_update_ret( &mbedtls_sha1, data,
-                                         data_len ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ret", ret );
+#endif /* MBEDTLS_SSL_SRV_C */
+
+    /* Clear existing peer CRT structure in case we tried to
+     * reuse a session but it failed, and allocate a new one. */
+    ssl_clear_peer_cert(ssl->session_negotiate);
+
+    chain = mbedtls_calloc(1, sizeof(mbedtls_x509_crt));
+    if (chain == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed",
+                                  sizeof(mbedtls_x509_crt)));
+        mbedtls_ssl_send_alert_message(ssl,
+                                       MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);
+
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
         goto exit;
     }
-    if( ( ret = mbedtls_sha1_finish_ret( &mbedtls_sha1,
-                                         output + 16 ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_finish_ret", ret );
+    mbedtls_x509_crt_init(chain);
+
+    ret = ssl_parse_certificate_chain(ssl, chain);
+    if (ret != 0) {
         goto exit;
     }
 
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    if (ssl->handshake->ecrs_enabled) {
+        ssl->handshake->ecrs_state = ssl_ecrs_crt_verify;
+    }
+
+crt_verify:
+    if (ssl->handshake->ecrs_enabled) {
+        rs_ctx = &ssl->handshake->ecrs_ctx;
+    }
+#endif
+
+    ret = ssl_parse_certificate_verify(ssl, authmode,
+                                       chain, rs_ctx);
+    if (ret != 0) {
+        goto exit;
+    }
+
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    {
+        unsigned char *crt_start, *pk_start;
+        size_t crt_len, pk_len;
+
+        /* We parse the CRT chain without copying, so
+         * these pointers point into the input buffer,
+         * and are hence still valid after freeing the
+         * CRT chain. */
+
+        crt_start = chain->raw.p;
+        crt_len   = chain->raw.len;
+
+        pk_start = chain->pk_raw.p;
+        pk_len   = chain->pk_raw.len;
+
+        /* Free the CRT structures before computing
+         * digest and copying the peer's public key. */
+        mbedtls_x509_crt_free(chain);
+        mbedtls_free(chain);
+        chain = NULL;
+
+        ret = ssl_remember_peer_crt_digest(ssl, crt_start, crt_len);
+        if (ret != 0) {
+            goto exit;
+        }
+
+        ret = ssl_remember_peer_pubkey(ssl, pk_start, pk_len);
+        if (ret != 0) {
+            goto exit;
+        }
+    }
+#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+    /* Pass ownership to session structure. */
+    ssl->session_negotiate->peer_cert = chain;
+    chain = NULL;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate"));
+
 exit:
-    mbedtls_md5_free( &mbedtls_md5 );
-    mbedtls_sha1_free( &mbedtls_sha1 );
 
-    if( ret != 0 )
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
+    if (ret == 0) {
+        ssl->state++;
+    }
 
-    return( ret );
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    if (ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) {
+        ssl->handshake->ecrs_peer_cert = chain;
+        chain = NULL;
+    }
+#endif
 
+    if (chain != NULL) {
+        mbedtls_x509_crt_free(chain);
+        mbedtls_free(chain);
+    }
+
+    return ret;
 }
-#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \
-          MBEDTLS_SSL_PROTO_TLS1_1 */
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
-    defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+static int ssl_calc_finished_tls_sha256(
+    mbedtls_ssl_context *ssl, unsigned char *buf, int from)
+{
+    int len = 12;
+    const char *sender;
+    unsigned char padbuf[32];
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    size_t hash_size;
+    psa_hash_operation_t sha256_psa = PSA_HASH_OPERATION_INIT;
+    psa_status_t status;
+#else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_md_context_t sha256;
+#endif
+
+    mbedtls_ssl_session *session = ssl->session_negotiate;
+    if (!session) {
+        session = ssl->session;
+    }
+
+    sender = (from == MBEDTLS_SSL_IS_CLIENT)
+             ? "client finished"
+             : "server finished";
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
-                                            unsigned char *hash, size_t *hashlen,
-                                            unsigned char *data, size_t data_len,
-                                            mbedtls_md_type_t md_alg )
+    sha256_psa = psa_hash_operation_init();
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc PSA finished tls sha256"));
+
+    status = psa_hash_clone(&ssl->handshake->fin_sha256_psa, &sha256_psa);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_finish(&sha256_psa, padbuf, sizeof(padbuf), &hash_size);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+    MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated padbuf", padbuf, 32);
+#else
+
+    mbedtls_md_init(&sha256);
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc  finished tls sha256"));
+
+    ret = mbedtls_md_setup(&sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_md_clone(&sha256, &ssl->handshake->fin_sha256);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    /*
+     * TLSv1.2:
+     *   hash = PRF( master, finished_label,
+     *               Hash( handshake ) )[0.11]
+     */
+
+    ret = mbedtls_md_finish(&sha256, padbuf);
+    if (ret != 0) {
+        goto exit;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "finished sha256 output", padbuf, 32);
+
+    ssl->handshake->tls_prf(session->master, 48, sender,
+                            padbuf, 32, buf, len);
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "calc finished result", buf, len);
+
+    mbedtls_platform_zeroize(padbuf, sizeof(padbuf));
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc  finished"));
+
+exit:
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_hash_abort(&sha256_psa);
+    return PSA_TO_MD_ERR(status);
+#else
+    mbedtls_md_free(&sha256);
+    return ret;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+}
+#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+
+
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+static int ssl_calc_finished_tls_sha384(
+    mbedtls_ssl_context *ssl, unsigned char *buf, int from)
+{
+    int len = 12;
+    const char *sender;
+    unsigned char padbuf[48];
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    size_t hash_size;
+    psa_hash_operation_t sha384_psa = PSA_HASH_OPERATION_INIT;
+    psa_status_t status;
+#else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_md_context_t sha384;
+#endif
+
+    mbedtls_ssl_session *session = ssl->session_negotiate;
+    if (!session) {
+        session = ssl->session;
+    }
+
+    sender = (from == MBEDTLS_SSL_IS_CLIENT)
+                ? "client finished"
+                : "server finished";
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    sha384_psa = psa_hash_operation_init();
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc PSA finished tls sha384"));
+
+    status = psa_hash_clone(&ssl->handshake->fin_sha384_psa, &sha384_psa);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_finish(&sha384_psa, padbuf, sizeof(padbuf), &hash_size);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+    MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated padbuf", padbuf, 48);
+#else
+    mbedtls_md_init(&sha384);
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc  finished tls sha384"));
+
+    ret = mbedtls_md_setup(&sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_md_clone(&sha384, &ssl->handshake->fin_sha384);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    /*
+     * TLSv1.2:
+     *   hash = PRF( master, finished_label,
+     *               Hash( handshake ) )[0.11]
+     */
+
+    ret = mbedtls_md_finish(&sha384, padbuf);
+    if (ret != 0) {
+        goto exit;
+    }
+#endif
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "finished sha384 output", padbuf, 48);
+
+    ssl->handshake->tls_prf(session->master, 48, sender,
+                            padbuf, 48, buf, len);
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "calc finished result", buf, len);
+
+    mbedtls_platform_zeroize(padbuf, sizeof(padbuf));
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc  finished"));
+
+exit:
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_hash_abort(&sha384_psa);
+    return PSA_TO_MD_ERR(status);
+#else
+    mbedtls_md_free(&sha384);
+    return ret;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+}
+#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+
+void mbedtls_ssl_handshake_wrapup_free_hs_transform(mbedtls_ssl_context *ssl)
+{
+    MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup: final free"));
+
+    /*
+     * Free our handshake params
+     */
+    mbedtls_ssl_handshake_free(ssl);
+    mbedtls_free(ssl->handshake);
+    ssl->handshake = NULL;
+
+    /*
+     * Free the previous transform and switch in the current one
+     */
+    if (ssl->transform) {
+        mbedtls_ssl_transform_free(ssl->transform);
+        mbedtls_free(ssl->transform);
+    }
+    ssl->transform = ssl->transform_negotiate;
+    ssl->transform_negotiate = NULL;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup: final free"));
+}
+
+void mbedtls_ssl_handshake_wrapup(mbedtls_ssl_context *ssl)
+{
+    int resume = ssl->handshake->resume;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup"));
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {
+        ssl->renego_status =  MBEDTLS_SSL_RENEGOTIATION_DONE;
+        ssl->renego_records_seen = 0;
+    }
+#endif
+
+    /*
+     * Free the previous session and switch in the current one
+     */
+    if (ssl->session) {
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+        /* RFC 7366 3.1: keep the EtM state */
+        ssl->session_negotiate->encrypt_then_mac =
+            ssl->session->encrypt_then_mac;
+#endif
+
+        mbedtls_ssl_session_free(ssl->session);
+        mbedtls_free(ssl->session);
+    }
+    ssl->session = ssl->session_negotiate;
+    ssl->session_negotiate = NULL;
+
+    /*
+     * Add cache entry
+     */
+    if (ssl->conf->f_set_cache != NULL &&
+        ssl->session->id_len != 0 &&
+        resume == 0) {
+        if (ssl->conf->f_set_cache(ssl->conf->p_cache,
+                                   ssl->session->id,
+                                   ssl->session->id_len,
+                                   ssl->session) != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("cache did not store session"));
+        }
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        ssl->handshake->flight != NULL) {
+        /* Cancel handshake timer */
+        mbedtls_ssl_set_timer(ssl, 0);
+
+        /* Keep last flight around in case we need to resend it:
+         * we need the handshake and transform structures for that */
+        MBEDTLS_SSL_DEBUG_MSG(3, ("skip freeing handshake and transform"));
+    } else
+#endif
+    mbedtls_ssl_handshake_wrapup_free_hs_transform(ssl);
+
+    ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup"));
+}
+
+int mbedtls_ssl_write_finished(mbedtls_ssl_context *ssl)
+{
+    int ret, hash_len;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write finished"));
+
+    mbedtls_ssl_update_out_pointers(ssl, ssl->transform_negotiate);
+
+    ret = ssl->handshake->calc_finished(ssl, ssl->out_msg + 4, ssl->conf->endpoint);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "calc_finished", ret);
+    }
+
+    /*
+     * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites
+     * may define some other value. Currently (early 2016), no defined
+     * ciphersuite does this (and this is unlikely to change as activity has
+     * moved to TLS 1.3 now) so we can keep the hardcoded 12 here.
+     */
+    hash_len = 12;
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    ssl->verify_data_len = hash_len;
+    memcpy(ssl->own_verify_data, ssl->out_msg + 4, hash_len);
+#endif
+
+    ssl->out_msglen  = 4 + hash_len;
+    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = MBEDTLS_SSL_HS_FINISHED;
+
+    /*
+     * In case of session resuming, invert the client and server
+     * ChangeCipherSpec messages order.
+     */
+    if (ssl->handshake->resume != 0) {
+#if defined(MBEDTLS_SSL_CLI_C)
+        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+            ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
+        }
+#endif
+#if defined(MBEDTLS_SSL_SRV_C)
+        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
+            ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC;
+        }
+#endif
+    } else {
+        ssl->state++;
+    }
+
+    /*
+     * Switch to our negotiated transform and session parameters for outbound
+     * data.
+     */
+    MBEDTLS_SSL_DEBUG_MSG(3, ("switching to new transform spec for outbound data"));
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        unsigned char i;
+
+        /* Remember current epoch settings for resending */
+        ssl->handshake->alt_transform_out = ssl->transform_out;
+        memcpy(ssl->handshake->alt_out_ctr, ssl->cur_out_ctr,
+               sizeof(ssl->handshake->alt_out_ctr));
+
+        /* Set sequence_number to zero */
+        memset(&ssl->cur_out_ctr[2], 0, sizeof(ssl->cur_out_ctr) - 2);
+
+
+        /* Increment epoch */
+        for (i = 2; i > 0; i--) {
+            if (++ssl->cur_out_ctr[i - 1] != 0) {
+                break;
+            }
+        }
+
+        /* The loop goes to its end iff the counter is wrapping */
+        if (i == 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS epoch would wrap"));
+            return MBEDTLS_ERR_SSL_COUNTER_WRAPPING;
+        }
+    } else
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+    memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr));
+
+    ssl->transform_out = ssl->transform_negotiate;
+    ssl->session_out = ssl->session_negotiate;
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        mbedtls_ssl_send_flight_completed(ssl);
+    }
+#endif
+
+    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret);
+        return ret;
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        (ret = mbedtls_ssl_flight_transmit(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret);
+        return ret;
+    }
+#endif
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write finished"));
+
+    return 0;
+}
+
+#define SSL_MAX_HASH_LEN 12
+
+int mbedtls_ssl_parse_finished(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned int hash_len = 12;
+    unsigned char buf[SSL_MAX_HASH_LEN];
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse finished"));
+
+    ret = ssl->handshake->calc_finished(ssl, buf, ssl->conf->endpoint ^ 1);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "calc_finished", ret);
+    }
+
+    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
+        goto exit;
+    }
+
+    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
+        ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+        goto exit;
+    }
+
+    if (ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED) {
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
+        ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+        goto exit;
+    }
+
+    if (ssl->in_hslen  != mbedtls_ssl_hs_hdr_len(ssl) + hash_len) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        ret = MBEDTLS_ERR_SSL_DECODE_ERROR;
+        goto exit;
+    }
+
+    if (mbedtls_ct_memcmp(ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl),
+                          buf, hash_len) != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR);
+        ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+        goto exit;
+    }
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    ssl->verify_data_len = hash_len;
+    memcpy(ssl->peer_verify_data, buf, hash_len);
+#endif
+
+    if (ssl->handshake->resume != 0) {
+#if defined(MBEDTLS_SSL_CLI_C)
+        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+            ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC;
+        }
+#endif
+#if defined(MBEDTLS_SSL_SRV_C)
+        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
+            ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
+        }
+#endif
+    } else {
+        ssl->state++;
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        mbedtls_ssl_recv_flight_completed(ssl);
+    }
+#endif
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse finished"));
+
+exit:
+    mbedtls_platform_zeroize(buf, hash_len);
+    return ret;
+}
+
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+/*
+ * Helper to get TLS 1.2 PRF from ciphersuite
+ * (Duplicates bits of logic from ssl_set_handshake_prfs().)
+ */
+static tls_prf_fn ssl_tls12prf_from_cs(int ciphersuite_id)
+{
+    const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
+        mbedtls_ssl_ciphersuite_from_id(ciphersuite_id);
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    if (ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA384) {
+        return tls_prf_sha384;
+    } else
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    {
+        if (ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA256) {
+            return tls_prf_sha256;
+        }
+    }
+#endif
+#if !defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
+    !defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    (void) ciphersuite_info;
+#endif
+
+    return NULL;
+}
+#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
+
+static mbedtls_tls_prf_types tls_prf_get_type(mbedtls_ssl_tls_prf_cb *tls_prf)
+{
+    ((void) tls_prf);
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    if (tls_prf == tls_prf_sha384) {
+        return MBEDTLS_SSL_TLS_PRF_SHA384;
+    } else
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    if (tls_prf == tls_prf_sha256) {
+        return MBEDTLS_SSL_TLS_PRF_SHA256;
+    } else
+#endif
+    return MBEDTLS_SSL_TLS_PRF_NONE;
+}
+
+/*
+ * Populate a transform structure with session keys and all the other
+ * necessary information.
+ *
+ * Parameters:
+ * - [in/out]: transform: structure to populate
+ *      [in] must be just initialised with mbedtls_ssl_transform_init()
+ *      [out] fully populated, ready for use by mbedtls_ssl_{en,de}crypt_buf()
+ * - [in] ciphersuite
+ * - [in] master
+ * - [in] encrypt_then_mac
+ * - [in] tls_prf: pointer to PRF to use for key derivation
+ * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random
+ * - [in] tls_version: TLS version
+ * - [in] endpoint: client or server
+ * - [in] ssl: used for:
+ *        - ssl->conf->{f,p}_export_keys
+ *      [in] optionally used for:
+ *        - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls12_populate_transform(mbedtls_ssl_transform *transform,
+                                        int ciphersuite,
+                                        const unsigned char master[48],
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+                                        int encrypt_then_mac,
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
+                                        ssl_tls_prf_t tls_prf,
+                                        const unsigned char randbytes[64],
+                                        mbedtls_ssl_protocol_version tls_version,
+                                        unsigned endpoint,
+                                        const mbedtls_ssl_context *ssl)
+{
+    int ret = 0;
+    unsigned char keyblk[256];
+    unsigned char *key1;
+    unsigned char *key2;
+    unsigned char *mac_enc;
+    unsigned char *mac_dec;
+    size_t mac_key_len = 0;
+    size_t iv_copy_len;
+    size_t keylen;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+    mbedtls_ssl_mode_t ssl_mode;
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
+    const mbedtls_cipher_info_t *cipher_info;
+    const mbedtls_md_info_t *md_info;
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_key_type_t key_type;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_algorithm_t alg;
+    psa_algorithm_t mac_alg = 0;
+    size_t key_bits;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+#endif
+
+#if !defined(MBEDTLS_DEBUG_C) && \
+    !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    if (ssl->f_export_keys == NULL) {
+        ssl = NULL; /* make sure we don't use it except for these cases */
+        (void) ssl;
+    }
+#endif
+
+    /*
+     * Some data just needs copying into the structure
+     */
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+    transform->encrypt_then_mac = encrypt_then_mac;
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
+    transform->tls_version = tls_version;
+
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+    memcpy(transform->randbytes, randbytes, sizeof(transform->randbytes));
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
+        /* At the moment, we keep TLS <= 1.2 and TLS 1.3 transform
+         * generation separate. This should never happen. */
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+    /*
+     * Get various info structures
+     */
+    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite);
+    if (ciphersuite_info == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("ciphersuite info for %d not found",
+                                  ciphersuite));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    ssl_mode = mbedtls_ssl_get_mode_from_ciphersuite(
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+        encrypt_then_mac,
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
+        ciphersuite_info);
+
+    if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) {
+        transform->taglen =
+            ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;
+    }
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if ((status = mbedtls_ssl_cipher_to_psa(ciphersuite_info->cipher,
+                                            transform->taglen,
+                                            &alg,
+                                            &key_type,
+                                            &key_bits)) != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_cipher_to_psa", ret);
+        goto end;
+    }
+#else
+    cipher_info = mbedtls_cipher_info_from_type(ciphersuite_info->cipher);
+    if (cipher_info == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("cipher info for %u not found",
+                                  ciphersuite_info->cipher));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    mac_alg = mbedtls_hash_info_psa_from_md(ciphersuite_info->mac);
+    if (mac_alg == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("mbedtls_hash_info_psa_from_md for %u not found",
+                                  (unsigned) ciphersuite_info->mac));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+#else
+    md_info = mbedtls_md_info_from_type(ciphersuite_info->mac);
+    if (md_info == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("mbedtls_md info for %u not found",
+                                  (unsigned) ciphersuite_info->mac));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    /* Copy own and peer's CID if the use of the CID
+     * extension has been negotiated. */
+    if (ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_ENABLED) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("Copy CIDs into SSL transform"));
+
+        transform->in_cid_len = ssl->own_cid_len;
+        memcpy(transform->in_cid, ssl->own_cid, ssl->own_cid_len);
+        MBEDTLS_SSL_DEBUG_BUF(3, "Incoming CID", transform->in_cid,
+                              transform->in_cid_len);
+
+        transform->out_cid_len = ssl->handshake->peer_cid_len;
+        memcpy(transform->out_cid, ssl->handshake->peer_cid,
+               ssl->handshake->peer_cid_len);
+        MBEDTLS_SSL_DEBUG_BUF(3, "Outgoing CID", transform->out_cid,
+                              transform->out_cid_len);
+    }
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+    /*
+     * Compute key block using the PRF
+     */
+    ret = tls_prf(master, 48, "key expansion", randbytes, 64, keyblk, 256);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "prf", ret);
+        return ret;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite = %s",
+                              mbedtls_ssl_get_ciphersuite_name(ciphersuite)));
+    MBEDTLS_SSL_DEBUG_BUF(3, "master secret", master, 48);
+    MBEDTLS_SSL_DEBUG_BUF(4, "random bytes", randbytes, 64);
+    MBEDTLS_SSL_DEBUG_BUF(4, "key block", keyblk, 256);
+
+    /*
+     * Determine the appropriate key, IV and MAC length.
+     */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    keylen = PSA_BITS_TO_BYTES(key_bits);
+#else
+    keylen = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;
+#endif
+
+#if defined(MBEDTLS_GCM_C) ||                           \
+    defined(MBEDTLS_CCM_C) ||                           \
+    defined(MBEDTLS_CHACHAPOLY_C)
+    if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) {
+        size_t explicit_ivlen;
+
+        transform->maclen = 0;
+        mac_key_len = 0;
+
+        /* All modes haves 96-bit IVs, but the length of the static parts vary
+         * with mode and version:
+         * - For GCM and CCM in TLS 1.2, there's a static IV of 4 Bytes
+         *   (to be concatenated with a dynamically chosen IV of 8 Bytes)
+         * - For ChaChaPoly in TLS 1.2, and all modes in TLS 1.3, there's
+         *   a static IV of 12 Bytes (to be XOR'ed with the 8 Byte record
+         *   sequence number).
+         */
+        transform->ivlen = 12;
+
+        int is_chachapoly = 0;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        is_chachapoly = (key_type == PSA_KEY_TYPE_CHACHA20);
+#else
+        is_chachapoly = (mbedtls_cipher_info_get_mode(cipher_info)
+                         == MBEDTLS_MODE_CHACHAPOLY);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+        if (is_chachapoly) {
+            transform->fixed_ivlen = 12;
+        } else {
+            transform->fixed_ivlen = 4;
+        }
+
+        /* Minimum length of encrypted record */
+        explicit_ivlen = transform->ivlen - transform->fixed_ivlen;
+        transform->minlen = explicit_ivlen + transform->taglen;
+    } else
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
+    if (ssl_mode == MBEDTLS_SSL_MODE_STREAM ||
+        ssl_mode == MBEDTLS_SSL_MODE_CBC ||
+        ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        size_t block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type);
+#else
+        size_t block_size = cipher_info->block_size;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        /* Get MAC length */
+        mac_key_len = PSA_HASH_LENGTH(mac_alg);
+#else
+        /* Initialize HMAC contexts */
+        if ((ret = mbedtls_md_setup(&transform->md_ctx_enc, md_info, 1)) != 0 ||
+            (ret = mbedtls_md_setup(&transform->md_ctx_dec, md_info, 1)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_setup", ret);
+            goto end;
+        }
+
+        /* Get MAC length */
+        mac_key_len = mbedtls_md_get_size(md_info);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+        transform->maclen = mac_key_len;
+
+        /* IV length */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        transform->ivlen = PSA_CIPHER_IV_LENGTH(key_type, alg);
+#else
+        transform->ivlen = cipher_info->iv_size;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+        /* Minimum length */
+        if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) {
+            transform->minlen = transform->maclen;
+        } else {
+            /*
+             * GenericBlockCipher:
+             * 1. if EtM is in use: one block plus MAC
+             *    otherwise: * first multiple of blocklen greater than maclen
+             * 2. IV
+             */
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+            if (ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) {
+                transform->minlen = transform->maclen
+                                    + block_size;
+            } else
+#endif
+            {
+                transform->minlen = transform->maclen
+                                    + block_size
+                                    - transform->maclen % block_size;
+            }
+
+            if (tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {
+                transform->minlen += transform->ivlen;
+            } else {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+                ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+                goto end;
+            }
+        }
+    } else
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
+    {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("keylen: %u, minlen: %u, ivlen: %u, maclen: %u",
+                              (unsigned) keylen,
+                              (unsigned) transform->minlen,
+                              (unsigned) transform->ivlen,
+                              (unsigned) transform->maclen));
+
+    /*
+     * Finally setup the cipher contexts, IVs and MAC secrets.
+     */
+#if defined(MBEDTLS_SSL_CLI_C)
+    if (endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        key1 = keyblk + mac_key_len * 2;
+        key2 = keyblk + mac_key_len * 2 + keylen;
+
+        mac_enc = keyblk;
+        mac_dec = keyblk + mac_key_len;
+
+        iv_copy_len = (transform->fixed_ivlen) ?
+                      transform->fixed_ivlen : transform->ivlen;
+        memcpy(transform->iv_enc, key2 + keylen,  iv_copy_len);
+        memcpy(transform->iv_dec, key2 + keylen + iv_copy_len,
+               iv_copy_len);
+    } else
+#endif /* MBEDTLS_SSL_CLI_C */
+#if defined(MBEDTLS_SSL_SRV_C)
+    if (endpoint == MBEDTLS_SSL_IS_SERVER) {
+        key1 = keyblk + mac_key_len * 2 + keylen;
+        key2 = keyblk + mac_key_len * 2;
+
+        mac_enc = keyblk + mac_key_len;
+        mac_dec = keyblk;
+
+        iv_copy_len = (transform->fixed_ivlen) ?
+                      transform->fixed_ivlen : transform->ivlen;
+        memcpy(transform->iv_dec, key1 + keylen,  iv_copy_len);
+        memcpy(transform->iv_enc, key1 + keylen + iv_copy_len,
+               iv_copy_len);
+    } else
+#endif /* MBEDTLS_SSL_SRV_C */
+    {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        goto end;
+    }
+
+    if (ssl != NULL && ssl->f_export_keys != NULL) {
+        ssl->f_export_keys(ssl->p_export_keys,
+                           MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET,
+                           master, 48,
+                           randbytes + 32,
+                           randbytes,
+                           tls_prf_get_type(tls_prf));
+    }
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    transform->psa_alg = alg;
+
+    if (alg != MBEDTLS_SSL_NULL_CIPHER) {
+        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
+        psa_set_key_algorithm(&attributes, alg);
+        psa_set_key_type(&attributes, key_type);
+
+        if ((status = psa_import_key(&attributes,
+                                     key1,
+                                     PSA_BITS_TO_BYTES(key_bits),
+                                     &transform->psa_key_enc)) != PSA_SUCCESS) {
+            MBEDTLS_SSL_DEBUG_RET(3, "psa_import_key", (int) status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", ret);
+            goto end;
+        }
+
+        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
+
+        if ((status = psa_import_key(&attributes,
+                                     key2,
+                                     PSA_BITS_TO_BYTES(key_bits),
+                                     &transform->psa_key_dec)) != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", ret);
+            goto end;
+        }
+    }
+#else
+    if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_enc,
+                                    cipher_info)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret);
+        goto end;
+    }
+
+    if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_dec,
+                                    cipher_info)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret);
+        goto end;
+    }
+
+    if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_enc, key1,
+                                     (int) mbedtls_cipher_info_get_key_bitlen(cipher_info),
+                                     MBEDTLS_ENCRYPT)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret);
+        goto end;
+    }
+
+    if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_dec, key2,
+                                     (int) mbedtls_cipher_info_get_key_bitlen(cipher_info),
+                                     MBEDTLS_DECRYPT)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret);
+        goto end;
+    }
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    if (mbedtls_cipher_info_get_mode(cipher_info) == MBEDTLS_MODE_CBC) {
+        if ((ret = mbedtls_cipher_set_padding_mode(&transform->cipher_ctx_enc,
+                                                   MBEDTLS_PADDING_NONE)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_set_padding_mode", ret);
+            goto end;
+        }
+
+        if ((ret = mbedtls_cipher_set_padding_mode(&transform->cipher_ctx_dec,
+                                                   MBEDTLS_PADDING_NONE)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_set_padding_mode", ret);
+            goto end;
+        }
+    }
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
+    /* For HMAC-based ciphersuites, initialize the HMAC transforms.
+       For AEAD-based ciphersuites, there is nothing to do here. */
+    if (mac_key_len != 0) {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        transform->psa_mac_alg = PSA_ALG_HMAC(mac_alg);
+
+        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
+        psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(mac_alg));
+        psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
+
+        if ((status = psa_import_key(&attributes,
+                                     mac_enc, mac_key_len,
+                                     &transform->psa_mac_enc)) != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_mac_key", ret);
+            goto end;
+        }
+
+        if ((transform->psa_alg == MBEDTLS_SSL_NULL_CIPHER) ||
+            ((transform->psa_alg == PSA_ALG_CBC_NO_PADDING)
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+             && (transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED)
+#endif
+            )) {
+            /* mbedtls_ct_hmac() requires the key to be exportable */
+            psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT |
+                                    PSA_KEY_USAGE_VERIFY_HASH);
+        } else {
+            psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
+        }
+
+        if ((status = psa_import_key(&attributes,
+                                     mac_dec, mac_key_len,
+                                     &transform->psa_mac_dec)) != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_mac_key", ret);
+            goto end;
+        }
+#else
+        ret = mbedtls_md_hmac_starts(&transform->md_ctx_enc, mac_enc, mac_key_len);
+        if (ret != 0) {
+            goto end;
+        }
+        ret = mbedtls_md_hmac_starts(&transform->md_ctx_dec, mac_dec, mac_key_len);
+        if (ret != 0) {
+            goto end;
+        }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    }
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
+
+    ((void) mac_dec);
+    ((void) mac_enc);
+
+end:
+    mbedtls_platform_zeroize(keyblk, sizeof(keyblk));
+    return ret;
+}
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
+    defined(MBEDTLS_USE_PSA_CRYPTO)
+int mbedtls_psa_ecjpake_read_round(
+    psa_pake_operation_t *pake_ctx,
+    const unsigned char *buf,
+    size_t len, mbedtls_ecjpake_rounds_t round)
+{
+    psa_status_t status;
+    size_t input_offset = 0;
+    /*
+     * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice
+     * At round two perform a single cycle
+     */
+    unsigned int remaining_steps = (round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1;
+
+    for (; remaining_steps > 0; remaining_steps--) {
+        for (psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE;
+             step <= PSA_PAKE_STEP_ZK_PROOF;
+             ++step) {
+            /* Length is stored at the first byte */
+            size_t length = buf[input_offset];
+            input_offset += 1;
+
+            if (input_offset + length > len) {
+                return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+            }
+
+            status = psa_pake_input(pake_ctx, step,
+                                    buf + input_offset, length);
+            if (status != PSA_SUCCESS) {
+                return PSA_TO_MBEDTLS_ERR(status);
+            }
+
+            input_offset += length;
+        }
+    }
+
+    if (input_offset != len) {
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+    return 0;
+}
+
+int mbedtls_psa_ecjpake_write_round(
+    psa_pake_operation_t *pake_ctx,
+    unsigned char *buf,
+    size_t len, size_t *olen,
+    mbedtls_ecjpake_rounds_t round)
+{
+    psa_status_t status;
+    size_t output_offset = 0;
+    size_t output_len;
+    /*
+     * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice
+     * At round two perform a single cycle
+     */
+    unsigned int remaining_steps = (round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1;
+
+    for (; remaining_steps > 0; remaining_steps--) {
+        for (psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE;
+             step <= PSA_PAKE_STEP_ZK_PROOF;
+             ++step) {
+            /*
+             * For each step, prepend 1 byte with the length of the data as
+             * given by psa_pake_output().
+             */
+            status = psa_pake_output(pake_ctx, step,
+                                     buf + output_offset + 1,
+                                     len - output_offset - 1,
+                                     &output_len);
+            if (status != PSA_SUCCESS) {
+                return PSA_TO_MBEDTLS_ERR(status);
+            }
+
+            *(buf + output_offset) = (uint8_t) output_len;
+
+            output_offset += output_len + 1;
+        }
+    }
+
+    *olen = output_offset;
+
+    return 0;
+}
+#endif //MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl,
+                                           unsigned char *hash, size_t *hashlen,
+                                           unsigned char *data, size_t data_len,
+                                           mbedtls_md_type_t md_alg)
 {
     psa_status_t status;
     psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT;
-    psa_algorithm_t hash_alg = mbedtls_psa_translate_md( md_alg );
+    psa_algorithm_t hash_alg = mbedtls_hash_info_psa_from_md(md_alg);
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "Perform PSA-based computation of digest of ServerKeyExchange" ) );
+    MBEDTLS_SSL_DEBUG_MSG(3, ("Perform PSA-based computation of digest of ServerKeyExchange"));
 
-    if( ( status = psa_hash_setup( &hash_operation,
-                                   hash_alg ) ) != PSA_SUCCESS )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_setup", status );
+    if ((status = psa_hash_setup(&hash_operation,
+                                 hash_alg)) != PSA_SUCCESS) {
+        MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_setup", status);
         goto exit;
     }
 
-    if( ( status = psa_hash_update( &hash_operation, ssl->handshake->randbytes,
-                                    64 ) ) != PSA_SUCCESS )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_update", status );
+    if ((status = psa_hash_update(&hash_operation, ssl->handshake->randbytes,
+                                  64)) != PSA_SUCCESS) {
+        MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_update", status);
         goto exit;
     }
 
-    if( ( status = psa_hash_update( &hash_operation,
-                                    data, data_len ) ) != PSA_SUCCESS )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_update", status );
+    if ((status = psa_hash_update(&hash_operation,
+                                  data, data_len)) != PSA_SUCCESS) {
+        MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_update", status);
         goto exit;
     }
 
-    if( ( status = psa_hash_finish( &hash_operation, hash, PSA_HASH_MAX_SIZE,
-                                    hashlen ) ) != PSA_SUCCESS )
-    {
-         MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_finish", status );
-         goto exit;
+    if ((status = psa_hash_finish(&hash_operation, hash, PSA_HASH_MAX_SIZE,
+                                  hashlen)) != PSA_SUCCESS) {
+        MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_finish", status);
+        goto exit;
     }
 
 exit:
-    if( status != PSA_SUCCESS )
-    {
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
-        switch( status )
-        {
+    if (status != PSA_SUCCESS) {
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);
+        switch (status) {
             case PSA_ERROR_NOT_SUPPORTED:
-                return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
+                return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
             case PSA_ERROR_BAD_STATE: /* Intentional fallthrough */
             case PSA_ERROR_BUFFER_TOO_SMALL:
-                return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+                return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
             case PSA_ERROR_INSUFFICIENT_MEMORY:
-                return( MBEDTLS_ERR_MD_ALLOC_FAILED );
+                return MBEDTLS_ERR_MD_ALLOC_FAILED;
             default:
-                return( MBEDTLS_ERR_MD_HW_ACCEL_FAILED );
+                return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
         }
     }
-    return( 0 );
+    return 0;
 }
 
 #else
 
-int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
-                                            unsigned char *hash, size_t *hashlen,
-                                            unsigned char *data, size_t data_len,
-                                            mbedtls_md_type_t md_alg )
+int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl,
+                                           unsigned char *hash, size_t *hashlen,
+                                           unsigned char *data, size_t data_len,
+                                           mbedtls_md_type_t md_alg)
 {
     int ret = 0;
     mbedtls_md_context_t ctx;
-    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
-    *hashlen = mbedtls_md_get_size( md_info );
+    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_alg);
+    *hashlen = mbedtls_md_get_size(md_info);
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "Perform mbedtls-based computation of digest of ServerKeyExchange" ) );
+    MBEDTLS_SSL_DEBUG_MSG(3, ("Perform mbedtls-based computation of digest of ServerKeyExchange"));
 
-    mbedtls_md_init( &ctx );
+    mbedtls_md_init(&ctx);
 
     /*
      * digitally-signed struct {
@@ -7699,44 +8844,852 @@
      *     ServerDHParams params;
      * };
      */
-    if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret );
+    if ((ret = mbedtls_md_setup(&ctx, md_info, 0)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_setup", ret);
         goto exit;
     }
-    if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_starts", ret );
+    if ((ret = mbedtls_md_starts(&ctx)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_starts", ret);
         goto exit;
     }
-    if( ( ret = mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret );
+    if ((ret = mbedtls_md_update(&ctx, ssl->handshake->randbytes, 64)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_update", ret);
         goto exit;
     }
-    if( ( ret = mbedtls_md_update( &ctx, data, data_len ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret );
+    if ((ret = mbedtls_md_update(&ctx, data, data_len)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_update", ret);
         goto exit;
     }
-    if( ( ret = mbedtls_md_finish( &ctx, hash ) ) != 0 )
-    {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_finish", ret );
+    if ((ret = mbedtls_md_finish(&ctx, hash)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret);
         goto exit;
     }
 
 exit:
-    mbedtls_md_free( &ctx );
+    mbedtls_md_free(&ctx);
 
-    if( ret != 0 )
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
+    if (ret != 0) {
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);
+    }
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
-          MBEDTLS_SSL_PROTO_TLS1_2 */
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+
+/* Find the preferred hash for a given signature algorithm. */
+unsigned int mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg(
+    mbedtls_ssl_context *ssl,
+    unsigned int sig_alg)
+{
+    unsigned int i;
+    uint16_t *received_sig_algs = ssl->handshake->received_sig_algs;
+
+    if (sig_alg == MBEDTLS_SSL_SIG_ANON) {
+        return MBEDTLS_SSL_HASH_NONE;
+    }
+
+    for (i = 0; received_sig_algs[i] != MBEDTLS_TLS_SIG_NONE; i++) {
+        unsigned int hash_alg_received =
+            MBEDTLS_SSL_TLS12_HASH_ALG_FROM_SIG_AND_HASH_ALG(
+                received_sig_algs[i]);
+        unsigned int sig_alg_received =
+            MBEDTLS_SSL_TLS12_SIG_ALG_FROM_SIG_AND_HASH_ALG(
+                received_sig_algs[i]);
+
+        if (sig_alg == sig_alg_received) {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+            if (ssl->handshake->key_cert && ssl->handshake->key_cert->key) {
+                psa_algorithm_t psa_hash_alg =
+                    mbedtls_hash_info_psa_from_md(hash_alg_received);
+
+                if (sig_alg_received == MBEDTLS_SSL_SIG_ECDSA &&
+                    !mbedtls_pk_can_do_ext(ssl->handshake->key_cert->key,
+                                           PSA_ALG_ECDSA(psa_hash_alg),
+                                           PSA_KEY_USAGE_SIGN_HASH)) {
+                    continue;
+                }
+
+                if (sig_alg_received == MBEDTLS_SSL_SIG_RSA &&
+                    !mbedtls_pk_can_do_ext(ssl->handshake->key_cert->key,
+                                           PSA_ALG_RSA_PKCS1V15_SIGN(
+                                               psa_hash_alg),
+                                           PSA_KEY_USAGE_SIGN_HASH)) {
+                    continue;
+                }
+            }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+            return hash_alg_received;
+        }
+    }
+
+    return MBEDTLS_SSL_HASH_NONE;
+}
+
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
+/* Serialization of TLS 1.2 sessions:
+ *
+ * struct {
+ *    uint64 start_time;
+ *    uint8 ciphersuite[2];           // defined by the standard
+ *    uint8 session_id_len;           // at most 32
+ *    opaque session_id[32];
+ *    opaque master[48];              // fixed length in the standard
+ *    uint32 verify_result;
+ *    opaque peer_cert<0..2^24-1>;    // length 0 means no peer cert
+ *    opaque ticket<0..2^24-1>;       // length 0 means no ticket
+ *    uint32 ticket_lifetime;
+ *    uint8 mfl_code;                 // up to 255 according to standard
+ *    uint8 encrypt_then_mac;         // 0 or 1
+ * } serialized_session_tls12;
+ *
+ */
+static size_t ssl_tls12_session_save(const mbedtls_ssl_session *session,
+                                     unsigned char *buf,
+                                     size_t buf_len)
+{
+    unsigned char *p = buf;
+    size_t used = 0;
+
+#if defined(MBEDTLS_HAVE_TIME)
+    uint64_t start;
+#endif
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    size_t cert_len;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+    /*
+     * Time
+     */
+#if defined(MBEDTLS_HAVE_TIME)
+    used += 8;
+
+    if (used <= buf_len) {
+        start = (uint64_t) session->start;
+
+        MBEDTLS_PUT_UINT64_BE(start, p, 0);
+        p += 8;
+    }
+#endif /* MBEDTLS_HAVE_TIME */
+
+    /*
+     * Basic mandatory fields
+     */
+    used += 2   /* ciphersuite */
+            + 1 /* id_len */
+            + sizeof(session->id)
+            + sizeof(session->master)
+            + 4; /* verify_result */
+
+    if (used <= buf_len) {
+        MBEDTLS_PUT_UINT16_BE(session->ciphersuite, p, 0);
+        p += 2;
+
+        *p++ = MBEDTLS_BYTE_0(session->id_len);
+        memcpy(p, session->id, 32);
+        p += 32;
+
+        memcpy(p, session->master, 48);
+        p += 48;
+
+        MBEDTLS_PUT_UINT32_BE(session->verify_result, p, 0);
+        p += 4;
+    }
+
+    /*
+     * Peer's end-entity certificate
+     */
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    if (session->peer_cert == NULL) {
+        cert_len = 0;
+    } else {
+        cert_len = session->peer_cert->raw.len;
+    }
+
+    used += 3 + cert_len;
+
+    if (used <= buf_len) {
+        *p++ = MBEDTLS_BYTE_2(cert_len);
+        *p++ = MBEDTLS_BYTE_1(cert_len);
+        *p++ = MBEDTLS_BYTE_0(cert_len);
+
+        if (session->peer_cert != NULL) {
+            memcpy(p, session->peer_cert->raw.p, cert_len);
+            p += cert_len;
+        }
+    }
+#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+    if (session->peer_cert_digest != NULL) {
+        used += 1 /* type */ + 1 /* length */ + session->peer_cert_digest_len;
+        if (used <= buf_len) {
+            *p++ = (unsigned char) session->peer_cert_digest_type;
+            *p++ = (unsigned char) session->peer_cert_digest_len;
+            memcpy(p, session->peer_cert_digest,
+                   session->peer_cert_digest_len);
+            p += session->peer_cert_digest_len;
+        }
+    } else {
+        used += 2;
+        if (used <= buf_len) {
+            *p++ = (unsigned char) MBEDTLS_MD_NONE;
+            *p++ = 0;
+        }
+    }
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+    /*
+     * Session ticket if any, plus associated data
+     */
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+    used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */
+
+    if (used <= buf_len) {
+        *p++ = MBEDTLS_BYTE_2(session->ticket_len);
+        *p++ = MBEDTLS_BYTE_1(session->ticket_len);
+        *p++ = MBEDTLS_BYTE_0(session->ticket_len);
+
+        if (session->ticket != NULL) {
+            memcpy(p, session->ticket, session->ticket_len);
+            p += session->ticket_len;
+        }
+
+        MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0);
+        p += 4;
+    }
+#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
+
+    /*
+     * Misc extension-related info
+     */
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+    used += 1;
+
+    if (used <= buf_len) {
+        *p++ = session->mfl_code;
+    }
+#endif
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+    used += 1;
+
+    if (used <= buf_len) {
+        *p++ = MBEDTLS_BYTE_0(session->encrypt_then_mac);
+    }
+#endif
+
+    return used;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls12_session_load(mbedtls_ssl_session *session,
+                                  const unsigned char *buf,
+                                  size_t len)
+{
+#if defined(MBEDTLS_HAVE_TIME)
+    uint64_t start;
+#endif
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    size_t cert_len;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+    const unsigned char *p = buf;
+    const unsigned char * const end = buf + len;
+
+    /*
+     * Time
+     */
+#if defined(MBEDTLS_HAVE_TIME)
+    if (8 > (size_t) (end - p)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    start = ((uint64_t) p[0] << 56) |
+            ((uint64_t) p[1] << 48) |
+            ((uint64_t) p[2] << 40) |
+            ((uint64_t) p[3] << 32) |
+            ((uint64_t) p[4] << 24) |
+            ((uint64_t) p[5] << 16) |
+            ((uint64_t) p[6] <<  8) |
+            ((uint64_t) p[7]);
+    p += 8;
+
+    session->start = (time_t) start;
+#endif /* MBEDTLS_HAVE_TIME */
+
+    /*
+     * Basic mandatory fields
+     */
+    if (2 + 1 + 32 + 48 + 4 > (size_t) (end - p)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    session->ciphersuite = (p[0] << 8) | p[1];
+    p += 2;
+
+    session->id_len = *p++;
+    memcpy(session->id, p, 32);
+    p += 32;
+
+    memcpy(session->master, p, 48);
+    p += 48;
+
+    session->verify_result = ((uint32_t) p[0] << 24) |
+                             ((uint32_t) p[1] << 16) |
+                             ((uint32_t) p[2] <<  8) |
+                             ((uint32_t) p[3]);
+    p += 4;
+
+    /* Immediately clear invalid pointer values that have been read, in case
+     * we exit early before we replaced them with valid ones. */
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    session->peer_cert = NULL;
+#else
+    session->peer_cert_digest = NULL;
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+    session->ticket = NULL;
+#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
+
+    /*
+     * Peer certificate
+     */
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    /* Deserialize CRT from the end of the ticket. */
+    if (3 > (size_t) (end - p)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    cert_len = (p[0] << 16) | (p[1] << 8) | p[2];
+    p += 3;
+
+    if (cert_len != 0) {
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+        if (cert_len > (size_t) (end - p)) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+
+        session->peer_cert = mbedtls_calloc(1, sizeof(mbedtls_x509_crt));
+
+        if (session->peer_cert == NULL) {
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        }
+
+        mbedtls_x509_crt_init(session->peer_cert);
+
+        if ((ret = mbedtls_x509_crt_parse_der(session->peer_cert,
+                                              p, cert_len)) != 0) {
+            mbedtls_x509_crt_free(session->peer_cert);
+            mbedtls_free(session->peer_cert);
+            session->peer_cert = NULL;
+            return ret;
+        }
+
+        p += cert_len;
+    }
+#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+    /* Deserialize CRT digest from the end of the ticket. */
+    if (2 > (size_t) (end - p)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    session->peer_cert_digest_type = (mbedtls_md_type_t) *p++;
+    session->peer_cert_digest_len  = (size_t) *p++;
+
+    if (session->peer_cert_digest_len != 0) {
+        const mbedtls_md_info_t *md_info =
+            mbedtls_md_info_from_type(session->peer_cert_digest_type);
+        if (md_info == NULL) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+        if (session->peer_cert_digest_len != mbedtls_md_get_size(md_info)) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+
+        if (session->peer_cert_digest_len > (size_t) (end - p)) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+
+        session->peer_cert_digest =
+            mbedtls_calloc(1, session->peer_cert_digest_len);
+        if (session->peer_cert_digest == NULL) {
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        }
+
+        memcpy(session->peer_cert_digest, p,
+               session->peer_cert_digest_len);
+        p += session->peer_cert_digest_len;
+    }
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+    /*
+     * Session ticket and associated data
+     */
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+    if (3 > (size_t) (end - p)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    session->ticket_len = (p[0] << 16) | (p[1] << 8) | p[2];
+    p += 3;
+
+    if (session->ticket_len != 0) {
+        if (session->ticket_len > (size_t) (end - p)) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+
+        session->ticket = mbedtls_calloc(1, session->ticket_len);
+        if (session->ticket == NULL) {
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        }
+
+        memcpy(session->ticket, p, session->ticket_len);
+        p += session->ticket_len;
+    }
+
+    if (4 > (size_t) (end - p)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    session->ticket_lifetime = ((uint32_t) p[0] << 24) |
+                               ((uint32_t) p[1] << 16) |
+                               ((uint32_t) p[2] <<  8) |
+                               ((uint32_t) p[3]);
+    p += 4;
+#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
+
+    /*
+     * Misc extension-related info
+     */
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+    if (1 > (size_t) (end - p)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    session->mfl_code = *p++;
+#endif
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+    if (1 > (size_t) (end - p)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    session->encrypt_then_mac = *p++;
+#endif
+
+    /* Done, should have consumed entire buffer */
+    if (p != end) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+int mbedtls_ssl_validate_ciphersuite(
+    const mbedtls_ssl_context *ssl,
+    const mbedtls_ssl_ciphersuite_t *suite_info,
+    mbedtls_ssl_protocol_version min_tls_version,
+    mbedtls_ssl_protocol_version max_tls_version)
+{
+    (void) ssl;
+
+    if (suite_info == NULL) {
+        return -1;
+    }
+
+    if ((suite_info->min_tls_version > max_tls_version) ||
+        (suite_info->max_tls_version < min_tls_version)) {
+        return -1;
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_CLI_C)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE &&
+        ssl->handshake->psa_pake_ctx_is_ok != 1)
+#else
+    if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE &&
+        mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0)
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    {
+        return -1;
+    }
+#endif
+
+    /* Don't suggest PSK-based ciphersuite if no PSK is available. */
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+    if (mbedtls_ssl_ciphersuite_uses_psk(suite_info) &&
+        mbedtls_ssl_conf_has_static_psk(ssl->conf) == 0) {
+        return -1;
+    }
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+    return 0;
+}
+
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+/*
+ * Function for writing a signature algorithm extension.
+ *
+ * The `extension_data` field of signature algorithm contains  a `SignatureSchemeList`
+ * value (TLS 1.3 RFC8446):
+ *      enum {
+ *         ....
+ *        ecdsa_secp256r1_sha256( 0x0403 ),
+ *        ecdsa_secp384r1_sha384( 0x0503 ),
+ *        ecdsa_secp521r1_sha512( 0x0603 ),
+ *         ....
+ *      } SignatureScheme;
+ *
+ *      struct {
+ *         SignatureScheme supported_signature_algorithms<2..2^16-2>;
+ *      } SignatureSchemeList;
+ *
+ * The `extension_data` field of signature algorithm contains a `SignatureAndHashAlgorithm`
+ * value (TLS 1.2 RFC5246):
+ *      enum {
+ *          none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
+ *          sha512(6), (255)
+ *      } HashAlgorithm;
+ *
+ *      enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
+ *        SignatureAlgorithm;
+ *
+ *      struct {
+ *          HashAlgorithm hash;
+ *          SignatureAlgorithm signature;
+ *      } SignatureAndHashAlgorithm;
+ *
+ *      SignatureAndHashAlgorithm
+ *        supported_signature_algorithms<2..2^16-2>;
+ *
+ * The TLS 1.3 signature algorithm extension was defined to be a compatible
+ * generalization of the TLS 1.2 signature algorithm extension.
+ * `SignatureAndHashAlgorithm` field of TLS 1.2 can be represented by
+ * `SignatureScheme` field of TLS 1.3
+ *
+ */
+int mbedtls_ssl_write_sig_alg_ext(mbedtls_ssl_context *ssl, unsigned char *buf,
+                                  const unsigned char *end, size_t *out_len)
+{
+    unsigned char *p = buf;
+    unsigned char *supported_sig_alg; /* Start of supported_signature_algorithms */
+    size_t supported_sig_alg_len = 0; /* Length of supported_signature_algorithms */
+
+    *out_len = 0;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("adding signature_algorithms extension"));
+
+    /* Check if we have space for header and length field:
+     * - extension_type         (2 bytes)
+     * - extension_data_length  (2 bytes)
+     * - supported_signature_algorithms_length   (2 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6);
+    p += 6;
+
+    /*
+     * Write supported_signature_algorithms
+     */
+    supported_sig_alg = p;
+    const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl);
+    if (sig_alg == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_CONFIG;
+    }
+
+    for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("got signature scheme [%x] %s",
+                                  *sig_alg,
+                                  mbedtls_ssl_sig_alg_to_str(*sig_alg)));
+        if (!mbedtls_ssl_sig_alg_is_supported(ssl, *sig_alg)) {
+            continue;
+        }
+        MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);
+        MBEDTLS_PUT_UINT16_BE(*sig_alg, p, 0);
+        p += 2;
+        MBEDTLS_SSL_DEBUG_MSG(3, ("sent signature scheme [%x] %s",
+                                  *sig_alg,
+                                  mbedtls_ssl_sig_alg_to_str(*sig_alg)));
+    }
+
+    /* Length of supported_signature_algorithms */
+    supported_sig_alg_len = p - supported_sig_alg;
+    if (supported_sig_alg_len == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("No signature algorithms defined."));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SIG_ALG, buf, 0);
+    MBEDTLS_PUT_UINT16_BE(supported_sig_alg_len + 2, buf, 2);
+    MBEDTLS_PUT_UINT16_BE(supported_sig_alg_len, buf, 4);
+
+    *out_len = p - buf;
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_SIG_ALG);
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
+
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+/*
+ * mbedtls_ssl_parse_server_name_ext
+ *
+ * Structure of server_name extension:
+ *
+ *  enum {
+ *        host_name(0), (255)
+ *     } NameType;
+ *  opaque HostName<1..2^16-1>;
+ *
+ *  struct {
+ *          NameType name_type;
+ *          select (name_type) {
+ *             case host_name: HostName;
+ *           } name;
+ *     } ServerName;
+ *  struct {
+ *          ServerName server_name_list<1..2^16-1>
+ *     } ServerNameList;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_parse_server_name_ext(mbedtls_ssl_context *ssl,
+                                      const unsigned char *buf,
+                                      const unsigned char *end)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const unsigned char *p = buf;
+    size_t server_name_list_len, hostname_len;
+    const unsigned char *server_name_list_end;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("parse ServerName extension"));
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    server_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, server_name_list_len);
+    server_name_list_end = p + server_name_list_len;
+    while (p < server_name_list_end) {
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, server_name_list_end, 3);
+        hostname_len = MBEDTLS_GET_UINT16_BE(p, 1);
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, server_name_list_end,
+                                     hostname_len + 3);
+
+        if (p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME) {
+            /* sni_name is intended to be used only during the parsing of the
+             * ClientHello message (it is reset to NULL before the end of
+             * the message parsing). Thus it is ok to just point to the
+             * reception buffer and not make a copy of it.
+             */
+            ssl->handshake->sni_name = p + 3;
+            ssl->handshake->sni_name_len = hostname_len;
+            if (ssl->conf->f_sni == NULL) {
+                return 0;
+            }
+            ret = ssl->conf->f_sni(ssl->conf->p_sni,
+                                   ssl, p + 3, hostname_len);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "ssl_sni_wrapper", ret);
+                MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME,
+                                             MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME);
+                return MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME;
+            }
+            return 0;
+        }
+
+        p += hostname_len + 3;
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+
+#if defined(MBEDTLS_SSL_ALPN)
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_parse_alpn_ext(mbedtls_ssl_context *ssl,
+                               const unsigned char *buf,
+                               const unsigned char *end)
+{
+    const unsigned char *p = buf;
+    size_t protocol_name_list_len;
+    const unsigned char *protocol_name_list;
+    const unsigned char *protocol_name_list_end;
+    size_t protocol_name_len;
+
+    /* If ALPN not configured, just ignore the extension */
+    if (ssl->conf->alpn_list == NULL) {
+        return 0;
+    }
+
+    /*
+     * RFC7301, section 3.1
+     *      opaque ProtocolName<1..2^8-1>;
+     *
+     *      struct {
+     *          ProtocolName protocol_name_list<2..2^16-1>
+     *      } ProtocolNameList;
+     */
+
+    /*
+     * protocol_name_list_len    2 bytes
+     * protocol_name_len         1 bytes
+     * protocol_name             >=1 byte
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4);
+
+    protocol_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, protocol_name_list_len);
+    protocol_name_list = p;
+    protocol_name_list_end = p + protocol_name_list_len;
+
+    /* Validate peer's list (lengths) */
+    while (p < protocol_name_list_end) {
+        protocol_name_len = *p++;
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end,
+                                     protocol_name_len);
+        if (protocol_name_len == 0) {
+            MBEDTLS_SSL_PEND_FATAL_ALERT(
+                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+        }
+
+        p += protocol_name_len;
+    }
+
+    /* Use our order of preference */
+    for (const char **alpn = ssl->conf->alpn_list; *alpn != NULL; alpn++) {
+        size_t const alpn_len = strlen(*alpn);
+        p = protocol_name_list;
+        while (p < protocol_name_list_end) {
+            protocol_name_len = *p++;
+            if (protocol_name_len == alpn_len &&
+                memcmp(p, *alpn, alpn_len) == 0) {
+                ssl->alpn_chosen = *alpn;
+                return 0;
+            }
+
+            p += protocol_name_len;
+        }
+    }
+
+    /* If we get here, no match was found */
+    MBEDTLS_SSL_PEND_FATAL_ALERT(
+        MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL,
+        MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL);
+    return MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL;
+}
+
+int mbedtls_ssl_write_alpn_ext(mbedtls_ssl_context *ssl,
+                               unsigned char *buf,
+                               unsigned char *end,
+                               size_t *out_len)
+{
+    unsigned char *p = buf;
+    size_t protocol_name_len;
+    *out_len = 0;
+
+    if (ssl->alpn_chosen == NULL) {
+        return 0;
+    }
+
+    protocol_name_len = strlen(ssl->alpn_chosen);
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 7 + protocol_name_len);
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server side, adding alpn extension"));
+    /*
+     * 0 . 1    ext identifier
+     * 2 . 3    ext length
+     * 4 . 5    protocol list length
+     * 6 . 6    protocol name length
+     * 7 . 7+n  protocol name
+     */
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ALPN, p, 0);
+
+    *out_len = 7 + protocol_name_len;
+
+    MBEDTLS_PUT_UINT16_BE(protocol_name_len + 3, p, 2);
+    MBEDTLS_PUT_UINT16_BE(protocol_name_len + 1, p, 4);
+    /* Note: the length of the chosen protocol has been checked to be less
+     * than 255 bytes in `mbedtls_ssl_conf_alpn_protocols`.
+     */
+    p[6] = MBEDTLS_BYTE_0(protocol_name_len);
+
+    memcpy(p + 7, ssl->alpn_chosen, protocol_name_len);
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_ALPN);
+#endif
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_ALPN */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
+    defined(MBEDTLS_SSL_SESSION_TICKETS) && \
+    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \
+    defined(MBEDTLS_SSL_CLI_C)
+int mbedtls_ssl_session_set_hostname(mbedtls_ssl_session *session,
+                                     const char *hostname)
+{
+    /* Initialize to suppress unnecessary compiler warning */
+    size_t hostname_len = 0;
+
+    /* Check if new hostname is valid before
+     * making any change to current one */
+    if (hostname != NULL) {
+        hostname_len = strlen(hostname);
+
+        if (hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+    }
+
+    /* Now it's clear that we will overwrite the old hostname,
+     * so we can free it safely */
+    if (session->hostname != NULL) {
+        mbedtls_platform_zeroize(session->hostname,
+                                 strlen(session->hostname));
+        mbedtls_free(session->hostname);
+    }
+
+    /* Passing NULL as hostname shall clear the old one */
+    if (hostname == NULL) {
+        session->hostname = NULL;
+    } else {
+        session->hostname = mbedtls_calloc(1, hostname_len + 1);
+        if (session->hostname == NULL) {
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        }
+
+        memcpy(session->hostname, hostname, hostname_len);
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 &&
+          MBEDTLS_SSL_SESSION_TICKETS &&
+          MBEDTLS_SSL_SERVER_NAME_INDICATION &&
+          MBEDTLS_SSL_CLI_C */
 
 #endif /* MBEDTLS_SSL_TLS_C */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls12_client.c b/lib/libmbedtls/mbedtls/library/ssl_tls12_client.c
new file mode 100644
index 0000000..890e9a9
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls12_client.c
@@ -0,0 +1,3600 @@
+/*
+ *  TLS client-side functions
+ *
+ *  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.
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_2)
+
+#include "mbedtls/platform.h"
+
+#include "mbedtls/ssl.h"
+#include "ssl_client.h"
+#include "ssl_misc.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
+#include "mbedtls/constant_time.h"
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "mbedtls/psa_util.h"
+#include "psa/crypto.h"
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_ssl_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#include <string.h>
+
+#include <stdint.h>
+
+#if defined(MBEDTLS_HAVE_TIME)
+#include "mbedtls/platform_time.h"
+#endif
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+#include "mbedtls/platform_util.h"
+#endif
+
+#include "hash_info.h"
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_renegotiation_ext(mbedtls_ssl_context *ssl,
+                                       unsigned char *buf,
+                                       const unsigned char *end,
+                                       size_t *olen)
+{
+    unsigned char *p = buf;
+
+    *olen = 0;
+
+    /* We're always including a TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the
+     * initial ClientHello, in which case also adding the renegotiation
+     * info extension is NOT RECOMMENDED as per RFC 5746 Section 3.4. */
+    if (ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {
+        return 0;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3,
+                          ("client hello, adding renegotiation extension"));
+
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 5 + ssl->verify_data_len);
+
+    /*
+     * Secure renegotiation
+     */
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_RENEGOTIATION_INFO, p, 0);
+    p += 2;
+
+    *p++ = 0x00;
+    *p++ = MBEDTLS_BYTE_0(ssl->verify_data_len + 1);
+    *p++ = MBEDTLS_BYTE_0(ssl->verify_data_len);
+
+    memcpy(p, ssl->own_verify_data, ssl->verify_data_len);
+
+    *olen = 5 + ssl->verify_data_len;
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl,
+                                                 unsigned char *buf,
+                                                 const unsigned char *end,
+                                                 size_t *olen)
+{
+    unsigned char *p = buf;
+    (void) ssl; /* ssl used for debugging only */
+
+    *olen = 0;
+
+    MBEDTLS_SSL_DEBUG_MSG(3,
+                          ("client hello, adding supported_point_formats extension"));
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6);
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, p, 0);
+    p += 2;
+
+    *p++ = 0x00;
+    *p++ = 2;
+
+    *p++ = 1;
+    *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED;
+
+    *olen = 6;
+
+    return 0;
+}
+#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
+          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl,
+                                      unsigned char *buf,
+                                      const unsigned char *end,
+                                      size_t *olen)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *p = buf;
+    size_t kkpp_len = 0;
+
+    *olen = 0;
+
+    /* Skip costly extension if we can't use EC J-PAKE anyway */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (ssl->handshake->psa_pake_ctx_is_ok != 1) {
+        return 0;
+    }
+#else
+    if (mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0) {
+        return 0;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    MBEDTLS_SSL_DEBUG_MSG(3,
+                          ("client hello, adding ecjpake_kkpp extension"));
+
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4);
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0);
+    p += 2;
+
+    /*
+     * We may need to send ClientHello multiple times for Hello verification.
+     * We don't want to compute fresh values every time (both for performance
+     * and consistency reasons), so cache the extension content.
+     */
+    if (ssl->handshake->ecjpake_cache == NULL ||
+        ssl->handshake->ecjpake_cache_len == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("generating new ecjpake parameters"));
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx,
+                                              p + 2, end - p - 2, &kkpp_len,
+                                              MBEDTLS_ECJPAKE_ROUND_ONE);
+        if (ret != 0) {
+            psa_destroy_key(ssl->handshake->psa_pake_password);
+            psa_pake_abort(&ssl->handshake->psa_pake_ctx);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret);
+            return ret;
+        }
+#else
+        ret = mbedtls_ecjpake_write_round_one(&ssl->handshake->ecjpake_ctx,
+                                              p + 2, end - p - 2, &kkpp_len,
+                                              ssl->conf->f_rng, ssl->conf->p_rng);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1,
+                                  "mbedtls_ecjpake_write_round_one", ret);
+            return ret;
+        }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+        ssl->handshake->ecjpake_cache = mbedtls_calloc(1, kkpp_len);
+        if (ssl->handshake->ecjpake_cache == NULL) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("allocation failed"));
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        }
+
+        memcpy(ssl->handshake->ecjpake_cache, p + 2, kkpp_len);
+        ssl->handshake->ecjpake_cache_len = kkpp_len;
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("re-using cached ecjpake parameters"));
+
+        kkpp_len = ssl->handshake->ecjpake_cache_len;
+        MBEDTLS_SSL_CHK_BUF_PTR(p + 2, end, kkpp_len);
+
+        memcpy(p + 2, ssl->handshake->ecjpake_cache, kkpp_len);
+    }
+
+    MBEDTLS_PUT_UINT16_BE(kkpp_len, p, 0);
+    p += 2;
+
+    *olen = kkpp_len + 4;
+
+    return 0;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_cid_ext(mbedtls_ssl_context *ssl,
+                             unsigned char *buf,
+                             const unsigned char *end,
+                             size_t *olen)
+{
+    unsigned char *p = buf;
+    size_t ext_len;
+
+    /*
+     *   struct {
+     *      opaque cid<0..2^8-1>;
+     *   } ConnectionId;
+     */
+
+    *olen = 0;
+    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
+        ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) {
+        return 0;
+    }
+    MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding CID extension"));
+
+    /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX
+     * which is at most 255, so the increment cannot overflow. */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, (unsigned) (ssl->own_cid_len + 5));
+
+    /* Add extension ID + size */
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_CID, p, 0);
+    p += 2;
+    ext_len = (size_t) ssl->own_cid_len + 1;
+    MBEDTLS_PUT_UINT16_BE(ext_len, p, 0);
+    p += 2;
+
+    *p++ = (uint8_t) ssl->own_cid_len;
+    memcpy(p, ssl->own_cid, ssl->own_cid_len);
+
+    *olen = ssl->own_cid_len + 5;
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_max_fragment_length_ext(mbedtls_ssl_context *ssl,
+                                             unsigned char *buf,
+                                             const unsigned char *end,
+                                             size_t *olen)
+{
+    unsigned char *p = buf;
+
+    *olen = 0;
+
+    if (ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE) {
+        return 0;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3,
+                          ("client hello, adding max_fragment_length extension"));
+
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 5);
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, p, 0);
+    p += 2;
+
+    *p++ = 0x00;
+    *p++ = 1;
+
+    *p++ = ssl->conf->mfl_code;
+
+    *olen = 5;
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_encrypt_then_mac_ext(mbedtls_ssl_context *ssl,
+                                          unsigned char *buf,
+                                          const unsigned char *end,
+                                          size_t *olen)
+{
+    unsigned char *p = buf;
+
+    *olen = 0;
+
+    if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED) {
+        return 0;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3,
+                          ("client hello, adding encrypt_then_mac extension"));
+
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4);
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, p, 0);
+    p += 2;
+
+    *p++ = 0x00;
+    *p++ = 0x00;
+
+    *olen = 4;
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
+
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_extended_ms_ext(mbedtls_ssl_context *ssl,
+                                     unsigned char *buf,
+                                     const unsigned char *end,
+                                     size_t *olen)
+{
+    unsigned char *p = buf;
+
+    *olen = 0;
+
+    if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED) {
+        return 0;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3,
+                          ("client hello, adding extended_master_secret extension"));
+
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4);
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, p, 0);
+    p += 2;
+
+    *p++ = 0x00;
+    *p++ = 0x00;
+
+    *olen = 4;
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_session_ticket_ext(mbedtls_ssl_context *ssl,
+                                        unsigned char *buf,
+                                        const unsigned char *end,
+                                        size_t *olen)
+{
+    unsigned char *p = buf;
+    size_t tlen = ssl->session_negotiate->ticket_len;
+
+    *olen = 0;
+
+    if (ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED) {
+        return 0;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3,
+                          ("client hello, adding session ticket extension"));
+
+    /* The addition is safe here since the ticket length is 16 bit. */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4 + tlen);
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SESSION_TICKET, p, 0);
+    p += 2;
+
+    MBEDTLS_PUT_UINT16_BE(tlen, p, 0);
+    p += 2;
+
+    *olen = 4;
+
+    if (ssl->session_negotiate->ticket == NULL || tlen == 0) {
+        return 0;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3,
+                          ("sending session ticket of length %" MBEDTLS_PRINTF_SIZET, tlen));
+
+    memcpy(p, ssl->session_negotiate->ticket, tlen);
+
+    *olen += tlen;
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_use_srtp_ext(mbedtls_ssl_context *ssl,
+                                  unsigned char *buf,
+                                  const unsigned char *end,
+                                  size_t *olen)
+{
+    unsigned char *p = buf;
+    size_t protection_profiles_index = 0, ext_len = 0;
+    uint16_t mki_len = 0, profile_value = 0;
+
+    *olen = 0;
+
+    if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) ||
+        (ssl->conf->dtls_srtp_profile_list == NULL) ||
+        (ssl->conf->dtls_srtp_profile_list_len == 0)) {
+        return 0;
+    }
+
+    /* RFC 5764 section 4.1.1
+     * uint8 SRTPProtectionProfile[2];
+     *
+     * struct {
+     *   SRTPProtectionProfiles SRTPProtectionProfiles;
+     *   opaque srtp_mki<0..255>;
+     * } UseSRTPData;
+     * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>;
+     */
+    if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED) {
+        mki_len = ssl->dtls_srtp_info.mki_len;
+    }
+    /* Extension length = 2 bytes for profiles length,
+     *                    ssl->conf->dtls_srtp_profile_list_len * 2 (each profile is 2 bytes length ),
+     *                    1 byte for srtp_mki vector length and the mki_len value
+     */
+    ext_len = 2 + 2 * (ssl->conf->dtls_srtp_profile_list_len) + 1 + mki_len;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding use_srtp extension"));
+
+    /* Check there is room in the buffer for the extension + 4 bytes
+     * - the extension tag (2 bytes)
+     * - the extension length (2 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, ext_len + 4);
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_USE_SRTP, p, 0);
+    p += 2;
+
+    MBEDTLS_PUT_UINT16_BE(ext_len, p, 0);
+    p += 2;
+
+    /* protection profile length: 2*(ssl->conf->dtls_srtp_profile_list_len) */
+    /* micro-optimization:
+     * the list size is limited to MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH
+     * which is lower than 127, so the upper byte of the length is always 0
+     * For the documentation, the more generic code is left in comments
+     * *p++ = (unsigned char)( ( ( 2 * ssl->conf->dtls_srtp_profile_list_len )
+     *                        >> 8 ) & 0xFF );
+     */
+    *p++ = 0;
+    *p++ = MBEDTLS_BYTE_0(2 * ssl->conf->dtls_srtp_profile_list_len);
+
+    for (protection_profiles_index = 0;
+         protection_profiles_index < ssl->conf->dtls_srtp_profile_list_len;
+         protection_profiles_index++) {
+        profile_value = mbedtls_ssl_check_srtp_profile_value
+                            (ssl->conf->dtls_srtp_profile_list[protection_profiles_index]);
+        if (profile_value != MBEDTLS_TLS_SRTP_UNSET) {
+            MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_write_use_srtp_ext, add profile: %04x",
+                                      profile_value));
+            MBEDTLS_PUT_UINT16_BE(profile_value, p, 0);
+            p += 2;
+        } else {
+            /*
+             * Note: we shall never arrive here as protection profiles
+             * is checked by mbedtls_ssl_conf_dtls_srtp_protection_profiles function
+             */
+            MBEDTLS_SSL_DEBUG_MSG(3,
+                                  ("client hello, "
+                                   "illegal DTLS-SRTP protection profile %d",
+                                   ssl->conf->dtls_srtp_profile_list[protection_profiles_index]
+                                  ));
+            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        }
+    }
+
+    *p++ = mki_len & 0xFF;
+
+    if (mki_len != 0) {
+        memcpy(p, ssl->dtls_srtp_info.mki_value, mki_len);
+        /*
+         * Increment p to point to the current position.
+         */
+        p += mki_len;
+        MBEDTLS_SSL_DEBUG_BUF(3, "sending mki",  ssl->dtls_srtp_info.mki_value,
+                              ssl->dtls_srtp_info.mki_len);
+    }
+
+    /*
+     * total extension length: extension type (2 bytes)
+     *                         + extension length (2 bytes)
+     *                         + protection profile length (2 bytes)
+     *                         + 2 * number of protection profiles
+     *                         + srtp_mki vector length(1 byte)
+     *                         + mki value
+     */
+    *olen = p - buf;
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
+int mbedtls_ssl_tls12_write_client_hello_exts(mbedtls_ssl_context *ssl,
+                                              unsigned char *buf,
+                                              const unsigned char *end,
+                                              int uses_ec,
+                                              size_t *out_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *p = buf;
+    size_t ext_len = 0;
+
+    (void) ssl;
+    (void) end;
+    (void) uses_ec;
+    (void) ret;
+    (void) ext_len;
+
+    *out_len = 0;
+
+    /* Note that TLS_EMPTY_RENEGOTIATION_INFO_SCSV is always added
+     * even if MBEDTLS_SSL_RENEGOTIATION is not defined. */
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    if ((ret = ssl_write_renegotiation_ext(ssl, p, end, &ext_len)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_renegotiation_ext", ret);
+        return ret;
+    }
+    p += ext_len;
+#endif
+
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+    if (uses_ec) {
+        if ((ret = ssl_write_supported_point_formats_ext(ssl, p, end,
+                                                         &ext_len)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_supported_point_formats_ext", ret);
+            return ret;
+        }
+        p += ext_len;
+    }
+#endif
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+    if ((ret = ssl_write_ecjpake_kkpp_ext(ssl, p, end, &ext_len)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_ecjpake_kkpp_ext", ret);
+        return ret;
+    }
+    p += ext_len;
+#endif
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    if ((ret = ssl_write_cid_ext(ssl, p, end, &ext_len)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_cid_ext", ret);
+        return ret;
+    }
+    p += ext_len;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+    if ((ret = ssl_write_max_fragment_length_ext(ssl, p, end,
+                                                 &ext_len)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_max_fragment_length_ext", ret);
+        return ret;
+    }
+    p += ext_len;
+#endif
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+    if ((ret = ssl_write_encrypt_then_mac_ext(ssl, p, end, &ext_len)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_encrypt_then_mac_ext", ret);
+        return ret;
+    }
+    p += ext_len;
+#endif
+
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+    if ((ret = ssl_write_extended_ms_ext(ssl, p, end, &ext_len)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_extended_ms_ext", ret);
+        return ret;
+    }
+    p += ext_len;
+#endif
+
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+    if ((ret = ssl_write_use_srtp_ext(ssl, p, end, &ext_len)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_use_srtp_ext", ret);
+        return ret;
+    }
+    p += ext_len;
+#endif
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    if ((ret = ssl_write_session_ticket_ext(ssl, p, end, &ext_len)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_session_ticket_ext", ret);
+        return ret;
+    }
+    p += ext_len;
+#endif
+
+    *out_len = p - buf;
+
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_renegotiation_info(mbedtls_ssl_context *ssl,
+                                        const unsigned char *buf,
+                                        size_t len)
+{
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {
+        /* Check verify-data in constant-time. The length OTOH is no secret */
+        if (len    != 1 + ssl->verify_data_len * 2 ||
+            buf[0] !=     ssl->verify_data_len * 2 ||
+            mbedtls_ct_memcmp(buf + 1,
+                              ssl->own_verify_data, ssl->verify_data_len) != 0 ||
+            mbedtls_ct_memcmp(buf + 1 + ssl->verify_data_len,
+                              ssl->peer_verify_data, ssl->verify_data_len) != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching renegotiation info"));
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+        }
+    } else
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+    {
+        if (len != 1 || buf[0] != 0x00) {
+            MBEDTLS_SSL_DEBUG_MSG(1,
+                                  ("non-zero length renegotiation info"));
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+        }
+
+        ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION;
+    }
+
+    return 0;
+}
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_max_fragment_length_ext(mbedtls_ssl_context *ssl,
+                                             const unsigned char *buf,
+                                             size_t len)
+{
+    /*
+     * server should use the extension only if we did,
+     * and if so the server's value should match ours (and len is always 1)
+     */
+    if (ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ||
+        len != 1 ||
+        buf[0] != ssl->conf->mfl_code) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("non-matching max fragment length extension"));
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_cid_ext(mbedtls_ssl_context *ssl,
+                             const unsigned char *buf,
+                             size_t len)
+{
+    size_t peer_cid_len;
+
+    if ( /* CID extension only makes sense in DTLS */
+        ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
+        /* The server must only send the CID extension if we have offered it. */
+        ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("CID extension unexpected"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT);
+        return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION;
+    }
+
+    if (len == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("CID extension invalid"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    peer_cid_len = *buf++;
+    len--;
+
+    if (peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("CID extension invalid"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    if (len != peer_cid_len) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("CID extension invalid"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED;
+    ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len;
+    memcpy(ssl->handshake->peer_cid, buf, peer_cid_len);
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("Use of CID extension negotiated"));
+    MBEDTLS_SSL_DEBUG_BUF(3, "Server CID", buf, peer_cid_len);
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_encrypt_then_mac_ext(mbedtls_ssl_context *ssl,
+                                          const unsigned char *buf,
+                                          size_t len)
+{
+    if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED ||
+        len != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("non-matching encrypt-then-MAC extension"));
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT);
+        return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION;
+    }
+
+    ((void) buf);
+
+    ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED;
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
+
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_extended_ms_ext(mbedtls_ssl_context *ssl,
+                                     const unsigned char *buf,
+                                     size_t len)
+{
+    if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED ||
+        len != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("non-matching extended master secret extension"));
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT);
+        return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION;
+    }
+
+    ((void) buf);
+
+    ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED;
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_session_ticket_ext(mbedtls_ssl_context *ssl,
+                                        const unsigned char *buf,
+                                        size_t len)
+{
+    if (ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ||
+        len != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("non-matching session ticket extension"));
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT);
+        return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION;
+    }
+
+    ((void) buf);
+
+    ssl->handshake->new_session_ticket = 1;
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_supported_point_formats_ext(mbedtls_ssl_context *ssl,
+                                                 const unsigned char *buf,
+                                                 size_t len)
+{
+    size_t list_size;
+    const unsigned char *p;
+
+    if (len == 0 || (size_t) (buf[0] + 1) != len) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+    list_size = buf[0];
+
+    p = buf + 1;
+    while (list_size > 0) {
+        if (p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED ||
+            p[0] == MBEDTLS_ECP_PF_COMPRESSED) {
+#if !defined(MBEDTLS_USE_PSA_CRYPTO) &&                             \
+            (defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C))
+            ssl->handshake->ecdh_ctx.point_format = p[0];
+#endif /* !MBEDTLS_USE_PSA_CRYPTO &&
+          ( MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ) */
+#if !defined(MBEDTLS_USE_PSA_CRYPTO) &&                             \
+            defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+            mbedtls_ecjpake_set_point_format(&ssl->handshake->ecjpake_ctx,
+                                             p[0]);
+#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+            MBEDTLS_SSL_DEBUG_MSG(4, ("point format selected: %d", p[0]));
+            return 0;
+        }
+
+        list_size--;
+        p++;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(1, ("no point format in common"));
+    mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                   MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+    return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+}
+#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
+          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_ecjpake_kkpp(mbedtls_ssl_context *ssl,
+                                  const unsigned char *buf,
+                                  size_t len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if (ssl->handshake->ciphersuite_info->key_exchange !=
+        MBEDTLS_KEY_EXCHANGE_ECJPAKE) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("skip ecjpake kkpp extension"));
+        return 0;
+    }
+
+    /* If we got here, we no longer need our cached extension */
+    mbedtls_free(ssl->handshake->ecjpake_cache);
+    ssl->handshake->ecjpake_cache = NULL;
+    ssl->handshake->ecjpake_cache_len = 0;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if ((ret = mbedtls_psa_ecjpake_read_round(
+             &ssl->handshake->psa_pake_ctx, buf, len,
+             MBEDTLS_ECJPAKE_ROUND_ONE)) != 0) {
+        psa_destroy_key(ssl->handshake->psa_pake_password);
+        psa_pake_abort(&ssl->handshake->psa_pake_ctx);
+
+        MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round one", ret);
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+        return ret;
+    }
+
+    return 0;
+#else
+    if ((ret = mbedtls_ecjpake_read_round_one(&ssl->handshake->ecjpake_ctx,
+                                              buf, len)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_read_round_one", ret);
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+        return ret;
+    }
+
+    return 0;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+
+#if defined(MBEDTLS_SSL_ALPN)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_alpn_ext(mbedtls_ssl_context *ssl,
+                              const unsigned char *buf, size_t len)
+{
+    size_t list_len, name_len;
+    const char **p;
+
+    /* If we didn't send it, the server shouldn't send it */
+    if (ssl->conf->alpn_list == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching ALPN extension"));
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT);
+        return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION;
+    }
+
+    /*
+     * opaque ProtocolName<1..2^8-1>;
+     *
+     * struct {
+     *     ProtocolName protocol_name_list<2..2^16-1>
+     * } ProtocolNameList;
+     *
+     * the "ProtocolNameList" MUST contain exactly one "ProtocolName"
+     */
+
+    /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */
+    if (len < 4) {
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    list_len = (buf[0] << 8) | buf[1];
+    if (list_len != len - 2) {
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    name_len = buf[2];
+    if (name_len != list_len - 1) {
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /* Check that the server chosen protocol was in our list and save it */
+    for (p = ssl->conf->alpn_list; *p != NULL; p++) {
+        if (name_len == strlen(*p) &&
+            memcmp(buf + 3, *p, name_len) == 0) {
+            ssl->alpn_chosen = *p;
+            return 0;
+        }
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(1, ("ALPN extension: no matching protocol"));
+    mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                   MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+    return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+}
+#endif /* MBEDTLS_SSL_ALPN */
+
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl,
+                                  const unsigned char *buf,
+                                  size_t len)
+{
+    mbedtls_ssl_srtp_profile server_protection = MBEDTLS_TLS_SRTP_UNSET;
+    size_t i, mki_len = 0;
+    uint16_t server_protection_profile_value = 0;
+
+    /* If use_srtp is not configured, just ignore the extension */
+    if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) ||
+        (ssl->conf->dtls_srtp_profile_list == NULL) ||
+        (ssl->conf->dtls_srtp_profile_list_len == 0)) {
+        return 0;
+    }
+
+    /* RFC 5764 section 4.1.1
+     * uint8 SRTPProtectionProfile[2];
+     *
+     * struct {
+     *   SRTPProtectionProfiles SRTPProtectionProfiles;
+     *   opaque srtp_mki<0..255>;
+     * } UseSRTPData;
+
+     * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>;
+     *
+     */
+    if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED) {
+        mki_len = ssl->dtls_srtp_info.mki_len;
+    }
+
+    /*
+     * Length is 5 + optional mki_value : one protection profile length (2 bytes)
+     *                                      + protection profile (2 bytes)
+     *                                      + mki_len(1 byte)
+     *                                      and optional srtp_mki
+     */
+    if ((len < 5) || (len != (buf[4] + 5u))) {
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /*
+     * get the server protection profile
+     */
+
+    /*
+     * protection profile length must be 0x0002 as we must have only
+     * one protection profile in server Hello
+     */
+    if ((buf[0] != 0) || (buf[1] != 2)) {
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    server_protection_profile_value = (buf[2] << 8) | buf[3];
+    server_protection = mbedtls_ssl_check_srtp_profile_value(
+        server_protection_profile_value);
+    if (server_protection != MBEDTLS_TLS_SRTP_UNSET) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("found srtp profile: %s",
+                                  mbedtls_ssl_get_srtp_profile_as_string(
+                                      server_protection)));
+    }
+
+    ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET;
+
+    /*
+     * Check we have the server profile in our list
+     */
+    for (i = 0; i < ssl->conf->dtls_srtp_profile_list_len; i++) {
+        if (server_protection == ssl->conf->dtls_srtp_profile_list[i]) {
+            ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i];
+            MBEDTLS_SSL_DEBUG_MSG(3, ("selected srtp profile: %s",
+                                      mbedtls_ssl_get_srtp_profile_as_string(
+                                          server_protection)));
+            break;
+        }
+    }
+
+    /* If no match was found : server problem, it shall never answer with incompatible profile */
+    if (ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET) {
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+    /* If server does not use mki in its reply, make sure the client won't keep
+     * one as negotiated */
+    if (len == 5) {
+        ssl->dtls_srtp_info.mki_len = 0;
+    }
+
+    /*
+     * RFC5764:
+     *  If the client detects a nonzero-length MKI in the server's response
+     *  that is different than the one the client offered, then the client
+     *  MUST abort the handshake and SHOULD send an invalid_parameter alert.
+     */
+    if (len > 5  && (buf[4] != mki_len ||
+                     (memcmp(ssl->dtls_srtp_info.mki_value, &buf[5], mki_len)))) {
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+#if defined(MBEDTLS_DEBUG_C)
+    if (len > 5) {
+        MBEDTLS_SSL_DEBUG_BUF(3, "received mki", ssl->dtls_srtp_info.mki_value,
+                              ssl->dtls_srtp_info.mki_len);
+    }
+#endif
+    return 0;
+}
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
+/*
+ * Parse HelloVerifyRequest.  Only called after verifying the HS type.
+ */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_hello_verify_request(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl);
+    uint16_t dtls_legacy_version;
+
+#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"));
+
+    /* Check that there is enough room for:
+     * - 2 bytes of version
+     * - 1 byte of cookie_len
+     */
+    if (mbedtls_ssl_hs_hdr_len(ssl) + 3 > ssl->in_msglen) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("incoming HelloVerifyRequest message is too short"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /*
+     * struct {
+     *   ProtocolVersion server_version;
+     *   opaque cookie<0..2^8-1>;
+     * } HelloVerifyRequest;
+     */
+    MBEDTLS_SSL_DEBUG_BUF(3, "server version", p, 2);
+    dtls_legacy_version = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+
+    /*
+     * Since the RFC is not clear on this point, accept DTLS 1.0 (0xfeff)
+     * The DTLS 1.3 (current draft) renames ProtocolVersion server_version to
+     * legacy_version and locks the value of legacy_version to 0xfefd (DTLS 1.2)
+     */
+    if (dtls_legacy_version != 0xfefd && dtls_legacy_version != 0xfeff) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad server version"));
+
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION);
+
+        return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;
+    }
+
+    cookie_len = *p++;
+    if ((ssl->in_msg + ssl->in_msglen) - p < cookie_len) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("cookie length does not match incoming message size"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+    MBEDTLS_SSL_DEBUG_BUF(3, "cookie", p, cookie_len);
+
+    mbedtls_free(ssl->handshake->cookie);
+
+    ssl->handshake->cookie = mbedtls_calloc(1, cookie_len);
+    if (ssl->handshake->cookie  == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("alloc failed (%d bytes)", cookie_len));
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+    }
+
+    memcpy(ssl->handshake->cookie, p, cookie_len);
+    ssl->handshake->cookie_len = cookie_len;
+
+    /* Start over at ClientHello */
+    ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
+    ret = mbedtls_ssl_reset_checksum(ssl);
+    if (0 != ret) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_reset_checksum"), ret);
+        return ret;
+    }
+
+    mbedtls_ssl_recv_flight_completed(ssl);
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse hello verify request"));
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_server_hello(mbedtls_ssl_context *ssl)
+{
+    int ret, i;
+    size_t n;
+    size_t ext_len;
+    unsigned char *buf, *ext;
+    unsigned char comp;
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    int renegotiation_info_seen = 0;
+#endif
+    int handshake_failure = 0;
+    const mbedtls_ssl_ciphersuite_t *suite_info;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse server hello"));
+
+    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {
+        /* No alert on a read error. */
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
+        return ret;
+    }
+
+    buf = ssl->in_msg;
+
+    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+        if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {
+            ssl->renego_records_seen++;
+
+            if (ssl->conf->renego_max_records >= 0 &&
+                ssl->renego_records_seen > ssl->conf->renego_max_records) {
+                MBEDTLS_SSL_DEBUG_MSG(1,
+                                      ("renegotiation requested, but not honored by server"));
+                return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+            }
+
+            MBEDTLS_SSL_DEBUG_MSG(1,
+                                  ("non-handshake message during renegotiation"));
+
+            ssl->keep_current_message = 1;
+            return MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO;
+        }
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message"));
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        if (buf[0] == MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("received hello verify request"));
+            MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse server hello"));
+            return ssl_parse_hello_verify_request(ssl);
+        } else {
+            /* We made it through the verification process */
+            mbedtls_free(ssl->handshake->cookie);
+            ssl->handshake->cookie = NULL;
+            ssl->handshake->cookie_len = 0;
+        }
+    }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+    if (ssl->in_hslen < 38 + mbedtls_ssl_hs_hdr_len(ssl) ||
+        buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /*
+     *  0   .  1    server_version
+     *  2   . 33    random (maybe including 4 bytes of Unix time)
+     * 34   . 34    session_id length = n
+     * 35   . 34+n  session_id
+     * 35+n . 36+n  cipher_suite
+     * 37+n . 37+n  compression_method
+     *
+     * 38+n . 39+n  extensions length (optional)
+     * 40+n .  ..   extensions
+     */
+    buf += mbedtls_ssl_hs_hdr_len(ssl);
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "server hello, version", buf, 2);
+    ssl->tls_version = mbedtls_ssl_read_version(buf, ssl->conf->transport);
+    ssl->session_negotiate->tls_version = ssl->tls_version;
+
+    if (ssl->tls_version < ssl->conf->min_tls_version ||
+        ssl->tls_version > ssl->conf->max_tls_version) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              (
+                                  "server version out of bounds -  min: [0x%x], server: [0x%x], max: [0x%x]",
+                                  (unsigned) ssl->conf->min_tls_version,
+                                  (unsigned) ssl->tls_version,
+                                  (unsigned) ssl->conf->max_tls_version));
+
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION);
+
+        return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, current time: %lu",
+                              ((unsigned long) buf[2] << 24) |
+                              ((unsigned long) buf[3] << 16) |
+                              ((unsigned long) buf[4] <<  8) |
+                              ((unsigned long) buf[5])));
+
+    memcpy(ssl->handshake->randbytes + 32, buf + 2, 32);
+
+    n = buf[34];
+
+    MBEDTLS_SSL_DEBUG_BUF(3,   "server hello, random bytes", buf + 2, 32);
+
+    if (n > 32) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    if (ssl->in_hslen > mbedtls_ssl_hs_hdr_len(ssl) + 39 + n) {
+        ext_len = ((buf[38 + n] <<  8)
+                   | (buf[39 + n]));
+
+        if ((ext_len > 0 && ext_len < 4) ||
+            ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) + 40 + n + ext_len) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message"));
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+    } else if (ssl->in_hslen == mbedtls_ssl_hs_hdr_len(ssl) + 38 + n) {
+        ext_len = 0;
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /* ciphersuite (used later) */
+    i = (buf[35 + n] << 8) | buf[36 + n];
+
+    /*
+     * Read and check compression
+     */
+    comp = buf[37 + n];
+
+    if (comp != MBEDTLS_SSL_COMPRESS_NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("server hello, bad compression: %d", comp));
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    }
+
+    /*
+     * Initialize update checksum functions
+     */
+    ssl->handshake->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(i);
+    if (ssl->handshake->ciphersuite_info == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("ciphersuite info for %04x not found", (unsigned int) i));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    mbedtls_ssl_optimize_checksum(ssl, ssl->handshake->ciphersuite_info);
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n));
+    MBEDTLS_SSL_DEBUG_BUF(3,   "server hello, session id", buf + 35, n);
+
+    /*
+     * Check if the session can be resumed
+     */
+    if (ssl->handshake->resume == 0 || n == 0 ||
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+        ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ||
+#endif
+        ssl->session_negotiate->ciphersuite != i ||
+        ssl->session_negotiate->id_len != n ||
+        memcmp(ssl->session_negotiate->id, buf + 35, n) != 0) {
+        ssl->state++;
+        ssl->handshake->resume = 0;
+#if defined(MBEDTLS_HAVE_TIME)
+        ssl->session_negotiate->start = mbedtls_time(NULL);
+#endif
+        ssl->session_negotiate->ciphersuite = i;
+        ssl->session_negotiate->id_len = n;
+        memcpy(ssl->session_negotiate->id, buf + 35, n);
+    } else {
+        ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("%s session has been resumed",
+                              ssl->handshake->resume ? "a" : "no"));
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen ciphersuite: %04x", (unsigned) i));
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, compress alg.: %d",
+                              buf[37 + n]));
+
+    /*
+     * Perform cipher suite validation in same way as in ssl_write_client_hello.
+     */
+    i = 0;
+    while (1) {
+        if (ssl->conf->ciphersuite_list[i] == 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message"));
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);
+            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+        }
+
+        if (ssl->conf->ciphersuite_list[i++] ==
+            ssl->session_negotiate->ciphersuite) {
+            break;
+        }
+    }
+
+    suite_info = mbedtls_ssl_ciphersuite_from_id(
+        ssl->session_negotiate->ciphersuite);
+    if (mbedtls_ssl_validate_ciphersuite(ssl, suite_info, ssl->tls_version,
+                                         ssl->tls_version) != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message"));
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3,
+                          ("server hello, chosen ciphersuite: %s", suite_info->name));
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA &&
+        ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {
+        ssl->handshake->ecrs_enabled = 1;
+    }
+#endif
+
+    if (comp != MBEDTLS_SSL_COMPRESS_NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message"));
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    ext = buf + 40 + n;
+
+    MBEDTLS_SSL_DEBUG_MSG(2,
+                          ("server hello, total extension length: %" MBEDTLS_PRINTF_SIZET,
+                           ext_len));
+
+    while (ext_len) {
+        unsigned int ext_id   = ((ext[0] <<  8)
+                                 | (ext[1]));
+        unsigned int ext_size = ((ext[2] <<  8)
+                                 | (ext[3]));
+
+        if (ext_size + 4 > ext_len) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message"));
+            mbedtls_ssl_send_alert_message(
+                ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+
+        switch (ext_id) {
+            case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found renegotiation extension"));
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+                renegotiation_info_seen = 1;
+#endif
+
+                if ((ret = ssl_parse_renegotiation_info(ssl, ext + 4,
+                                                        ext_size)) != 0) {
+                    return ret;
+                }
+
+                break;
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+            case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH:
+                MBEDTLS_SSL_DEBUG_MSG(3,
+                                      ("found max_fragment_length extension"));
+
+                if ((ret = ssl_parse_max_fragment_length_ext(ssl,
+                                                             ext + 4, ext_size)) != 0) {
+                    return ret;
+                }
+
+                break;
+#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+            case MBEDTLS_TLS_EXT_CID:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found CID extension"));
+
+                if ((ret = ssl_parse_cid_ext(ssl,
+                                             ext + 4,
+                                             ext_size)) != 0) {
+                    return ret;
+                }
+
+                break;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+            case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found encrypt_then_mac extension"));
+
+                if ((ret = ssl_parse_encrypt_then_mac_ext(ssl,
+                                                          ext + 4, ext_size)) != 0) {
+                    return ret;
+                }
+
+                break;
+#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
+
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+            case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET:
+                MBEDTLS_SSL_DEBUG_MSG(3,
+                                      ("found extended_master_secret extension"));
+
+                if ((ret = ssl_parse_extended_ms_ext(ssl,
+                                                     ext + 4, ext_size)) != 0) {
+                    return ret;
+                }
+
+                break;
+#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+            case MBEDTLS_TLS_EXT_SESSION_TICKET:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found session_ticket extension"));
+
+                if ((ret = ssl_parse_session_ticket_ext(ssl,
+                                                        ext + 4, ext_size)) != 0) {
+                    return ret;
+                }
+
+                break;
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+                defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+            case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS:
+                MBEDTLS_SSL_DEBUG_MSG(3,
+                                      ("found supported_point_formats extension"));
+
+                if ((ret = ssl_parse_supported_point_formats_ext(ssl,
+                                                                 ext + 4, ext_size)) != 0) {
+                    return ret;
+                }
+
+                break;
+#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
+          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+            case MBEDTLS_TLS_EXT_ECJPAKE_KKPP:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found ecjpake_kkpp extension"));
+
+                if ((ret = ssl_parse_ecjpake_kkpp(ssl,
+                                                  ext + 4, ext_size)) != 0) {
+                    return ret;
+                }
+
+                break;
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+
+#if defined(MBEDTLS_SSL_ALPN)
+            case MBEDTLS_TLS_EXT_ALPN:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension"));
+
+                if ((ret = ssl_parse_alpn_ext(ssl, ext + 4, ext_size)) != 0) {
+                    return ret;
+                }
+
+                break;
+#endif /* MBEDTLS_SSL_ALPN */
+
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+            case MBEDTLS_TLS_EXT_USE_SRTP:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found use_srtp extension"));
+
+                if ((ret = ssl_parse_use_srtp_ext(ssl, ext + 4, ext_size)) != 0) {
+                    return ret;
+                }
+
+                break;
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
+            default:
+                MBEDTLS_SSL_DEBUG_MSG(3,
+                                      ("unknown extension found: %u (ignoring)", ext_id));
+        }
+
+        ext_len -= 4 + ext_size;
+        ext += 4 + ext_size;
+
+        if (ext_len > 0 && ext_len < 4) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message"));
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+    }
+
+    /*
+     * mbedtls_ssl_derive_keys() has to be called after the parsing of the
+     * extensions. It sets the transform data for the resumed session which in
+     * case of DTLS includes the server CID extracted from the CID extension.
+     */
+    if (ssl->handshake->resume) {
+        if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_derive_keys", ret);
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);
+            return ret;
+        }
+    }
+
+    /*
+     * Renegotiation security checks
+     */
+    if (ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
+        ssl->conf->allow_legacy_renegotiation ==
+        MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("legacy renegotiation, breaking off handshake"));
+        handshake_failure = 1;
+    }
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
+             ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION &&
+             renegotiation_info_seen == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("renegotiation_info extension missing (secure)"));
+        handshake_failure = 1;
+    } else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
+               ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
+               ssl->conf->allow_legacy_renegotiation ==
+               MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("legacy renegotiation not allowed"));
+        handshake_failure = 1;
+    } else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
+               ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
+               renegotiation_info_seen == 1) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("renegotiation_info extension present (legacy)"));
+        handshake_failure = 1;
+    }
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+
+    if (handshake_failure == 1) {
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse server hello"));
+
+    return 0;
+}
+
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
+    defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_server_dh_params(mbedtls_ssl_context *ssl,
+                                      unsigned char **p,
+                                      unsigned char *end)
+{
+    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    size_t dhm_actual_bitlen;
+
+    /*
+     * Ephemeral DH parameters:
+     *
+     * struct {
+     *     opaque dh_p<1..2^16-1>;
+     *     opaque dh_g<1..2^16-1>;
+     *     opaque dh_Ys<1..2^16-1>;
+     * } ServerDHParams;
+     */
+    if ((ret = mbedtls_dhm_read_params(&ssl->handshake->dhm_ctx,
+                                       p, end)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(2, ("mbedtls_dhm_read_params"), ret);
+        return ret;
+    }
+
+    dhm_actual_bitlen = mbedtls_dhm_get_bitlen(&ssl->handshake->dhm_ctx);
+    if (dhm_actual_bitlen < ssl->conf->dhm_min_bitlen) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("DHM prime too short: %" MBEDTLS_PRINTF_SIZET " < %u",
+                                  dhm_actual_bitlen,
+                                  ssl->conf->dhm_min_bitlen));
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+    MBEDTLS_SSL_DEBUG_MPI(3, "DHM: P ", &ssl->handshake->dhm_ctx.P);
+    MBEDTLS_SSL_DEBUG_MPI(3, "DHM: G ", &ssl->handshake->dhm_ctx.G);
+    MBEDTLS_SSL_DEBUG_MPI(3, "DHM: GY", &ssl->handshake->dhm_ctx.GY);
+
+    return ret;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)   ||   \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)   ||   \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl,
+                                        unsigned char **p,
+                                        unsigned char *end)
+{
+    uint16_t tls_id;
+    uint8_t ecpoint_len;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    psa_ecc_family_t ec_psa_family = 0;
+    size_t ec_bits = 0;
+
+    /*
+     * struct {
+     *     ECParameters curve_params;
+     *     ECPoint      public;
+     * } ServerECDHParams;
+     *
+     *  1       curve_type (must be "named_curve")
+     *  2..3    NamedCurve
+     *  4       ECPoint.len
+     *  5+      ECPoint contents
+     */
+    if (end - *p < 4) {
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /* First byte is curve_type; only named_curve is handled */
+    if (*(*p)++ != MBEDTLS_ECP_TLS_NAMED_CURVE) {
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+    /* Next two bytes are the namedcurve value */
+    tls_id = *(*p)++;
+    tls_id <<= 8;
+    tls_id |= *(*p)++;
+
+    /* Check it's a curve we offered */
+    if (mbedtls_ssl_check_curve_tls_id(ssl, tls_id) != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(2,
+                              ("bad server key exchange message (ECDHE curve): %u",
+                               (unsigned) tls_id));
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+    /* Convert EC's TLS ID to PSA key type. */
+    if (mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &ec_psa_family,
+                                                   &ec_bits) == PSA_ERROR_NOT_SUPPORTED) {
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+    handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR(ec_psa_family);
+    handshake->ecdh_bits = ec_bits;
+
+    /* Keep a copy of the peer's public key */
+    ecpoint_len = *(*p)++;
+    if ((size_t) (end - *p) < ecpoint_len) {
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    if (ecpoint_len > sizeof(handshake->ecdh_psa_peerkey)) {
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+    memcpy(handshake->ecdh_psa_peerkey, *p, ecpoint_len);
+    handshake->ecdh_psa_peerkey_len = ecpoint_len;
+    *p += ecpoint_len;
+
+    return 0;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED   ||
+          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED   ||
+          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+#else
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)   ||   \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)    ||   \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)   ||   \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||   \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_check_server_ecdh_params(const mbedtls_ssl_context *ssl)
+{
+    uint16_t tls_id;
+    mbedtls_ecp_group_id grp_id;
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+    grp_id = ssl->handshake->ecdh_ctx.grp.id;
+#else
+    grp_id = ssl->handshake->ecdh_ctx.grp_id;
+#endif
+
+    tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id);
+    if (tls_id == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("ECDH curve: %s",
+                              mbedtls_ssl_get_curve_name_from_tls_id(tls_id)));
+
+    if (mbedtls_ssl_check_curve(ssl, grp_id) != 0) {
+        return -1;
+    }
+
+    MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,
+                           MBEDTLS_DEBUG_ECDH_QP);
+
+    return 0;
+}
+
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED   ||
+          MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED    ||
+          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED   ||
+          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||     \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ||     \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl,
+                                        unsigned char **p,
+                                        unsigned char *end)
+{
+    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+
+    /*
+     * Ephemeral ECDH parameters:
+     *
+     * struct {
+     *     ECParameters curve_params;
+     *     ECPoint      public;
+     * } ServerECDHParams;
+     */
+    if ((ret = mbedtls_ecdh_read_params(&ssl->handshake->ecdh_ctx,
+                                        (const unsigned char **) p, end)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecdh_read_params"), ret);
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+        if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
+            ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+        }
+#endif
+        return ret;
+    }
+
+    if (ssl_check_server_ecdh_params(ssl) != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("bad server key exchange message (ECDHE curve)"));
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+    return ret;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || \
+          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || \
+          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_server_psk_hint(mbedtls_ssl_context *ssl,
+                                     unsigned char **p,
+                                     unsigned char *end)
+{
+    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    uint16_t  len;
+    ((void) ssl);
+
+    /*
+     * PSK parameters:
+     *
+     * opaque psk_identity_hint<0..2^16-1>;
+     */
+    if (end - (*p) < 2) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("bad server key exchange message (psk_identity_hint length)"));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+    len = (*p)[0] << 8 | (*p)[1];
+    *p += 2;
+
+    if (end - (*p) < len) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("bad server key exchange message (psk_identity_hint length)"));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /*
+     * Note: we currently ignore the PSK identity hint, as we only allow one
+     * PSK to be provisioned on the client. This could be changed later if
+     * someone needs that feature.
+     */
+    *p += len;
+    ret = 0;
+
+    return ret;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) ||                           \
+    defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
+/*
+ * Generate a pre-master secret and encrypt it with the server's RSA key
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_encrypted_pms(mbedtls_ssl_context *ssl,
+                                   size_t offset, size_t *olen,
+                                   size_t pms_offset)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t len_bytes = 2;
+    unsigned char *p = ssl->handshake->premaster + pms_offset;
+    mbedtls_pk_context *peer_pk;
+
+    if (offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small for encrypted pms"));
+        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+    }
+
+    /*
+     * Generate (part of) the pre-master as
+     *  struct {
+     *      ProtocolVersion client_version;
+     *      opaque random[46];
+     *  } PreMasterSecret;
+     */
+    mbedtls_ssl_write_version(p, ssl->conf->transport,
+                              MBEDTLS_SSL_VERSION_TLS1_2);
+
+    if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p + 2, 46)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "f_rng", ret);
+        return ret;
+    }
+
+    ssl->handshake->pmslen = 48;
+
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    peer_pk = &ssl->handshake->peer_pubkey;
+#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+    if (ssl->session_negotiate->peer_cert == NULL) {
+        /* Should never happen */
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+    peer_pk = &ssl->session_negotiate->peer_cert->pk;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
+    /*
+     * Now write it out, encrypted
+     */
+    if (!mbedtls_pk_can_do(peer_pk, MBEDTLS_PK_RSA)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("certificate key type mismatch"));
+        return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;
+    }
+
+    if ((ret = mbedtls_pk_encrypt(peer_pk,
+                                  p, ssl->handshake->pmslen,
+                                  ssl->out_msg + offset + len_bytes, olen,
+                                  MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes,
+                                  ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_rsa_pkcs1_encrypt", ret);
+        return ret;
+    }
+
+    if (len_bytes == 2) {
+        MBEDTLS_PUT_UINT16_BE(*olen, ssl->out_msg, offset);
+        *olen += 2;
+    }
+
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    /* We don't need the peer's public key anymore. Free it. */
+    mbedtls_pk_free(peer_pk);
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+    return 0;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const mbedtls_ecp_keypair *peer_key;
+    mbedtls_pk_context *peer_pk;
+
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    peer_pk = &ssl->handshake->peer_pubkey;
+#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+    if (ssl->session_negotiate->peer_cert == NULL) {
+        /* Should never happen */
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+    peer_pk = &ssl->session_negotiate->peer_cert->pk;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
+    /* This is a public key, so it can't be opaque, so can_do() is a good
+     * enough check to ensure pk_ec() is safe to use below. */
+    if (!mbedtls_pk_can_do(peer_pk, MBEDTLS_PK_ECKEY)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("server key not ECDH capable"));
+        return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;
+    }
+
+    peer_key = mbedtls_pk_ec(*peer_pk);
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    size_t olen = 0;
+    uint16_t tls_id = 0;
+    psa_ecc_family_t ecc_family;
+
+    if (mbedtls_ssl_check_curve(ssl, peer_key->grp.id) != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad server certificate (ECDH curve)"));
+        return MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
+    }
+
+    tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(peer_key->grp.id);
+    if (tls_id == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("ECC group %u not suported",
+                                  peer_key->grp.id));
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    /* If the above conversion to TLS ID was fine, then also this one will be,
+       so there is no need to check the return value here */
+    mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &ecc_family,
+                                               &ssl->handshake->ecdh_bits);
+
+    ssl->handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR(ecc_family);
+
+    /* Store peer's public key in psa format. */
+    ret = mbedtls_ecp_point_write_binary(&peer_key->grp, &peer_key->Q,
+                                         MBEDTLS_ECP_PF_UNCOMPRESSED, &olen,
+                                         ssl->handshake->ecdh_psa_peerkey,
+                                         MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH);
+
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecp_point_write_binary"), ret);
+        return ret;
+    }
+
+    ssl->handshake->ecdh_psa_peerkey_len = olen;
+#else
+    if ((ret = mbedtls_ecdh_get_params(&ssl->handshake->ecdh_ctx, peer_key,
+                                       MBEDTLS_ECDH_THEIRS)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecdh_get_params"), ret);
+        return ret;
+    }
+
+    if (ssl_check_server_ecdh_params(ssl) != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad server certificate (ECDH curve)"));
+        return MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
+    }
+#endif
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    /* We don't need the peer's public key anymore. Free it,
+     * so that more RAM is available for upcoming expensive
+     * operations like ECDHE. */
+    mbedtls_pk_free(peer_pk);
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
+    return ret;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
+          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+    unsigned char *p = NULL, *end = NULL;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse server key exchange"));
+
+#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse server key exchange"));
+        ssl->state++;
+        return 0;
+    }
+    ((void) p);
+    ((void) end);
+#endif
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA) {
+        if ((ret = ssl_get_ecdh_params_from_cert(ssl)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "ssl_get_ecdh_params_from_cert", ret);
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+            return ret;
+        }
+
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse server key exchange"));
+        ssl->state++;
+        return 0;
+    }
+    ((void) p);
+    ((void) end);
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    if (ssl->handshake->ecrs_enabled &&
+        ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing) {
+        goto start_processing;
+    }
+#endif
+
+    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
+        return ret;
+    }
+
+    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message"));
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
+
+    /*
+     * ServerKeyExchange may be skipped with PSK and RSA-PSK when the server
+     * doesn't use a psk_identity_hint
+     */
+    if (ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE) {
+        if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
+            ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) {
+            /* Current message is probably either
+             * CertificateRequest or ServerHelloDone */
+            ssl->keep_current_message = 1;
+            goto exit;
+        }
+
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("server key exchange message must not be skipped"));
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
+
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    if (ssl->handshake->ecrs_enabled) {
+        ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing;
+    }
+
+start_processing:
+#endif
+    p   = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl);
+    end = ssl->in_msg + ssl->in_hslen;
+    MBEDTLS_SSL_DEBUG_BUF(3,   "server key exchange", p, end - p);
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) {
+        if (ssl_parse_server_psk_hint(ssl, &p, end) != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message"));
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+    } /* FALLTHROUGH */
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) ||                       \
+    defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) {
+        ; /* nothing more to do */
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
+    defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK) {
+        if (ssl_parse_server_dh_params(ssl, &p, end) != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message"));
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);
+            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+        }
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||     \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ||     \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA) {
+        if (ssl_parse_server_ecdh_params(ssl, &p, end) != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message"));
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);
+            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+        }
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        /*
+         * The first 3 bytes are:
+         * [0] MBEDTLS_ECP_TLS_NAMED_CURVE
+         * [1, 2] elliptic curve's TLS ID
+         *
+         * However since we only support secp256r1 for now, we check only
+         * that TLS ID here
+         */
+        uint16_t read_tls_id = MBEDTLS_GET_UINT16_BE(p, 1);
+        uint16_t exp_tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(
+            MBEDTLS_ECP_DP_SECP256R1);
+
+        if (exp_tls_id == 0) {
+            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+        }
+
+        if ((*p != MBEDTLS_ECP_TLS_NAMED_CURVE) ||
+            (read_tls_id != exp_tls_id)) {
+            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+        }
+
+        p += 3;
+
+        if ((ret = mbedtls_psa_ecjpake_read_round(
+                 &ssl->handshake->psa_pake_ctx, p, end - p,
+                 MBEDTLS_ECJPAKE_ROUND_TWO)) != 0) {
+            psa_destroy_key(ssl->handshake->psa_pake_password);
+            psa_pake_abort(&ssl->handshake->psa_pake_ctx);
+
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round two", ret);
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+        }
+#else
+        ret = mbedtls_ecjpake_read_round_two(&ssl->handshake->ecjpake_ctx,
+                                             p, end - p);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_read_round_two", ret);
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+        }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+    {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
+    if (mbedtls_ssl_ciphersuite_uses_server_signature(ciphersuite_info)) {
+        size_t sig_len, hashlen;
+        unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
+
+        mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;
+        mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
+        unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl);
+        size_t params_len = p - params;
+        void *rs_ctx = NULL;
+        uint16_t sig_alg;
+
+        mbedtls_pk_context *peer_pk;
+
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+        peer_pk = &ssl->handshake->peer_pubkey;
+#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+        if (ssl->session_negotiate->peer_cert == NULL) {
+            /* Should never happen */
+            MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        }
+        peer_pk = &ssl->session_negotiate->peer_cert->pk;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
+        /*
+         * Handle the digitally-signed structure
+         */
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+        sig_alg = MBEDTLS_GET_UINT16_BE(p, 0);
+        if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg(
+                sig_alg, &pk_alg, &md_alg) != 0 &&
+            !mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg) &&
+            !mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg)) {
+            MBEDTLS_SSL_DEBUG_MSG(1,
+                                  ("bad server key exchange message"));
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);
+            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+        }
+        p += 2;
+
+        if (!mbedtls_pk_can_do(peer_pk, pk_alg)) {
+            MBEDTLS_SSL_DEBUG_MSG(1,
+                                  ("bad server key exchange message"));
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);
+            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+        }
+
+        /*
+         * Read signature
+         */
+
+        if (p > end - 2) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message"));
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+        sig_len = (p[0] << 8) | p[1];
+        p += 2;
+
+        if (p != end - sig_len) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message"));
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+
+        MBEDTLS_SSL_DEBUG_BUF(3, "signature", p, sig_len);
+
+        /*
+         * Compute the hash that has been signed
+         */
+        if (md_alg != MBEDTLS_MD_NONE) {
+            ret = mbedtls_ssl_get_key_exchange_md_tls1_2(ssl, hash, &hashlen,
+                                                         params, params_len,
+                                                         md_alg);
+            if (ret != 0) {
+                return ret;
+            }
+        } else {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        }
+
+        MBEDTLS_SSL_DEBUG_BUF(3, "parameters hash", hash, hashlen);
+
+        /*
+         * Verify signature
+         */
+        if (!mbedtls_pk_can_do(peer_pk, pk_alg)) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message"));
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+            return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;
+        }
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+        if (ssl->handshake->ecrs_enabled) {
+            rs_ctx = &ssl->handshake->ecrs_ctx.pk;
+        }
+#endif
+
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+        if (pk_alg == MBEDTLS_PK_RSASSA_PSS) {
+            mbedtls_pk_rsassa_pss_options rsassa_pss_options;
+            rsassa_pss_options.mgf1_hash_id = md_alg;
+            rsassa_pss_options.expected_salt_len =
+                mbedtls_hash_info_get_size(md_alg);
+            if (rsassa_pss_options.expected_salt_len == 0) {
+                return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+            }
+
+            ret = mbedtls_pk_verify_ext(pk_alg, &rsassa_pss_options,
+                                        peer_pk,
+                                        md_alg, hash, hashlen,
+                                        p, sig_len);
+        } else
+#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
+        ret = mbedtls_pk_verify_restartable(peer_pk,
+                                            md_alg, hash, hashlen, p, sig_len, rs_ctx);
+
+        if (ret != 0) {
+            int send_alert_msg = 1;
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+            send_alert_msg = (ret != MBEDTLS_ERR_ECP_IN_PROGRESS);
+#endif
+            if (send_alert_msg) {
+                mbedtls_ssl_send_alert_message(
+                    ssl,
+                    MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                    MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR);
+            }
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_verify", ret);
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+            if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
+                ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+            }
+#endif
+            return ret;
+        }
+
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+        /* We don't need the peer's public key anymore. Free it,
+         * so that more RAM is available for upcoming expensive
+         * operations like ECDHE. */
+        mbedtls_pk_free(peer_pk);
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+    }
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */
+
+exit:
+    ssl->state++;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse server key exchange"));
+
+    return 0;
+}
+
+#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_certificate_request(mbedtls_ssl_context *ssl)
+{
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate request"));
+
+    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate request"));
+        ssl->state++;
+        return 0;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+}
+#else /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_certificate_request(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *buf;
+    size_t n = 0;
+    size_t cert_type_len = 0, dn_len = 0;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+    size_t sig_alg_len;
+#if defined(MBEDTLS_DEBUG_C)
+    unsigned char *sig_alg;
+    unsigned char *dn;
+#endif
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate request"));
+
+    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate request"));
+        ssl->state++;
+        return 0;
+    }
+
+    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
+        return ret;
+    }
+
+    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message"));
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
+
+    ssl->state++;
+    ssl->handshake->client_auth =
+        (ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST);
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("got %s certificate request",
+                              ssl->handshake->client_auth ? "a" : "no"));
+
+    if (ssl->handshake->client_auth == 0) {
+        /* Current message is probably the ServerHelloDone */
+        ssl->keep_current_message = 1;
+        goto exit;
+    }
+
+    /*
+     *  struct {
+     *      ClientCertificateType certificate_types<1..2^8-1>;
+     *      SignatureAndHashAlgorithm
+     *        supported_signature_algorithms<2^16-1>; -- TLS 1.2 only
+     *      DistinguishedName certificate_authorities<0..2^16-1>;
+     *  } CertificateRequest;
+     *
+     *  Since we only support a single certificate on clients, let's just
+     *  ignore all the information that's supposed to help us pick a
+     *  certificate.
+     *
+     *  We could check that our certificate matches the request, and bail out
+     *  if it doesn't, but it's simpler to just send the certificate anyway,
+     *  and give the server the opportunity to decide if it should terminate
+     *  the connection when it doesn't like our certificate.
+     *
+     *  Same goes for the hash in TLS 1.2's signature_algorithms: at this
+     *  point we only have one hash available (see comments in
+     *  write_certificate_verify), so let's just use what we have.
+     *
+     *  However, we still minimally parse the message to check it is at least
+     *  superficially sane.
+     */
+    buf = ssl->in_msg;
+
+    /* certificate_types */
+    if (ssl->in_hslen <= mbedtls_ssl_hs_hdr_len(ssl)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+    cert_type_len = buf[mbedtls_ssl_hs_hdr_len(ssl)];
+    n = cert_type_len;
+
+    /*
+     * In the subsequent code there are two paths that read from buf:
+     *     * the length of the signature algorithms field (if minor version of
+     *       SSL is 3),
+     *     * distinguished name length otherwise.
+     * Both reach at most the index:
+     *    ...hdr_len + 2 + n,
+     * therefore the buffer length at this point must be greater than that
+     * regardless of the actual code path.
+     */
+    if (ssl->in_hslen <= mbedtls_ssl_hs_hdr_len(ssl) + 2 + n) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /* supported_signature_algorithms */
+    sig_alg_len = ((buf[mbedtls_ssl_hs_hdr_len(ssl) + 1 + n] <<  8)
+                   | (buf[mbedtls_ssl_hs_hdr_len(ssl) + 2 + n]));
+
+    /*
+     * The furthest access in buf is in the loop few lines below:
+     *     sig_alg[i + 1],
+     * where:
+     *     sig_alg = buf + ...hdr_len + 3 + n,
+     *     max(i) = sig_alg_len - 1.
+     * Therefore the furthest access is:
+     *     buf[...hdr_len + 3 + n + sig_alg_len - 1 + 1],
+     * which reduces to:
+     *     buf[...hdr_len + 3 + n + sig_alg_len],
+     * which is one less than we need the buf to be.
+     */
+    if (ssl->in_hslen <= mbedtls_ssl_hs_hdr_len(ssl) + 3 + n + sig_alg_len) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message"));
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+#if defined(MBEDTLS_DEBUG_C)
+    sig_alg = buf + mbedtls_ssl_hs_hdr_len(ssl) + 3 + n;
+    for (size_t i = 0; i < sig_alg_len; i += 2) {
+        MBEDTLS_SSL_DEBUG_MSG(3,
+                              ("Supported Signature Algorithm found: %02x %02x",
+                               sig_alg[i], sig_alg[i + 1]));
+    }
+#endif
+
+    n += 2 + sig_alg_len;
+
+    /* certificate_authorities */
+    dn_len = ((buf[mbedtls_ssl_hs_hdr_len(ssl) + 1 + n] <<  8)
+              | (buf[mbedtls_ssl_hs_hdr_len(ssl) + 2 + n]));
+
+    n += dn_len;
+    if (ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) + 3 + n) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+#if defined(MBEDTLS_DEBUG_C)
+    dn = buf + mbedtls_ssl_hs_hdr_len(ssl) + 3 + n - dn_len;
+    for (size_t i = 0, dni_len = 0; i < dn_len; i += 2 + dni_len) {
+        unsigned char *p = dn + i + 2;
+        mbedtls_x509_name name;
+        size_t asn1_len;
+        char s[MBEDTLS_X509_MAX_DN_NAME_SIZE];
+        memset(&name, 0, sizeof(name));
+        dni_len = MBEDTLS_GET_UINT16_BE(dn + i, 0);
+        if (dni_len > dn_len - i - 2 ||
+            mbedtls_asn1_get_tag(&p, p + dni_len, &asn1_len,
+                                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0 ||
+            mbedtls_x509_get_name(&p, p + asn1_len, &name) != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message"));
+            mbedtls_ssl_send_alert_message(
+                ssl,
+                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+        MBEDTLS_SSL_DEBUG_MSG(3,
+                              ("DN hint: %.*s",
+                               mbedtls_x509_dn_gets(s, sizeof(s), &name), s));
+        mbedtls_asn1_free_named_data_list_shallow(name.next);
+    }
+#endif
+
+exit:
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate request"));
+
+    return 0;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_server_hello_done(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse server hello done"));
+
+    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
+        return ret;
+    }
+
+    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello done message"));
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
+
+    if (ssl->in_hslen  != mbedtls_ssl_hs_hdr_len(ssl) ||
+        ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello done message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    ssl->state++;
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        mbedtls_ssl_recv_flight_completed(ssl);
+    }
+#endif
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse server hello done"));
+
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    size_t header_len;
+    size_t content_len;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write client key exchange"));
+
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA) {
+        /*
+         * DHM key exchange -- send G^X mod P
+         */
+        content_len = mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx);
+
+        MBEDTLS_PUT_UINT16_BE(content_len, ssl->out_msg, 4);
+        header_len = 6;
+
+        ret = mbedtls_dhm_make_public(&ssl->handshake->dhm_ctx,
+                                      (int) mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx),
+                                      &ssl->out_msg[header_len], content_len,
+                                      ssl->conf->f_rng, ssl->conf->p_rng);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_make_public", ret);
+            return ret;
+        }
+
+        MBEDTLS_SSL_DEBUG_MPI(3, "DHM: X ", &ssl->handshake->dhm_ctx.X);
+        MBEDTLS_SSL_DEBUG_MPI(3, "DHM: GX", &ssl->handshake->dhm_ctx.GX);
+
+        if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx,
+                                           ssl->handshake->premaster,
+                                           MBEDTLS_PREMASTER_SIZE,
+                                           &ssl->handshake->pmslen,
+                                           ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret);
+            return ret;
+        }
+
+        MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K);
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA) {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+        psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED;
+        psa_key_attributes_t key_attributes;
+
+        mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+        header_len = 4;
+
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH computation."));
+
+        /*
+         * Generate EC private key for ECDHE exchange.
+         */
+
+        /* The master secret is obtained from the shared ECDH secret by
+         * applying the TLS 1.2 PRF with a specific salt and label. While
+         * the PSA Crypto API encourages combining key agreement schemes
+         * such as ECDH with fixed KDFs such as TLS 1.2 PRF, it does not
+         * yet support the provisioning of salt + label to the KDF.
+         * For the time being, we therefore need to split the computation
+         * of the ECDH secret and the application of the TLS 1.2 PRF. */
+        key_attributes = psa_key_attributes_init();
+        psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
+        psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
+        psa_set_key_type(&key_attributes, handshake->ecdh_psa_type);
+        psa_set_key_bits(&key_attributes, handshake->ecdh_bits);
+
+        /* Generate ECDH private key. */
+        status = psa_generate_key(&key_attributes,
+                                  &handshake->ecdh_psa_privkey);
+        if (status != PSA_SUCCESS) {
+            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+        }
+
+        /* Export the public part of the ECDH private key from PSA.
+         * The export format is an ECPoint structure as expected by TLS,
+         * but we just need to add a length byte before that. */
+        unsigned char *own_pubkey = ssl->out_msg + header_len + 1;
+        unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
+        size_t own_pubkey_max_len = (size_t) (end - own_pubkey);
+        size_t own_pubkey_len;
+
+        status = psa_export_public_key(handshake->ecdh_psa_privkey,
+                                       own_pubkey, own_pubkey_max_len,
+                                       &own_pubkey_len);
+        if (status != PSA_SUCCESS) {
+            psa_destroy_key(handshake->ecdh_psa_privkey);
+            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+        }
+
+        ssl->out_msg[header_len] = (unsigned char) own_pubkey_len;
+        content_len = own_pubkey_len + 1;
+
+        /* The ECDH secret is the premaster secret used for key derivation. */
+
+        /* Compute ECDH shared secret. */
+        status = psa_raw_key_agreement(PSA_ALG_ECDH,
+                                       handshake->ecdh_psa_privkey,
+                                       handshake->ecdh_psa_peerkey,
+                                       handshake->ecdh_psa_peerkey_len,
+                                       ssl->handshake->premaster,
+                                       sizeof(ssl->handshake->premaster),
+                                       &ssl->handshake->pmslen);
+
+        destruction_status = psa_destroy_key(handshake->ecdh_psa_privkey);
+        handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+
+        if (status != PSA_SUCCESS || destruction_status != PSA_SUCCESS) {
+            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+        }
+#else
+        /*
+         * ECDH key exchange -- send client public value
+         */
+        header_len = 4;
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+        if (ssl->handshake->ecrs_enabled) {
+            if (ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret) {
+                goto ecdh_calc_secret;
+            }
+
+            mbedtls_ecdh_enable_restart(&ssl->handshake->ecdh_ctx);
+        }
+#endif
+
+        ret = mbedtls_ecdh_make_public(&ssl->handshake->ecdh_ctx,
+                                       &content_len,
+                                       &ssl->out_msg[header_len], 1000,
+                                       ssl->conf->f_rng, ssl->conf->p_rng);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_make_public", ret);
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+            if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
+                ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+            }
+#endif
+            return ret;
+        }
+
+        MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,
+                               MBEDTLS_DEBUG_ECDH_Q);
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+        if (ssl->handshake->ecrs_enabled) {
+            ssl->handshake->ecrs_n = content_len;
+            ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret;
+        }
+
+ecdh_calc_secret:
+        if (ssl->handshake->ecrs_enabled) {
+            content_len = ssl->handshake->ecrs_n;
+        }
+#endif
+        if ((ret = mbedtls_ecdh_calc_secret(&ssl->handshake->ecdh_ctx,
+                                            &ssl->handshake->pmslen,
+                                            ssl->handshake->premaster,
+                                            MBEDTLS_MPI_MAX_SIZE,
+                                            ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_calc_secret", ret);
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+            if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
+                ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+            }
+#endif
+            return ret;
+        }
+
+        MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,
+                               MBEDTLS_DEBUG_ECDH_Z);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+#if defined(MBEDTLS_USE_PSA_CRYPTO) &&                           \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) {
+        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+        psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED;
+        psa_key_attributes_t key_attributes;
+
+        mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+        /*
+         * opaque psk_identity<0..2^16-1>;
+         */
+        if (mbedtls_ssl_conf_has_static_psk(ssl->conf) == 0) {
+            /* We don't offer PSK suites if we don't have a PSK,
+             * and we check that the server's choice is among the
+             * ciphersuites we offered, so this should never happen. */
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        }
+
+        /* uint16 to store content length */
+        const size_t content_len_size = 2;
+
+        header_len = 4;
+
+        if (header_len + content_len_size + ssl->conf->psk_identity_len
+            > MBEDTLS_SSL_OUT_CONTENT_LEN) {
+            MBEDTLS_SSL_DEBUG_MSG(1,
+                                  ("psk identity too long or SSL buffer too short"));
+            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+        }
+
+        unsigned char *p = ssl->out_msg + header_len;
+
+        *p++ = MBEDTLS_BYTE_1(ssl->conf->psk_identity_len);
+        *p++ = MBEDTLS_BYTE_0(ssl->conf->psk_identity_len);
+        header_len += content_len_size;
+
+        memcpy(p, ssl->conf->psk_identity,
+               ssl->conf->psk_identity_len);
+        p += ssl->conf->psk_identity_len;
+
+        header_len += ssl->conf->psk_identity_len;
+
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH computation."));
+
+        /*
+         * Generate EC private key for ECDHE exchange.
+         */
+
+        /* The master secret is obtained from the shared ECDH secret by
+         * applying the TLS 1.2 PRF with a specific salt and label. While
+         * the PSA Crypto API encourages combining key agreement schemes
+         * such as ECDH with fixed KDFs such as TLS 1.2 PRF, it does not
+         * yet support the provisioning of salt + label to the KDF.
+         * For the time being, we therefore need to split the computation
+         * of the ECDH secret and the application of the TLS 1.2 PRF. */
+        key_attributes = psa_key_attributes_init();
+        psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
+        psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
+        psa_set_key_type(&key_attributes, handshake->ecdh_psa_type);
+        psa_set_key_bits(&key_attributes, handshake->ecdh_bits);
+
+        /* Generate ECDH private key. */
+        status = psa_generate_key(&key_attributes,
+                                  &handshake->ecdh_psa_privkey);
+        if (status != PSA_SUCCESS) {
+            return PSA_TO_MBEDTLS_ERR(status);
+        }
+
+        /* Export the public part of the ECDH private key from PSA.
+         * The export format is an ECPoint structure as expected by TLS,
+         * but we just need to add a length byte before that. */
+        unsigned char *own_pubkey = p + 1;
+        unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
+        size_t own_pubkey_max_len = (size_t) (end - own_pubkey);
+        size_t own_pubkey_len = 0;
+
+        status = psa_export_public_key(handshake->ecdh_psa_privkey,
+                                       own_pubkey, own_pubkey_max_len,
+                                       &own_pubkey_len);
+        if (status != PSA_SUCCESS) {
+            psa_destroy_key(handshake->ecdh_psa_privkey);
+            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+            return PSA_TO_MBEDTLS_ERR(status);
+        }
+
+        *p = (unsigned char) own_pubkey_len;
+        content_len = own_pubkey_len + 1;
+
+        /* As RFC 5489 section 2, the premaster secret is formed as follows:
+         * - a uint16 containing the length (in octets) of the ECDH computation
+         * - the octet string produced by the ECDH computation
+         * - a uint16 containing the length (in octets) of the PSK
+         * - the PSK itself
+         */
+        unsigned char *pms = ssl->handshake->premaster;
+        const unsigned char * const pms_end = pms +
+                                              sizeof(ssl->handshake->premaster);
+        /* uint16 to store length (in octets) of the ECDH computation */
+        const size_t zlen_size = 2;
+        size_t zlen = 0;
+
+        /* Perform ECDH computation after the uint16 reserved for the length */
+        status = psa_raw_key_agreement(PSA_ALG_ECDH,
+                                       handshake->ecdh_psa_privkey,
+                                       handshake->ecdh_psa_peerkey,
+                                       handshake->ecdh_psa_peerkey_len,
+                                       pms + zlen_size,
+                                       pms_end - (pms + zlen_size),
+                                       &zlen);
+
+        destruction_status = psa_destroy_key(handshake->ecdh_psa_privkey);
+        handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+
+        if (status != PSA_SUCCESS) {
+            return PSA_TO_MBEDTLS_ERR(status);
+        } else if (destruction_status != PSA_SUCCESS) {
+            return PSA_TO_MBEDTLS_ERR(destruction_status);
+        }
+
+        /* Write the ECDH computation length before the ECDH computation */
+        MBEDTLS_PUT_UINT16_BE(zlen, pms, 0);
+        pms += zlen_size + zlen;
+    } else
+#endif /* MBEDTLS_USE_PSA_CRYPTO &&
+          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+    if (mbedtls_ssl_ciphersuite_uses_psk(ciphersuite_info)) {
+        /*
+         * opaque psk_identity<0..2^16-1>;
+         */
+        if (mbedtls_ssl_conf_has_static_psk(ssl->conf) == 0) {
+            /* We don't offer PSK suites if we don't have a PSK,
+             * and we check that the server's choice is among the
+             * ciphersuites we offered, so this should never happen. */
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        }
+
+        header_len = 4;
+        content_len = ssl->conf->psk_identity_len;
+
+        if (header_len + 2 + content_len > MBEDTLS_SSL_OUT_CONTENT_LEN) {
+            MBEDTLS_SSL_DEBUG_MSG(1,
+                                  ("psk identity too long or SSL buffer too short"));
+            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+        }
+
+        ssl->out_msg[header_len++] = MBEDTLS_BYTE_1(content_len);
+        ssl->out_msg[header_len++] = MBEDTLS_BYTE_0(content_len);
+
+        memcpy(ssl->out_msg + header_len,
+               ssl->conf->psk_identity,
+               ssl->conf->psk_identity_len);
+        header_len += ssl->conf->psk_identity_len;
+
+#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
+        if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK) {
+            content_len = 0;
+        } else
+#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
+        if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) {
+            if ((ret = ssl_write_encrypted_pms(ssl, header_len,
+                                               &content_len, 2)) != 0) {
+                return ret;
+            }
+        } else
+#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
+        if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK) {
+            /*
+             * ClientDiffieHellmanPublic public (DHM send G^X mod P)
+             */
+            content_len = mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx);
+
+            if (header_len + 2 + content_len >
+                MBEDTLS_SSL_OUT_CONTENT_LEN) {
+                MBEDTLS_SSL_DEBUG_MSG(1,
+                                      ("psk identity or DHM size too long or SSL buffer too short"));
+                return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+            }
+
+            ssl->out_msg[header_len++] = MBEDTLS_BYTE_1(content_len);
+            ssl->out_msg[header_len++] = MBEDTLS_BYTE_0(content_len);
+
+            ret = mbedtls_dhm_make_public(&ssl->handshake->dhm_ctx,
+                                          (int) mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx),
+                                          &ssl->out_msg[header_len], content_len,
+                                          ssl->conf->f_rng, ssl->conf->p_rng);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_make_public", ret);
+                return ret;
+            }
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+            unsigned char *pms = ssl->handshake->premaster;
+            unsigned char *pms_end = pms + sizeof(ssl->handshake->premaster);
+            size_t pms_len;
+
+            /* Write length only when we know the actual value */
+            if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx,
+                                               pms + 2, pms_end - (pms + 2), &pms_len,
+                                               ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret);
+                return ret;
+            }
+            MBEDTLS_PUT_UINT16_BE(pms_len, pms, 0);
+            pms += 2 + pms_len;
+
+            MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K);
+#endif
+        } else
+#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
+#if !defined(MBEDTLS_USE_PSA_CRYPTO) &&                             \
+        defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+        if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) {
+            /*
+             * ClientECDiffieHellmanPublic public;
+             */
+            ret = mbedtls_ecdh_make_public(&ssl->handshake->ecdh_ctx,
+                                           &content_len,
+                                           &ssl->out_msg[header_len],
+                                           MBEDTLS_SSL_OUT_CONTENT_LEN - header_len,
+                                           ssl->conf->f_rng, ssl->conf->p_rng);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_make_public", ret);
+                return ret;
+            }
+
+            MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,
+                                   MBEDTLS_DEBUG_ECDH_Q);
+        } else
+#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+        {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        }
+
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
+        if ((ret = mbedtls_ssl_psk_derive_premaster(ssl,
+                                                    ciphersuite_info->key_exchange)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1,
+                                  "mbedtls_ssl_psk_derive_premaster", ret);
+            return ret;
+        }
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA) {
+        header_len = 4;
+        if ((ret = ssl_write_encrypted_pms(ssl, header_len,
+                                           &content_len, 0)) != 0) {
+            return ret;
+        }
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) {
+        header_len = 4;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        unsigned char *out_p = ssl->out_msg + header_len;
+        unsigned char *end_p = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN -
+                               header_len;
+        ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx,
+                                              out_p, end_p - out_p, &content_len,
+                                              MBEDTLS_ECJPAKE_ROUND_TWO);
+        if (ret != 0) {
+            psa_destroy_key(ssl->handshake->psa_pake_password);
+            psa_pake_abort(&ssl->handshake->psa_pake_ctx);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret);
+            return ret;
+        }
+#else
+        ret = mbedtls_ecjpake_write_round_two(&ssl->handshake->ecjpake_ctx,
+                                              ssl->out_msg + header_len,
+                                              MBEDTLS_SSL_OUT_CONTENT_LEN - header_len,
+                                              &content_len,
+                                              ssl->conf->f_rng, ssl->conf->p_rng);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_write_round_two", ret);
+            return ret;
+        }
+
+        ret = mbedtls_ecjpake_derive_secret(&ssl->handshake->ecjpake_ctx,
+                                            ssl->handshake->premaster, 32, &ssl->handshake->pmslen,
+                                            ssl->conf->f_rng, ssl->conf->p_rng);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_derive_secret", ret);
+            return ret;
+        }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
+    {
+        ((void) ciphersuite_info);
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    ssl->out_msglen  = header_len + content_len;
+    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE;
+
+    ssl->state++;
+
+    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret);
+        return ret;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write client key exchange"));
+
+    return 0;
+}
+
+#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_certificate_verify(mbedtls_ssl_context *ssl)
+{
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate verify"));
+
+    if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_derive_keys", ret);
+        return ret;
+    }
+
+    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate verify"));
+        ssl->state++;
+        return 0;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+}
+#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_certificate_verify(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+    size_t n = 0, offset = 0;
+    unsigned char hash[48];
+    unsigned char *hash_start = hash;
+    mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;
+    size_t hashlen;
+    void *rs_ctx = NULL;
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+    size_t out_buf_len = ssl->out_buf_len - (ssl->out_msg - ssl->out_buf);
+#else
+    size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (ssl->out_msg - ssl->out_buf);
+#endif
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate verify"));
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    if (ssl->handshake->ecrs_enabled &&
+        ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign) {
+        goto sign;
+    }
+#endif
+
+    if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_derive_keys", ret);
+        return ret;
+    }
+
+    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate verify"));
+        ssl->state++;
+        return 0;
+    }
+
+    if (ssl->handshake->client_auth == 0 ||
+        mbedtls_ssl_own_cert(ssl) == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate verify"));
+        ssl->state++;
+        return 0;
+    }
+
+    if (mbedtls_ssl_own_key(ssl) == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("got no private key for certificate"));
+        return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED;
+    }
+
+    /*
+     * Make a signature of the handshake digests
+     */
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    if (ssl->handshake->ecrs_enabled) {
+        ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign;
+    }
+
+sign:
+#endif
+
+    ret = ssl->handshake->calc_verify(ssl, hash, &hashlen);
+    if (0 != ret) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("calc_verify"), ret);
+        return ret;
+    }
+
+    /*
+     * digitally-signed struct {
+     *     opaque handshake_messages[handshake_messages_length];
+     * };
+     *
+     * Taking shortcut here. We assume that the server always allows the
+     * PRF Hash function and has sent it in the allowed signature
+     * algorithms list received in the Certificate Request message.
+     *
+     * Until we encounter a server that does not, we will take this
+     * shortcut.
+     *
+     * Reason: Otherwise we should have running hashes for SHA512 and
+     *         SHA224 in order to satisfy 'weird' needs from the server
+     *         side.
+     */
+    if (ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384) {
+        md_alg = MBEDTLS_MD_SHA384;
+        ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384;
+    } else {
+        md_alg = MBEDTLS_MD_SHA256;
+        ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256;
+    }
+    ssl->out_msg[5] = mbedtls_ssl_sig_from_pk(mbedtls_ssl_own_key(ssl));
+
+    /* Info from md_alg will be used instead */
+    hashlen = 0;
+    offset = 2;
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    if (ssl->handshake->ecrs_enabled) {
+        rs_ctx = &ssl->handshake->ecrs_ctx.pk;
+    }
+#endif
+
+    if ((ret = mbedtls_pk_sign_restartable(mbedtls_ssl_own_key(ssl),
+                                           md_alg, hash_start, hashlen,
+                                           ssl->out_msg + 6 + offset,
+                                           out_buf_len - 6 - offset,
+                                           &n,
+                                           ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_sign", ret);
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+        if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
+            ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+        }
+#endif
+        return ret;
+    }
+
+    MBEDTLS_PUT_UINT16_BE(n, ssl->out_msg, offset + 4);
+
+    ssl->out_msglen  = 6 + n + offset;
+    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY;
+
+    ssl->state++;
+
+    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret);
+        return ret;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate verify"));
+
+    return ret;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_new_session_ticket(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    uint32_t lifetime;
+    size_t ticket_len;
+    unsigned char *ticket;
+    const unsigned char *msg;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse new session ticket"));
+
+    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
+        return ret;
+    }
+
+    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad new session ticket message"));
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
+
+    /*
+     * struct {
+     *     uint32 ticket_lifetime_hint;
+     *     opaque ticket<0..2^16-1>;
+     * } NewSessionTicket;
+     *
+     * 0  .  3   ticket_lifetime_hint
+     * 4  .  5   ticket_len (n)
+     * 6  .  5+n ticket content
+     */
+    if (ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET ||
+        ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len(ssl)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad new session ticket message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl);
+
+    lifetime = (((uint32_t) msg[0]) << 24) | (msg[1] << 16) |
+               (msg[2] << 8) | (msg[3]);
+
+    ticket_len = (msg[4] << 8) | (msg[5]);
+
+    if (ticket_len + 6 + mbedtls_ssl_hs_hdr_len(ssl) != ssl->in_hslen) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad new session ticket message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("ticket length: %" MBEDTLS_PRINTF_SIZET, ticket_len));
+
+    /* We're not waiting for a NewSessionTicket message any more */
+    ssl->handshake->new_session_ticket = 0;
+    ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC;
+
+    /*
+     * Zero-length ticket means the server changed his mind and doesn't want
+     * to send a ticket after all, so just forget it
+     */
+    if (ticket_len == 0) {
+        return 0;
+    }
+
+    if (ssl->session != NULL && ssl->session->ticket != NULL) {
+        mbedtls_platform_zeroize(ssl->session->ticket,
+                                 ssl->session->ticket_len);
+        mbedtls_free(ssl->session->ticket);
+        ssl->session->ticket = NULL;
+        ssl->session->ticket_len = 0;
+    }
+
+    mbedtls_platform_zeroize(ssl->session_negotiate->ticket,
+                             ssl->session_negotiate->ticket_len);
+    mbedtls_free(ssl->session_negotiate->ticket);
+    ssl->session_negotiate->ticket = NULL;
+    ssl->session_negotiate->ticket_len = 0;
+
+    if ((ticket = mbedtls_calloc(1, ticket_len)) == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("ticket alloc failed"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+    }
+
+    memcpy(ticket, msg + 6, ticket_len);
+
+    ssl->session_negotiate->ticket = ticket;
+    ssl->session_negotiate->ticket_len = ticket_len;
+    ssl->session_negotiate->ticket_lifetime = lifetime;
+
+    /*
+     * RFC 5077 section 3.4:
+     * "If the client receives a session ticket from the server, then it
+     * discards any Session ID that was sent in the ServerHello."
+     */
+    MBEDTLS_SSL_DEBUG_MSG(3, ("ticket in use, discarding session id"));
+    ssl->session_negotiate->id_len = 0;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse new session ticket"));
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+/*
+ * SSL handshake -- client side -- single step
+ */
+int mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl)
+{
+    int ret = 0;
+
+    /* Change state now, so that it is right in mbedtls_ssl_read_record(), used
+     * by DTLS for dropping out-of-sequence ChangeCipherSpec records */
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    if (ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC &&
+        ssl->handshake->new_session_ticket != 0) {
+        ssl->state = MBEDTLS_SSL_NEW_SESSION_TICKET;
+    }
+#endif
+
+    switch (ssl->state) {
+        case MBEDTLS_SSL_HELLO_REQUEST:
+            ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
+            break;
+
+        /*
+         *  ==>   ClientHello
+         */
+        case MBEDTLS_SSL_CLIENT_HELLO:
+            ret = mbedtls_ssl_write_client_hello(ssl);
+            break;
+
+        /*
+         *  <==   ServerHello
+         *        Certificate
+         *      ( ServerKeyExchange  )
+         *      ( CertificateRequest )
+         *        ServerHelloDone
+         */
+        case MBEDTLS_SSL_SERVER_HELLO:
+            ret = ssl_parse_server_hello(ssl);
+            break;
+
+        case MBEDTLS_SSL_SERVER_CERTIFICATE:
+            ret = mbedtls_ssl_parse_certificate(ssl);
+            break;
+
+        case MBEDTLS_SSL_SERVER_KEY_EXCHANGE:
+            ret = ssl_parse_server_key_exchange(ssl);
+            break;
+
+        case MBEDTLS_SSL_CERTIFICATE_REQUEST:
+            ret = ssl_parse_certificate_request(ssl);
+            break;
+
+        case MBEDTLS_SSL_SERVER_HELLO_DONE:
+            ret = ssl_parse_server_hello_done(ssl);
+            break;
+
+        /*
+         *  ==> ( Certificate/Alert  )
+         *        ClientKeyExchange
+         *      ( CertificateVerify  )
+         *        ChangeCipherSpec
+         *        Finished
+         */
+        case MBEDTLS_SSL_CLIENT_CERTIFICATE:
+            ret = mbedtls_ssl_write_certificate(ssl);
+            break;
+
+        case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:
+            ret = ssl_write_client_key_exchange(ssl);
+            break;
+
+        case MBEDTLS_SSL_CERTIFICATE_VERIFY:
+            ret = ssl_write_certificate_verify(ssl);
+            break;
+
+        case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC:
+            ret = mbedtls_ssl_write_change_cipher_spec(ssl);
+            break;
+
+        case MBEDTLS_SSL_CLIENT_FINISHED:
+            ret = mbedtls_ssl_write_finished(ssl);
+            break;
+
+            /*
+             *  <==   ( NewSessionTicket )
+             *        ChangeCipherSpec
+             *        Finished
+             */
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+        case MBEDTLS_SSL_NEW_SESSION_TICKET:
+            ret = ssl_parse_new_session_ticket(ssl);
+            break;
+#endif
+
+        case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC:
+            ret = mbedtls_ssl_parse_change_cipher_spec(ssl);
+            break;
+
+        case MBEDTLS_SSL_SERVER_FINISHED:
+            ret = mbedtls_ssl_parse_finished(ssl);
+            break;
+
+        case MBEDTLS_SSL_FLUSH_BUFFERS:
+            MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done"));
+            ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
+            break;
+
+        case MBEDTLS_SSL_HANDSHAKE_WRAPUP:
+            mbedtls_ssl_handshake_wrapup(ssl);
+            break;
+
+        default:
+            MBEDTLS_SSL_DEBUG_MSG(1, ("invalid state %d", ssl->state));
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    return ret;
+}
+
+#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_PROTO_TLS1_2 */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls12_server.c b/lib/libmbedtls/mbedtls/library/ssl_tls12_server.c
new file mode 100644
index 0000000..631331d
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls12_server.c
@@ -0,0 +1,4341 @@
+/*
+ *  TLS server-side functions
+ *
+ *  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.
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_TLS1_2)
+
+#include "mbedtls/platform.h"
+
+#include "mbedtls/ssl.h"
+#include "ssl_misc.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
+#include "mbedtls/platform_util.h"
+#include "constant_time_internal.h"
+#include "mbedtls/constant_time.h"
+#include "hash_info.h"
+
+#include <string.h>
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_ssl_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+#endif
+
+#if defined(MBEDTLS_ECP_C)
+#include "mbedtls/ecp.h"
+#endif
+
+#if defined(MBEDTLS_HAVE_TIME)
+#include "mbedtls/platform_time.h"
+#endif
+
+#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
+int mbedtls_ssl_set_client_transport_id(mbedtls_ssl_context *ssl,
+                                        const unsigned char *info,
+                                        size_t ilen)
+{
+    if (ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    mbedtls_free(ssl->cli_id);
+
+    if ((ssl->cli_id = mbedtls_calloc(1, ilen)) == NULL) {
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+    }
+
+    memcpy(ssl->cli_id, info, ilen);
+    ssl->cli_id_len = ilen;
+
+    return 0;
+}
+
+void mbedtls_ssl_conf_dtls_cookies(mbedtls_ssl_config *conf,
+                                   mbedtls_ssl_cookie_write_t *f_cookie_write,
+                                   mbedtls_ssl_cookie_check_t *f_cookie_check,
+                                   void *p_cookie)
+{
+    conf->f_cookie_write = f_cookie_write;
+    conf->f_cookie_check = f_cookie_check;
+    conf->p_cookie       = p_cookie;
+}
+#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_conf_has_psk_or_cb(mbedtls_ssl_config const *conf)
+{
+    if (conf->f_psk != NULL) {
+        return 1;
+    }
+
+    if (conf->psk_identity_len == 0 || conf->psk_identity == NULL) {
+        return 0;
+    }
+
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) {
+        return 1;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    if (conf->psk != NULL && conf->psk_len != 0) {
+        return 1;
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_renegotiation_info(mbedtls_ssl_context *ssl,
+                                        const unsigned char *buf,
+                                        size_t len)
+{
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {
+        /* Check verify-data in constant-time. The length OTOH is no secret */
+        if (len    != 1 + ssl->verify_data_len ||
+            buf[0] !=     ssl->verify_data_len ||
+            mbedtls_ct_memcmp(buf + 1, ssl->peer_verify_data,
+                              ssl->verify_data_len) != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching renegotiation info"));
+            mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                           MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+        }
+    } else
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+    {
+        if (len != 1 || buf[0] != 0x0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("non-zero length renegotiation info"));
+            mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                           MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+        }
+
+        ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION;
+    }
+
+    return 0;
+}
+
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+/*
+ * Function for parsing a supported groups (TLS 1.3) or supported elliptic
+ * curves (TLS 1.2) extension.
+ *
+ * The "extension_data" field of a supported groups extension contains a
+ * "NamedGroupList" value (TLS 1.3 RFC8446):
+ *      enum {
+ *          secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019),
+ *          x25519(0x001D), x448(0x001E),
+ *          ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102),
+ *          ffdhe6144(0x0103), ffdhe8192(0x0104),
+ *          ffdhe_private_use(0x01FC..0x01FF),
+ *          ecdhe_private_use(0xFE00..0xFEFF),
+ *          (0xFFFF)
+ *      } NamedGroup;
+ *      struct {
+ *          NamedGroup named_group_list<2..2^16-1>;
+ *      } NamedGroupList;
+ *
+ * The "extension_data" field of a supported elliptic curves extension contains
+ * a "NamedCurveList" value (TLS 1.2 RFC 8422):
+ * enum {
+ *      deprecated(1..22),
+ *      secp256r1 (23), secp384r1 (24), secp521r1 (25),
+ *      x25519(29), x448(30),
+ *      reserved (0xFE00..0xFEFF),
+ *      deprecated(0xFF01..0xFF02),
+ *      (0xFFFF)
+ *  } NamedCurve;
+ * struct {
+ *      NamedCurve named_curve_list<2..2^16-1>
+ *  } NamedCurveList;
+ *
+ * The TLS 1.3 supported groups extension was defined to be a compatible
+ * generalization of the TLS 1.2 supported elliptic curves extension. They both
+ * share the same extension identifier.
+ *
+ * DHE groups are not supported yet.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_supported_groups_ext(mbedtls_ssl_context *ssl,
+                                          const unsigned char *buf,
+                                          size_t len)
+{
+    size_t list_size, our_size;
+    const unsigned char *p;
+    uint16_t *curves_tls_id;
+
+    if (len < 2) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+    list_size = ((buf[0] << 8) | (buf[1]));
+    if (list_size + 2 != len ||
+        list_size % 2 != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /* Should never happen unless client duplicates the extension */
+    if (ssl->handshake->curves_tls_id != NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    /* Don't allow our peer to make us allocate too much memory,
+     * and leave room for a final 0 */
+    our_size = list_size / 2 + 1;
+    if (our_size > MBEDTLS_ECP_DP_MAX) {
+        our_size = MBEDTLS_ECP_DP_MAX;
+    }
+
+    if ((curves_tls_id = mbedtls_calloc(our_size,
+                                        sizeof(*curves_tls_id))) == NULL) {
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+    }
+
+    ssl->handshake->curves_tls_id = curves_tls_id;
+
+    p = buf + 2;
+    while (list_size > 0 && our_size > 1) {
+        uint16_t curr_tls_id = MBEDTLS_GET_UINT16_BE(p, 0);
+
+        if (mbedtls_ssl_get_ecp_group_id_from_tls_id(curr_tls_id) !=
+            MBEDTLS_ECP_DP_NONE) {
+            *curves_tls_id++ = curr_tls_id;
+            our_size--;
+        }
+
+        list_size -= 2;
+        p += 2;
+    }
+
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_supported_point_formats(mbedtls_ssl_context *ssl,
+                                             const unsigned char *buf,
+                                             size_t len)
+{
+    size_t list_size;
+    const unsigned char *p;
+
+    if (len == 0 || (size_t) (buf[0] + 1) != len) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+    list_size = buf[0];
+
+    p = buf + 1;
+    while (list_size > 0) {
+        if (p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED ||
+            p[0] == MBEDTLS_ECP_PF_COMPRESSED) {
+#if !defined(MBEDTLS_USE_PSA_CRYPTO) &&                             \
+            (defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C))
+            ssl->handshake->ecdh_ctx.point_format = p[0];
+#endif /* !MBEDTLS_USE_PSA_CRYPTO &&
+          ( MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ) */
+#if !defined(MBEDTLS_USE_PSA_CRYPTO) &&                             \
+            defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+            mbedtls_ecjpake_set_point_format(&ssl->handshake->ecjpake_ctx,
+                                             p[0]);
+#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+            MBEDTLS_SSL_DEBUG_MSG(4, ("point format selected: %d", p[0]));
+            return 0;
+        }
+
+        list_size--;
+        p++;
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
+          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_ecjpake_kkpp(mbedtls_ssl_context *ssl,
+                                  const unsigned char *buf,
+                                  size_t len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (ssl->handshake->psa_pake_ctx_is_ok != 1)
+#else
+    if (mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0)
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("skip ecjpake kkpp extension"));
+        return 0;
+    }
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if ((ret = mbedtls_psa_ecjpake_read_round(
+             &ssl->handshake->psa_pake_ctx, buf, len,
+             MBEDTLS_ECJPAKE_ROUND_ONE)) != 0) {
+        psa_destroy_key(ssl->handshake->psa_pake_password);
+        psa_pake_abort(&ssl->handshake->psa_pake_ctx);
+
+        MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round one", ret);
+        mbedtls_ssl_send_alert_message(
+            ssl,
+            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+
+        return ret;
+    }
+#else
+    if ((ret = mbedtls_ecjpake_read_round_one(&ssl->handshake->ecjpake_ctx,
+                                              buf, len)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_read_round_one", ret);
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);
+        return ret;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    /* Only mark the extension as OK when we're sure it is */
+    ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK;
+
+    return 0;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_max_fragment_length_ext(mbedtls_ssl_context *ssl,
+                                             const unsigned char *buf,
+                                             size_t len)
+{
+    if (len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    ssl->session_negotiate->mfl_code = buf[0];
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_cid_ext(mbedtls_ssl_context *ssl,
+                             const unsigned char *buf,
+                             size_t len)
+{
+    size_t peer_cid_len;
+
+    /* CID extension only makes sense in DTLS */
+    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    /*
+     *   struct {
+     *      opaque cid<0..2^8-1>;
+     *   } ConnectionId;
+     */
+
+    if (len < 1) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    peer_cid_len = *buf++;
+    len--;
+
+    if (len != peer_cid_len) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /* Ignore CID if the user has disabled its use. */
+    if (ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) {
+        /* Leave ssl->handshake->cid_in_use in its default
+         * value of MBEDTLS_SSL_CID_DISABLED. */
+        MBEDTLS_SSL_DEBUG_MSG(3, ("Client sent CID extension, but CID disabled"));
+        return 0;
+    }
+
+    if (peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED;
+    ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len;
+    memcpy(ssl->handshake->peer_cid, buf, peer_cid_len);
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("Use of CID extension negotiated"));
+    MBEDTLS_SSL_DEBUG_BUF(3, "Client CID", buf, peer_cid_len);
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_encrypt_then_mac_ext(mbedtls_ssl_context *ssl,
+                                          const unsigned char *buf,
+                                          size_t len)
+{
+    if (len != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    ((void) buf);
+
+    if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED) {
+        ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED;
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
+
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_extended_ms_ext(mbedtls_ssl_context *ssl,
+                                     const unsigned char *buf,
+                                     size_t len)
+{
+    if (len != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    ((void) buf);
+
+    if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED) {
+        ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED;
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_session_ticket_ext(mbedtls_ssl_context *ssl,
+                                        unsigned char *buf,
+                                        size_t len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ssl_session session;
+
+    mbedtls_ssl_session_init(&session);
+
+    if (ssl->conf->f_ticket_parse == NULL ||
+        ssl->conf->f_ticket_write == NULL) {
+        return 0;
+    }
+
+    /* Remember the client asked us to send a new ticket */
+    ssl->handshake->new_session_ticket = 1;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("ticket length: %" MBEDTLS_PRINTF_SIZET, len));
+
+    if (len == 0) {
+        return 0;
+    }
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("ticket rejected: renegotiating"));
+        return 0;
+    }
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+
+    /*
+     * Failures are ok: just ignore the ticket and proceed.
+     */
+    if ((ret = ssl->conf->f_ticket_parse(ssl->conf->p_ticket, &session,
+                                         buf, len)) != 0) {
+        mbedtls_ssl_session_free(&session);
+
+        if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) {
+            MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is not authentic"));
+        } else if (ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) {
+            MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is expired"));
+        } else {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_ticket_parse", ret);
+        }
+
+        return 0;
+    }
+
+    /*
+     * Keep the session ID sent by the client, since we MUST send it back to
+     * inform them we're accepting the ticket  (RFC 5077 section 3.4)
+     */
+    session.id_len = ssl->session_negotiate->id_len;
+    memcpy(&session.id, ssl->session_negotiate->id, session.id_len);
+
+    mbedtls_ssl_session_free(ssl->session_negotiate);
+    memcpy(ssl->session_negotiate, &session, sizeof(mbedtls_ssl_session));
+
+    /* Zeroize instead of free as we copied the content */
+    mbedtls_platform_zeroize(&session, sizeof(mbedtls_ssl_session));
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("session successfully restored from ticket"));
+
+    ssl->handshake->resume = 1;
+
+    /* Don't send a new ticket after all, this one is OK */
+    ssl->handshake->new_session_ticket = 0;
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl,
+                                  const unsigned char *buf,
+                                  size_t len)
+{
+    mbedtls_ssl_srtp_profile client_protection = MBEDTLS_TLS_SRTP_UNSET;
+    size_t i, j;
+    size_t profile_length;
+    uint16_t mki_length;
+    /*! 2 bytes for profile length and 1 byte for mki len */
+    const size_t size_of_lengths = 3;
+
+    /* If use_srtp is not configured, just ignore the extension */
+    if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) ||
+        (ssl->conf->dtls_srtp_profile_list == NULL) ||
+        (ssl->conf->dtls_srtp_profile_list_len == 0)) {
+        return 0;
+    }
+
+    /* RFC5764 section 4.1.1
+     * uint8 SRTPProtectionProfile[2];
+     *
+     * struct {
+     *   SRTPProtectionProfiles SRTPProtectionProfiles;
+     *   opaque srtp_mki<0..255>;
+     * } UseSRTPData;
+
+     * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>;
+     */
+
+    /*
+     * Min length is 5: at least one protection profile(2 bytes)
+     *                  and length(2 bytes) + srtp_mki length(1 byte)
+     * Check here that we have at least 2 bytes of protection profiles length
+     * and one of srtp_mki length
+     */
+    if (len < size_of_lengths) {
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET;
+
+    /* first 2 bytes are protection profile length(in bytes) */
+    profile_length = (buf[0] << 8) | buf[1];
+    buf += 2;
+
+    /* The profile length cannot be bigger than input buffer size - lengths fields */
+    if (profile_length > len - size_of_lengths ||
+        profile_length % 2 != 0) { /* profiles are 2 bytes long, so the length must be even */
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+    /*
+     * parse the extension list values are defined in
+     * http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml
+     */
+    for (j = 0; j < profile_length; j += 2) {
+        uint16_t protection_profile_value = buf[j] << 8 | buf[j + 1];
+        client_protection = mbedtls_ssl_check_srtp_profile_value(protection_profile_value);
+
+        if (client_protection != MBEDTLS_TLS_SRTP_UNSET) {
+            MBEDTLS_SSL_DEBUG_MSG(3, ("found srtp profile: %s",
+                                      mbedtls_ssl_get_srtp_profile_as_string(
+                                          client_protection)));
+        } else {
+            continue;
+        }
+        /* check if suggested profile is in our list */
+        for (i = 0; i < ssl->conf->dtls_srtp_profile_list_len; i++) {
+            if (client_protection == ssl->conf->dtls_srtp_profile_list[i]) {
+                ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i];
+                MBEDTLS_SSL_DEBUG_MSG(3, ("selected srtp profile: %s",
+                                          mbedtls_ssl_get_srtp_profile_as_string(
+                                              client_protection)));
+                break;
+            }
+        }
+        if (ssl->dtls_srtp_info.chosen_dtls_srtp_profile != MBEDTLS_TLS_SRTP_UNSET) {
+            break;
+        }
+    }
+    buf += profile_length; /* buf points to the mki length */
+    mki_length = *buf;
+    buf++;
+
+    if (mki_length > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH ||
+        mki_length + profile_length + size_of_lengths != len) {
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /* Parse the mki only if present and mki is supported locally */
+    if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED &&
+        mki_length > 0) {
+        ssl->dtls_srtp_info.mki_len = mki_length;
+
+        memcpy(ssl->dtls_srtp_info.mki_value, buf, mki_length);
+
+        MBEDTLS_SSL_DEBUG_BUF(3, "using mki",  ssl->dtls_srtp_info.mki_value,
+                              ssl->dtls_srtp_info.mki_len);
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
+/*
+ * Auxiliary functions for ServerHello parsing and related actions
+ */
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+/*
+ * Return 0 if the given key uses one of the acceptable curves, -1 otherwise
+ */
+#if defined(MBEDTLS_ECDSA_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_check_key_curve(mbedtls_pk_context *pk,
+                               uint16_t *curves_tls_id)
+{
+    uint16_t *curr_tls_id = curves_tls_id;
+    mbedtls_ecp_group_id grp_id = mbedtls_pk_ec(*pk)->grp.id;
+    mbedtls_ecp_group_id curr_grp_id;
+
+    while (*curr_tls_id != 0) {
+        curr_grp_id = mbedtls_ssl_get_ecp_group_id_from_tls_id(*curr_tls_id);
+        if (curr_grp_id == grp_id) {
+            return 0;
+        }
+        curr_tls_id++;
+    }
+
+    return -1;
+}
+#endif /* MBEDTLS_ECDSA_C */
+
+/*
+ * Try picking a certificate for this ciphersuite,
+ * return 0 on success and -1 on failure.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_pick_cert(mbedtls_ssl_context *ssl,
+                         const mbedtls_ssl_ciphersuite_t *ciphersuite_info)
+{
+    mbedtls_ssl_key_cert *cur, *list;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_algorithm_t pk_alg =
+        mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(ciphersuite_info);
+    psa_key_usage_t pk_usage =
+        mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(ciphersuite_info);
+#else
+    mbedtls_pk_type_t pk_alg =
+        mbedtls_ssl_get_ciphersuite_sig_pk_alg(ciphersuite_info);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    uint32_t flags;
+
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    if (ssl->handshake->sni_key_cert != NULL) {
+        list = ssl->handshake->sni_key_cert;
+    } else
+#endif
+    list = ssl->conf->key_cert;
+
+    int pk_alg_is_none = 0;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    pk_alg_is_none = (pk_alg == PSA_ALG_NONE);
+#else
+    pk_alg_is_none = (pk_alg == MBEDTLS_PK_NONE);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    if (pk_alg_is_none) {
+        return 0;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite requires certificate"));
+
+    if (list == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("server has no certificate"));
+        return -1;
+    }
+
+    for (cur = list; cur != NULL; cur = cur->next) {
+        flags = 0;
+        MBEDTLS_SSL_DEBUG_CRT(3, "candidate certificate chain, certificate",
+                              cur->cert);
+
+        int key_type_matches = 0;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+        key_type_matches = ((ssl->conf->f_async_sign_start != NULL ||
+                             ssl->conf->f_async_decrypt_start != NULL ||
+                             mbedtls_pk_can_do_ext(cur->key, pk_alg, pk_usage)) &&
+                            mbedtls_pk_can_do_ext(&cur->cert->pk, pk_alg, pk_usage));
+#else
+        key_type_matches = (
+            mbedtls_pk_can_do_ext(cur->key, pk_alg, pk_usage));
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+#else
+        key_type_matches = mbedtls_pk_can_do(&cur->cert->pk, pk_alg);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+        if (!key_type_matches) {
+            MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: key type"));
+            continue;
+        }
+
+        /*
+         * This avoids sending the client a cert it'll reject based on
+         * keyUsage or other extensions.
+         *
+         * It also allows the user to provision different certificates for
+         * different uses based on keyUsage, eg if they want to avoid signing
+         * and decrypting with the same RSA key.
+         */
+        if (mbedtls_ssl_check_cert_usage(cur->cert, ciphersuite_info,
+                                         MBEDTLS_SSL_IS_SERVER, &flags) != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: "
+                                      "(extended) key usage extension"));
+            continue;
+        }
+
+#if defined(MBEDTLS_ECDSA_C)
+        if (pk_alg == MBEDTLS_PK_ECDSA &&
+            ssl_check_key_curve(&cur->cert->pk,
+                                ssl->handshake->curves_tls_id) != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: elliptic curve"));
+            continue;
+        }
+#endif
+
+        /* If we get there, we got a winner */
+        break;
+    }
+
+    /* Do not update ssl->handshake->key_cert unless there is a match */
+    if (cur != NULL) {
+        ssl->handshake->key_cert = cur;
+        MBEDTLS_SSL_DEBUG_CRT(3, "selected certificate chain, certificate",
+                              ssl->handshake->key_cert->cert);
+        return 0;
+    }
+
+    return -1;
+}
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+/*
+ * Check if a given ciphersuite is suitable for use with our config/keys/etc
+ * Sets ciphersuite_info only if the suite matches.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_ciphersuite_match(mbedtls_ssl_context *ssl, int suite_id,
+                                 const mbedtls_ssl_ciphersuite_t **ciphersuite_info)
+{
+    const mbedtls_ssl_ciphersuite_t *suite_info;
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+    mbedtls_pk_type_t sig_type;
+#endif
+
+    suite_info = mbedtls_ssl_ciphersuite_from_id(suite_id);
+    if (suite_info == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("trying ciphersuite: %#04x (%s)",
+                              (unsigned int) suite_id, suite_info->name));
+
+    if (suite_info->min_tls_version > ssl->tls_version ||
+        suite_info->max_tls_version < ssl->tls_version) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: version"));
+        return 0;
+    }
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+    if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE &&
+        (ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK) == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: ecjpake "
+                                  "not configured or ext missing"));
+        return 0;
+    }
+#endif
+
+
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
+    if (mbedtls_ssl_ciphersuite_uses_ec(suite_info) &&
+        (ssl->handshake->curves_tls_id == NULL ||
+         ssl->handshake->curves_tls_id[0] == 0)) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: "
+                                  "no common elliptic curve"));
+        return 0;
+    }
+#endif
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+    /* If the ciphersuite requires a pre-shared key and we don't
+     * have one, skip it now rather than failing later */
+    if (mbedtls_ssl_ciphersuite_uses_psk(suite_info) &&
+        ssl_conf_has_psk_or_cb(ssl->conf) == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: no pre-shared key"));
+        return 0;
+    }
+#endif
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    /*
+     * Final check: if ciphersuite requires us to have a
+     * certificate/key of a particular type:
+     * - select the appropriate certificate if we have one, or
+     * - try the next ciphersuite if we don't
+     * This must be done last since we modify the key_cert list.
+     */
+    if (ssl_pick_cert(ssl, suite_info) != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: "
+                                  "no suitable certificate"));
+        return 0;
+    }
+#endif
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+    /* If the ciphersuite requires signing, check whether
+     * a suitable hash algorithm is present. */
+    sig_type = mbedtls_ssl_get_ciphersuite_sig_alg(suite_info);
+    if (sig_type != MBEDTLS_PK_NONE &&
+        mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg(
+            ssl, mbedtls_ssl_sig_from_pk_alg(sig_type)) == MBEDTLS_SSL_HASH_NONE) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: no suitable hash algorithm "
+                                  "for signature algorithm %u", (unsigned) sig_type));
+        return 0;
+    }
+
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
+    *ciphersuite_info = suite_info;
+    return 0;
+}
+
+/* This function doesn't alert on errors that happen early during
+   ClientHello parsing because they might indicate that the client is
+   not talking SSL/TLS at all and would not understand our alert. */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_client_hello(mbedtls_ssl_context *ssl)
+{
+    int ret, got_common_suite;
+    size_t i, j;
+    size_t ciph_offset, comp_offset, ext_offset;
+    size_t msg_len, ciph_len, sess_len, comp_len, ext_len;
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    size_t cookie_offset, cookie_len;
+#endif
+    unsigned char *buf, *p, *ext;
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    int renegotiation_info_seen = 0;
+#endif
+    int handshake_failure = 0;
+    const int *ciphersuites;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+
+    /* If there is no signature-algorithm extension present,
+     * we need to fall back to the default values for allowed
+     * signature-hash pairs. */
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+    int sig_hash_alg_ext_present = 0;
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client hello"));
+
+    int renegotiating;
+
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+read_record_header:
+#endif
+    /*
+     * If renegotiating, then the input was read with mbedtls_ssl_read_record(),
+     * otherwise read it ourselves manually in order to support SSLv2
+     * ClientHello, which doesn't use the same record layer format.
+     */
+    renegotiating = 0;
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    renegotiating = (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE);
+#endif
+    if (!renegotiating) {
+        if ((ret = mbedtls_ssl_fetch_input(ssl, 5)) != 0) {
+            /* No alert on a read error. */
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret);
+            return ret;
+        }
+    }
+
+    buf = ssl->in_hdr;
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "record header", buf, mbedtls_ssl_in_hdr_len(ssl));
+
+    /*
+     * TLS Client Hello
+     *
+     * Record layer:
+     *     0  .   0   message type
+     *     1  .   2   protocol version
+     *     3  .   11  DTLS: epoch + record sequence number
+     *     3  .   4   message length
+     */
+    MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, message type: %d",
+                              buf[0]));
+
+    if (buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, message len.: %d",
+                              (ssl->in_len[0] << 8) | ssl->in_len[1]));
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, protocol version: [%d:%d]",
+                              buf[1], buf[2]));
+
+    /* For DTLS if this is the initial handshake, remember the client sequence
+     * number to use it in our next message (RFC 6347 4.2.1) */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+        && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE
+#endif
+        ) {
+        /* Epoch should be 0 for initial handshakes */
+        if (ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+        }
+
+        memcpy(&ssl->cur_out_ctr[2], ssl->in_ctr + 2,
+               sizeof(ssl->cur_out_ctr) - 2);
+
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+        if (mbedtls_ssl_dtls_replay_check(ssl) != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("replayed record, discarding"));
+            ssl->next_record_offset = 0;
+            ssl->in_left = 0;
+            goto read_record_header;
+        }
+
+        /* No MAC to check yet, so we can update right now */
+        mbedtls_ssl_dtls_replay_update(ssl);
+#endif
+    }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+    msg_len = (ssl->in_len[0] << 8) | ssl->in_len[1];
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {
+        /* Set by mbedtls_ssl_read_record() */
+        msg_len = ssl->in_hslen;
+    } else
+#endif
+    {
+        if (msg_len > MBEDTLS_SSL_IN_CONTENT_LEN) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+        }
+
+        if ((ret = mbedtls_ssl_fetch_input(ssl,
+                                           mbedtls_ssl_in_hdr_len(ssl) + msg_len)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret);
+            return ret;
+        }
+
+        /* Done reading this record, get ready for the next one */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+            ssl->next_record_offset = msg_len + mbedtls_ssl_in_hdr_len(ssl);
+        } else
+#endif
+        ssl->in_left = 0;
+    }
+
+    buf = ssl->in_msg;
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "record contents", buf, msg_len);
+
+    ret = ssl->handshake->update_checksum(ssl, buf, msg_len);
+    if (0 != ret) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret);
+        return ret;
+    }
+
+    /*
+     * Handshake layer:
+     *     0  .   0   handshake type
+     *     1  .   3   handshake length
+     *     4  .   5   DTLS only: message sequence number
+     *     6  .   8   DTLS only: fragment offset
+     *     9  .  11   DTLS only: fragment length
+     */
+    if (msg_len < mbedtls_ssl_hs_hdr_len(ssl)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, handshake type: %d", buf[0]));
+
+    if (buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
+    {
+        size_t handshake_len = MBEDTLS_GET_UINT24_BE(buf, 1);
+        MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, handshake len.: %u",
+                                  (unsigned) handshake_len));
+
+        /* The record layer has a record size limit of 2^14 - 1 and
+         * fragmentation is not supported, so buf[1] should be zero. */
+        if (buf[1] != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message: %u != 0",
+                                      (unsigned) buf[1]));
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+
+        /* We don't support fragmentation of ClientHello (yet?) */
+        if (msg_len != mbedtls_ssl_hs_hdr_len(ssl) + handshake_len) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message: %u != %u + %u",
+                                      (unsigned) msg_len,
+                                      (unsigned) mbedtls_ssl_hs_hdr_len(ssl),
+                                      (unsigned) handshake_len));
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        /*
+         * Copy the client's handshake message_seq on initial handshakes,
+         * check sequence number on renego.
+         */
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+        if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {
+            /* This couldn't be done in ssl_prepare_handshake_record() */
+            unsigned int cli_msg_seq = (ssl->in_msg[4] << 8) |
+                                       ssl->in_msg[5];
+
+            if (cli_msg_seq != ssl->handshake->in_msg_seq) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message_seq: "
+                                          "%u (expected %u)", cli_msg_seq,
+                                          ssl->handshake->in_msg_seq));
+                return MBEDTLS_ERR_SSL_DECODE_ERROR;
+            }
+
+            ssl->handshake->in_msg_seq++;
+        } else
+#endif
+        {
+            unsigned int cli_msg_seq = (ssl->in_msg[4] << 8) |
+                                       ssl->in_msg[5];
+            ssl->handshake->out_msg_seq = cli_msg_seq;
+            ssl->handshake->in_msg_seq  = cli_msg_seq + 1;
+        }
+        {
+            /*
+             * For now we don't support fragmentation, so make sure
+             * fragment_offset == 0 and fragment_length == length
+             */
+            size_t fragment_offset, fragment_length, length;
+            fragment_offset = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 6);
+            fragment_length = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 9);
+            length = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 1);
+            MBEDTLS_SSL_DEBUG_MSG(
+                4, ("fragment_offset=%u fragment_length=%u length=%u",
+                    (unsigned) fragment_offset, (unsigned) fragment_length,
+                    (unsigned) length));
+            if (fragment_offset != 0 || length != fragment_length) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("ClientHello fragmentation not supported"));
+                return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+            }
+        }
+    }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+    buf += mbedtls_ssl_hs_hdr_len(ssl);
+    msg_len -= mbedtls_ssl_hs_hdr_len(ssl);
+
+    /*
+     * ClientHello layer:
+     *     0  .   1   protocol version
+     *     2  .  33   random bytes (starting with 4 bytes of Unix time)
+     *    34  .  35   session id length (1 byte)
+     *    35  . 34+x  session id
+     *   35+x . 35+x  DTLS only: cookie length (1 byte)
+     *   36+x .  ..   DTLS only: cookie
+     *    ..  .  ..   ciphersuite list length (2 bytes)
+     *    ..  .  ..   ciphersuite list
+     *    ..  .  ..   compression alg. list length (1 byte)
+     *    ..  .  ..   compression alg. list
+     *    ..  .  ..   extensions length (2 bytes, optional)
+     *    ..  .  ..   extensions (optional)
+     */
+
+    /*
+     * Minimal length (with everything empty and extensions omitted) is
+     * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can
+     * read at least up to session id length without worrying.
+     */
+    if (msg_len < 38) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /*
+     * Check and save the protocol version
+     */
+    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, version", buf, 2);
+
+    ssl->tls_version = mbedtls_ssl_read_version(buf, ssl->conf->transport);
+    ssl->session_negotiate->tls_version = ssl->tls_version;
+
+    if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_2) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("server only supports TLS 1.2"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION);
+        return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;
+    }
+
+    /*
+     * Save client random (inc. Unix time)
+     */
+    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, random bytes", buf + 2, 32);
+
+    memcpy(ssl->handshake->randbytes, buf + 2, 32);
+
+    /*
+     * Check the session ID length and save session ID
+     */
+    sess_len = buf[34];
+
+    if (sess_len > sizeof(ssl->session_negotiate->id) ||
+        sess_len + 34 + 2 > msg_len) { /* 2 for cipherlist length field */
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, session id", buf + 35, sess_len);
+
+    ssl->session_negotiate->id_len = sess_len;
+    memset(ssl->session_negotiate->id, 0,
+           sizeof(ssl->session_negotiate->id));
+    memcpy(ssl->session_negotiate->id, buf + 35,
+           ssl->session_negotiate->id_len);
+
+    /*
+     * Check the cookie length and content
+     */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        cookie_offset = 35 + sess_len;
+        cookie_len = buf[cookie_offset];
+
+        if (cookie_offset + 1 + cookie_len + 2 > msg_len) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+            mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+
+        MBEDTLS_SSL_DEBUG_BUF(3, "client hello, cookie",
+                              buf + cookie_offset + 1, cookie_len);
+
+#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
+        if (ssl->conf->f_cookie_check != NULL
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+            && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE
+#endif
+            ) {
+            if (ssl->conf->f_cookie_check(ssl->conf->p_cookie,
+                                          buf + cookie_offset + 1, cookie_len,
+                                          ssl->cli_id, ssl->cli_id_len) != 0) {
+                MBEDTLS_SSL_DEBUG_MSG(2, ("cookie verification failed"));
+                ssl->handshake->cookie_verify_result = 1;
+            } else {
+                MBEDTLS_SSL_DEBUG_MSG(2, ("cookie verification passed"));
+                ssl->handshake->cookie_verify_result = 0;
+            }
+        } else
+#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
+        {
+            /* We know we didn't send a cookie, so it should be empty */
+            if (cookie_len != 0) {
+                /* This may be an attacker's probe, so don't send an alert */
+                MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+                return MBEDTLS_ERR_SSL_DECODE_ERROR;
+            }
+
+            MBEDTLS_SSL_DEBUG_MSG(2, ("cookie verification skipped"));
+        }
+
+        /*
+         * Check the ciphersuitelist length (will be parsed later)
+         */
+        ciph_offset = cookie_offset + 1 + cookie_len;
+    } else
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+    ciph_offset = 35 + sess_len;
+
+    ciph_len = (buf[ciph_offset + 0] << 8)
+               | (buf[ciph_offset + 1]);
+
+    if (ciph_len < 2 ||
+        ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */
+        (ciph_len % 2) != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, ciphersuitelist",
+                          buf + ciph_offset + 2,  ciph_len);
+
+    /*
+     * Check the compression algorithm's length.
+     * The list contents are ignored because implementing
+     * MBEDTLS_SSL_COMPRESS_NULL is mandatory and is the only
+     * option supported by Mbed TLS.
+     */
+    comp_offset = ciph_offset + 2 + ciph_len;
+
+    comp_len = buf[comp_offset];
+
+    if (comp_len < 1 ||
+        comp_len > 16 ||
+        comp_len + comp_offset + 1 > msg_len) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, compression",
+                          buf + comp_offset + 1, comp_len);
+
+    /*
+     * Check the extension length
+     */
+    ext_offset = comp_offset + 1 + comp_len;
+    if (msg_len > ext_offset) {
+        if (msg_len < ext_offset + 2) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+            mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+
+        ext_len = (buf[ext_offset + 0] << 8)
+                  | (buf[ext_offset + 1]);
+
+        if (msg_len != ext_offset + 2 + ext_len) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+            mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+    } else {
+        ext_len = 0;
+    }
+
+    ext = buf + ext_offset + 2;
+    MBEDTLS_SSL_DEBUG_BUF(3, "client hello extensions", ext, ext_len);
+
+    while (ext_len != 0) {
+        unsigned int ext_id;
+        unsigned int ext_size;
+        if (ext_len < 4) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+            mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+        ext_id   = ((ext[0] <<  8) | (ext[1]));
+        ext_size = ((ext[2] <<  8) | (ext[3]));
+
+        if (ext_size + 4 > ext_len) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+            mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+        switch (ext_id) {
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+            case MBEDTLS_TLS_EXT_SERVERNAME:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found ServerName extension"));
+                ret = mbedtls_ssl_parse_server_name_ext(ssl, ext + 4,
+                                                        ext + 4 + ext_size);
+                if (ret != 0) {
+                    return ret;
+                }
+                break;
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+
+            case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found renegotiation extension"));
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+                renegotiation_info_seen = 1;
+#endif
+
+                ret = ssl_parse_renegotiation_info(ssl, ext + 4, ext_size);
+                if (ret != 0) {
+                    return ret;
+                }
+                break;
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+            case MBEDTLS_TLS_EXT_SIG_ALG:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found signature_algorithms extension"));
+
+                ret = mbedtls_ssl_parse_sig_alg_ext(ssl, ext + 4, ext + 4 + ext_size);
+                if (ret != 0) {
+                    return ret;
+                }
+
+                sig_hash_alg_ext_present = 1;
+                break;
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+                defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+            case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found supported elliptic curves extension"));
+
+                ret = ssl_parse_supported_groups_ext(ssl, ext + 4, ext_size);
+                if (ret != 0) {
+                    return ret;
+                }
+                break;
+
+            case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found supported point formats extension"));
+                ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT;
+
+                ret = ssl_parse_supported_point_formats(ssl, ext + 4, ext_size);
+                if (ret != 0) {
+                    return ret;
+                }
+                break;
+#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
+          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+            case MBEDTLS_TLS_EXT_ECJPAKE_KKPP:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found ecjpake kkpp extension"));
+
+                ret = ssl_parse_ecjpake_kkpp(ssl, ext + 4, ext_size);
+                if (ret != 0) {
+                    return ret;
+                }
+                break;
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+            case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found max fragment length extension"));
+
+                ret = ssl_parse_max_fragment_length_ext(ssl, ext + 4, ext_size);
+                if (ret != 0) {
+                    return ret;
+                }
+                break;
+#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+            case MBEDTLS_TLS_EXT_CID:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found CID extension"));
+
+                ret = ssl_parse_cid_ext(ssl, ext + 4, ext_size);
+                if (ret != 0) {
+                    return ret;
+                }
+                break;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+            case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found encrypt then mac extension"));
+
+                ret = ssl_parse_encrypt_then_mac_ext(ssl, ext + 4, ext_size);
+                if (ret != 0) {
+                    return ret;
+                }
+                break;
+#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
+
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+            case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found extended master secret extension"));
+
+                ret = ssl_parse_extended_ms_ext(ssl, ext + 4, ext_size);
+                if (ret != 0) {
+                    return ret;
+                }
+                break;
+#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+            case MBEDTLS_TLS_EXT_SESSION_TICKET:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found session ticket extension"));
+
+                ret = ssl_parse_session_ticket_ext(ssl, ext + 4, ext_size);
+                if (ret != 0) {
+                    return ret;
+                }
+                break;
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+#if defined(MBEDTLS_SSL_ALPN)
+            case MBEDTLS_TLS_EXT_ALPN:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension"));
+
+                ret = mbedtls_ssl_parse_alpn_ext(ssl, ext + 4,
+                                                 ext + 4 + ext_size);
+                if (ret != 0) {
+                    return ret;
+                }
+                break;
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+            case MBEDTLS_TLS_EXT_USE_SRTP:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found use_srtp extension"));
+
+                ret = ssl_parse_use_srtp_ext(ssl, ext + 4, ext_size);
+                if (ret != 0) {
+                    return ret;
+                }
+                break;
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
+            default:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("unknown extension found: %u (ignoring)",
+                                          ext_id));
+        }
+
+        ext_len -= 4 + ext_size;
+        ext += 4 + ext_size;
+    }
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+
+    /*
+     * Try to fall back to default hash SHA1 if the client
+     * hasn't provided any preferred signature-hash combinations.
+     */
+    if (!sig_hash_alg_ext_present) {
+        uint16_t *received_sig_algs = ssl->handshake->received_sig_algs;
+        const uint16_t default_sig_algs[] = {
+#if defined(MBEDTLS_ECDSA_C)
+            MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA,
+                                               MBEDTLS_SSL_HASH_SHA1),
+#endif
+#if defined(MBEDTLS_RSA_C)
+            MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA,
+                                               MBEDTLS_SSL_HASH_SHA1),
+#endif
+            MBEDTLS_TLS_SIG_NONE
+        };
+
+        MBEDTLS_STATIC_ASSERT(sizeof(default_sig_algs) / sizeof(default_sig_algs[0])
+                              <= MBEDTLS_RECEIVED_SIG_ALGS_SIZE,
+                              "default_sig_algs is too big");
+
+        memcpy(received_sig_algs, default_sig_algs, sizeof(default_sig_algs));
+    }
+
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
+    /*
+     * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+     */
+    for (i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2) {
+        if (p[0] == 0 && p[1] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO) {
+            MBEDTLS_SSL_DEBUG_MSG(3, ("received TLS_EMPTY_RENEGOTIATION_INFO "));
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+            if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("received RENEGOTIATION SCSV "
+                                          "during renegotiation"));
+                mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                               MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+                return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+            }
+#endif
+            ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION;
+            break;
+        }
+    }
+
+    /*
+     * Renegotiation security checks
+     */
+    if (ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION &&
+        ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("legacy renegotiation, breaking off handshake"));
+        handshake_failure = 1;
+    }
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
+             ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION &&
+             renegotiation_info_seen == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("renegotiation_info extension missing (secure)"));
+        handshake_failure = 1;
+    } else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
+               ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
+               ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("legacy renegotiation not allowed"));
+        handshake_failure = 1;
+    } else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
+               ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
+               renegotiation_info_seen == 1) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("renegotiation_info extension present (legacy)"));
+        handshake_failure = 1;
+    }
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+
+    if (handshake_failure == 1) {
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+    /*
+     * Server certification selection (after processing TLS extensions)
+     */
+    if (ssl->conf->f_cert_cb && (ret = ssl->conf->f_cert_cb(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "f_cert_cb", ret);
+        return ret;
+    }
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    ssl->handshake->sni_name = NULL;
+    ssl->handshake->sni_name_len = 0;
+#endif
+
+    /*
+     * Search for a matching ciphersuite
+     * (At the end because we need information from the EC-based extensions
+     * and certificate from the SNI callback triggered by the SNI extension
+     * or certificate from server certificate selection callback.)
+     */
+    got_common_suite = 0;
+    ciphersuites = ssl->conf->ciphersuite_list;
+    ciphersuite_info = NULL;
+
+    if (ssl->conf->respect_cli_pref == MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT) {
+        for (j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2) {
+            for (i = 0; ciphersuites[i] != 0; i++) {
+                if (MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i]) {
+                    continue;
+                }
+
+                got_common_suite = 1;
+
+                if ((ret = ssl_ciphersuite_match(ssl, ciphersuites[i],
+                                                 &ciphersuite_info)) != 0) {
+                    return ret;
+                }
+
+                if (ciphersuite_info != NULL) {
+                    goto have_ciphersuite;
+                }
+            }
+        }
+    } else {
+        for (i = 0; ciphersuites[i] != 0; i++) {
+            for (j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2) {
+                if (MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i]) {
+                    continue;
+                }
+
+                got_common_suite = 1;
+
+                if ((ret = ssl_ciphersuite_match(ssl, ciphersuites[i],
+                                                 &ciphersuite_info)) != 0) {
+                    return ret;
+                }
+
+                if (ciphersuite_info != NULL) {
+                    goto have_ciphersuite;
+                }
+            }
+        }
+    }
+
+    if (got_common_suite) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("got ciphersuites in common, "
+                                  "but none of them usable"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("got no ciphersuites in common"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+have_ciphersuite:
+    MBEDTLS_SSL_DEBUG_MSG(2, ("selected ciphersuite: %s", ciphersuite_info->name));
+
+    ssl->session_negotiate->ciphersuite = ciphersuites[i];
+    ssl->handshake->ciphersuite_info = ciphersuite_info;
+
+    ssl->state++;
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        mbedtls_ssl_recv_flight_completed(ssl);
+    }
+#endif
+
+    /* Debugging-only output for testsuite */
+#if defined(MBEDTLS_DEBUG_C)                         && \
+    defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+    mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg(ciphersuite_info);
+    if (sig_alg != MBEDTLS_PK_NONE) {
+        unsigned int sig_hash = mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg(
+            ssl, mbedtls_ssl_sig_from_pk_alg(sig_alg));
+        MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, signature_algorithm ext: %u",
+                                  sig_hash));
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("no hash algorithm for signature algorithm "
+                                  "%u - should not happen", (unsigned) sig_alg));
+    }
+#endif
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse client hello"));
+
+    return 0;
+}
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+static void ssl_write_cid_ext(mbedtls_ssl_context *ssl,
+                              unsigned char *buf,
+                              size_t *olen)
+{
+    unsigned char *p = buf;
+    size_t ext_len;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
+
+    *olen = 0;
+
+    /* Skip writing the extension if we don't want to use it or if
+     * the client hasn't offered it. */
+    if (ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_DISABLED) {
+        return;
+    }
+
+    /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX
+     * which is at most 255, so the increment cannot overflow. */
+    if (end < p || (size_t) (end - p) < (unsigned) (ssl->own_cid_len + 5)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small"));
+        return;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding CID extension"));
+
+    /*
+     *   struct {
+     *      opaque cid<0..2^8-1>;
+     *   } ConnectionId;
+     */
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_CID, p, 0);
+    p += 2;
+    ext_len = (size_t) ssl->own_cid_len + 1;
+    MBEDTLS_PUT_UINT16_BE(ext_len, p, 0);
+    p += 2;
+
+    *p++ = (uint8_t) ssl->own_cid_len;
+    memcpy(p, ssl->own_cid, ssl->own_cid_len);
+
+    *olen = ssl->own_cid_len + 5;
+}
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+static void ssl_write_encrypt_then_mac_ext(mbedtls_ssl_context *ssl,
+                                           unsigned char *buf,
+                                           size_t *olen)
+{
+    unsigned char *p = buf;
+    const mbedtls_ssl_ciphersuite_t *suite = NULL;
+
+    /*
+     * RFC 7366: "If a server receives an encrypt-then-MAC request extension
+     * from a client and then selects a stream or Authenticated Encryption
+     * with Associated Data (AEAD) ciphersuite, it MUST NOT send an
+     * encrypt-then-MAC response extension back to the client."
+     */
+    suite = mbedtls_ssl_ciphersuite_from_id(
+        ssl->session_negotiate->ciphersuite);
+    if (suite == NULL) {
+        ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED;
+    } else {
+        mbedtls_ssl_mode_t ssl_mode =
+            mbedtls_ssl_get_mode_from_ciphersuite(
+                ssl->session_negotiate->encrypt_then_mac,
+                suite);
+
+        if (ssl_mode != MBEDTLS_SSL_MODE_CBC_ETM) {
+            ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED;
+        }
+    }
+
+    if (ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED) {
+        *olen = 0;
+        return;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding encrypt then mac extension"));
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, p, 0);
+    p += 2;
+
+    *p++ = 0x00;
+    *p++ = 0x00;
+
+    *olen = 4;
+}
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
+
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+static void ssl_write_extended_ms_ext(mbedtls_ssl_context *ssl,
+                                      unsigned char *buf,
+                                      size_t *olen)
+{
+    unsigned char *p = buf;
+
+    if (ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED) {
+        *olen = 0;
+        return;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding extended master secret "
+                              "extension"));
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, p, 0);
+    p += 2;
+
+    *p++ = 0x00;
+    *p++ = 0x00;
+
+    *olen = 4;
+}
+#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+static void ssl_write_session_ticket_ext(mbedtls_ssl_context *ssl,
+                                         unsigned char *buf,
+                                         size_t *olen)
+{
+    unsigned char *p = buf;
+
+    if (ssl->handshake->new_session_ticket == 0) {
+        *olen = 0;
+        return;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding session ticket extension"));
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SESSION_TICKET, p, 0);
+    p += 2;
+
+    *p++ = 0x00;
+    *p++ = 0x00;
+
+    *olen = 4;
+}
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+static void ssl_write_renegotiation_ext(mbedtls_ssl_context *ssl,
+                                        unsigned char *buf,
+                                        size_t *olen)
+{
+    unsigned char *p = buf;
+
+    if (ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION) {
+        *olen = 0;
+        return;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, secure renegotiation extension"));
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_RENEGOTIATION_INFO, p, 0);
+    p += 2;
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {
+        *p++ = 0x00;
+        *p++ = (ssl->verify_data_len * 2 + 1) & 0xFF;
+        *p++ = ssl->verify_data_len * 2 & 0xFF;
+
+        memcpy(p, ssl->peer_verify_data, ssl->verify_data_len);
+        p += ssl->verify_data_len;
+        memcpy(p, ssl->own_verify_data, ssl->verify_data_len);
+        p += ssl->verify_data_len;
+    } else
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+    {
+        *p++ = 0x00;
+        *p++ = 0x01;
+        *p++ = 0x00;
+    }
+
+    *olen = p - buf;
+}
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+static void ssl_write_max_fragment_length_ext(mbedtls_ssl_context *ssl,
+                                              unsigned char *buf,
+                                              size_t *olen)
+{
+    unsigned char *p = buf;
+
+    if (ssl->session_negotiate->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE) {
+        *olen = 0;
+        return;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, max_fragment_length extension"));
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, p, 0);
+    p += 2;
+
+    *p++ = 0x00;
+    *p++ = 1;
+
+    *p++ = ssl->session_negotiate->mfl_code;
+
+    *olen = 5;
+}
+#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+static void ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl,
+                                                  unsigned char *buf,
+                                                  size_t *olen)
+{
+    unsigned char *p = buf;
+    ((void) ssl);
+
+    if ((ssl->handshake->cli_exts &
+         MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT) == 0) {
+        *olen = 0;
+        return;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, supported_point_formats extension"));
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, p, 0);
+    p += 2;
+
+    *p++ = 0x00;
+    *p++ = 2;
+
+    *p++ = 1;
+    *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED;
+
+    *olen = 6;
+}
+#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+static void ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl,
+                                       unsigned char *buf,
+                                       size_t *olen)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *p = buf;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
+    size_t kkpp_len;
+
+    *olen = 0;
+
+    /* Skip costly computation if not needed */
+    if (ssl->handshake->ciphersuite_info->key_exchange !=
+        MBEDTLS_KEY_EXCHANGE_ECJPAKE) {
+        return;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, ecjpake kkpp extension"));
+
+    if (end - p < 4) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small"));
+        return;
+    }
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0);
+    p += 2;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx,
+                                          p + 2, end - p - 2, &kkpp_len,
+                                          MBEDTLS_ECJPAKE_ROUND_ONE);
+    if (ret != 0) {
+        psa_destroy_key(ssl->handshake->psa_pake_password);
+        psa_pake_abort(&ssl->handshake->psa_pake_ctx);
+        MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret);
+        return;
+    }
+#else
+    ret = mbedtls_ecjpake_write_round_one(&ssl->handshake->ecjpake_ctx,
+                                          p + 2, end - p - 2, &kkpp_len,
+                                          ssl->conf->f_rng, ssl->conf->p_rng);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_write_round_one", ret);
+        return;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    MBEDTLS_PUT_UINT16_BE(kkpp_len, p, 0);
+    p += 2;
+
+    *olen = kkpp_len + 4;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+
+#if defined(MBEDTLS_SSL_DTLS_SRTP) && defined(MBEDTLS_SSL_PROTO_DTLS)
+static void ssl_write_use_srtp_ext(mbedtls_ssl_context *ssl,
+                                   unsigned char *buf,
+                                   size_t *olen)
+{
+    size_t mki_len = 0, ext_len = 0;
+    uint16_t profile_value = 0;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
+
+    *olen = 0;
+
+    if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) ||
+        (ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET)) {
+        return;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding use_srtp extension"));
+
+    if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED) {
+        mki_len = ssl->dtls_srtp_info.mki_len;
+    }
+
+    /* The extension total size is 9 bytes :
+     * - 2 bytes for the extension tag
+     * - 2 bytes for the total size
+     * - 2 bytes for the protection profile length
+     * - 2 bytes for the protection profile
+     * - 1 byte for the mki length
+     * +  the actual mki length
+     * Check we have enough room in the output buffer */
+    if ((size_t) (end - buf) < mki_len + 9) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small"));
+        return;
+    }
+
+    /* extension */
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_USE_SRTP, buf, 0);
+    /*
+     * total length 5 and mki value: only one profile(2 bytes)
+     *              and length(2 bytes) and srtp_mki  )
+     */
+    ext_len = 5 + mki_len;
+    MBEDTLS_PUT_UINT16_BE(ext_len, buf, 2);
+
+    /* protection profile length: 2 */
+    buf[4] = 0x00;
+    buf[5] = 0x02;
+    profile_value = mbedtls_ssl_check_srtp_profile_value(
+        ssl->dtls_srtp_info.chosen_dtls_srtp_profile);
+    if (profile_value != MBEDTLS_TLS_SRTP_UNSET) {
+        MBEDTLS_PUT_UINT16_BE(profile_value, buf, 6);
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("use_srtp extension invalid profile"));
+        return;
+    }
+
+    buf[8] = mki_len & 0xFF;
+    memcpy(&buf[9], ssl->dtls_srtp_info.mki_value, mki_len);
+
+    *olen = 9 + mki_len;
+}
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
+#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_hello_verify_request(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *p = ssl->out_msg + 4;
+    unsigned char *cookie_len_byte;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write hello verify request"));
+
+    /*
+     * struct {
+     *   ProtocolVersion server_version;
+     *   opaque cookie<0..2^8-1>;
+     * } HelloVerifyRequest;
+     */
+
+    /* The RFC is not clear on this point, but sending the actual negotiated
+     * version looks like the most interoperable thing to do. */
+    mbedtls_ssl_write_version(p, ssl->conf->transport, ssl->tls_version);
+    MBEDTLS_SSL_DEBUG_BUF(3, "server version", p, 2);
+    p += 2;
+
+    /* If we get here, f_cookie_check is not null */
+    if (ssl->conf->f_cookie_write == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("inconsistent cookie callbacks"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    /* Skip length byte until we know the length */
+    cookie_len_byte = p++;
+
+    if ((ret = ssl->conf->f_cookie_write(ssl->conf->p_cookie,
+                                         &p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN,
+                                         ssl->cli_id, ssl->cli_id_len)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "f_cookie_write", ret);
+        return ret;
+    }
+
+    *cookie_len_byte = (unsigned char) (p - (cookie_len_byte + 1));
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte);
+
+    ssl->out_msglen  = p - ssl->out_msg;
+    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST;
+
+    ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT;
+
+    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret);
+        return ret;
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        (ret = mbedtls_ssl_flight_transmit(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret);
+        return ret;
+    }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write hello verify request"));
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
+
+static void ssl_handle_id_based_session_resumption(mbedtls_ssl_context *ssl)
+{
+    int ret;
+    mbedtls_ssl_session session_tmp;
+    mbedtls_ssl_session * const session = ssl->session_negotiate;
+
+    /* Resume is 0  by default, see ssl_handshake_init().
+     * It may be already set to 1 by ssl_parse_session_ticket_ext(). */
+    if (ssl->handshake->resume == 1) {
+        return;
+    }
+    if (session->id_len == 0) {
+        return;
+    }
+    if (ssl->conf->f_get_cache == NULL) {
+        return;
+    }
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {
+        return;
+    }
+#endif
+
+    mbedtls_ssl_session_init(&session_tmp);
+
+    ret = ssl->conf->f_get_cache(ssl->conf->p_cache,
+                                 session->id,
+                                 session->id_len,
+                                 &session_tmp);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    if (session->ciphersuite != session_tmp.ciphersuite) {
+        /* Mismatch between cached and negotiated session */
+        goto exit;
+    }
+
+    /* Move semantics */
+    mbedtls_ssl_session_free(session);
+    *session = session_tmp;
+    memset(&session_tmp, 0, sizeof(session_tmp));
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("session successfully restored from cache"));
+    ssl->handshake->resume = 1;
+
+exit:
+
+    mbedtls_ssl_session_free(&session_tmp);
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_server_hello(mbedtls_ssl_context *ssl)
+{
+#if defined(MBEDTLS_HAVE_TIME)
+    mbedtls_time_t t;
+#endif
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t olen, ext_len = 0, n;
+    unsigned char *buf, *p;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write server hello"));
+
+#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        ssl->handshake->cookie_verify_result != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("client hello was not authenticated"));
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server hello"));
+
+        return ssl_write_hello_verify_request(ssl);
+    }
+#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
+
+    if (ssl->conf->f_rng == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided"));
+        return MBEDTLS_ERR_SSL_NO_RNG;
+    }
+
+    /*
+     *     0  .   0   handshake type
+     *     1  .   3   handshake length
+     *     4  .   5   protocol version
+     *     6  .   9   UNIX time()
+     *    10  .  37   random bytes
+     */
+    buf = ssl->out_msg;
+    p = buf + 4;
+
+    mbedtls_ssl_write_version(p, ssl->conf->transport, ssl->tls_version);
+    p += 2;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen version: [%d:%d]",
+                              buf[4], buf[5]));
+
+#if defined(MBEDTLS_HAVE_TIME)
+    t = mbedtls_time(NULL);
+    MBEDTLS_PUT_UINT32_BE(t, p, 0);
+    p += 4;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, current time: %" MBEDTLS_PRINTF_LONGLONG,
+                              (long long) t));
+#else
+    if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 4)) != 0) {
+        return ret;
+    }
+
+    p += 4;
+#endif /* MBEDTLS_HAVE_TIME */
+
+    if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 28)) != 0) {
+        return ret;
+    }
+
+    p += 28;
+
+    memcpy(ssl->handshake->randbytes + 32, buf + 6, 32);
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", buf + 6, 32);
+
+    ssl_handle_id_based_session_resumption(ssl);
+
+    if (ssl->handshake->resume == 0) {
+        /*
+         * New session, create a new session id,
+         * unless we're about to issue a session ticket
+         */
+        ssl->state++;
+
+#if defined(MBEDTLS_HAVE_TIME)
+        ssl->session_negotiate->start = mbedtls_time(NULL);
+#endif
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+        if (ssl->handshake->new_session_ticket != 0) {
+            ssl->session_negotiate->id_len = n = 0;
+            memset(ssl->session_negotiate->id, 0, 32);
+        } else
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+        {
+            ssl->session_negotiate->id_len = n = 32;
+            if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, ssl->session_negotiate->id,
+                                        n)) != 0) {
+                return ret;
+            }
+        }
+    } else {
+        /*
+         * Resuming a session
+         */
+        n = ssl->session_negotiate->id_len;
+        ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC;
+
+        if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_derive_keys", ret);
+            return ret;
+        }
+    }
+
+    /*
+     *    38  .  38     session id length
+     *    39  . 38+n    session id
+     *   39+n . 40+n    chosen ciphersuite
+     *   41+n . 41+n    chosen compression alg.
+     *   42+n . 43+n    extensions length
+     *   44+n . 43+n+m  extensions
+     */
+    *p++ = (unsigned char) ssl->session_negotiate->id_len;
+    memcpy(p, ssl->session_negotiate->id, ssl->session_negotiate->id_len);
+    p += ssl->session_negotiate->id_len;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n));
+    MBEDTLS_SSL_DEBUG_BUF(3,   "server hello, session id", buf + 39, n);
+    MBEDTLS_SSL_DEBUG_MSG(3, ("%s session has been resumed",
+                              ssl->handshake->resume ? "a" : "no"));
+
+    MBEDTLS_PUT_UINT16_BE(ssl->session_negotiate->ciphersuite, p, 0);
+    p += 2;
+    *p++ = MBEDTLS_BYTE_0(MBEDTLS_SSL_COMPRESS_NULL);
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen ciphersuite: %s",
+                              mbedtls_ssl_get_ciphersuite_name(ssl->session_negotiate->ciphersuite)));
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, compress alg.: 0x%02X",
+                              (unsigned int) MBEDTLS_SSL_COMPRESS_NULL));
+
+    /*
+     *  First write extensions, then the total length
+     */
+    ssl_write_renegotiation_ext(ssl, p + 2 + ext_len, &olen);
+    ext_len += olen;
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+    ssl_write_max_fragment_length_ext(ssl, p + 2 + ext_len, &olen);
+    ext_len += olen;
+#endif
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    ssl_write_cid_ext(ssl, p + 2 + ext_len, &olen);
+    ext_len += olen;
+#endif
+
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+    ssl_write_encrypt_then_mac_ext(ssl, p + 2 + ext_len, &olen);
+    ext_len += olen;
+#endif
+
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+    ssl_write_extended_ms_ext(ssl, p + 2 + ext_len, &olen);
+    ext_len += olen;
+#endif
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    ssl_write_session_ticket_ext(ssl, p + 2 + ext_len, &olen);
+    ext_len += olen;
+#endif
+
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+    const mbedtls_ssl_ciphersuite_t *suite =
+        mbedtls_ssl_ciphersuite_from_id(ssl->session_negotiate->ciphersuite);
+    if (suite != NULL && mbedtls_ssl_ciphersuite_uses_ec(suite)) {
+        ssl_write_supported_point_formats_ext(ssl, p + 2 + ext_len, &olen);
+        ext_len += olen;
+    }
+#endif
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+    ssl_write_ecjpake_kkpp_ext(ssl, p + 2 + ext_len, &olen);
+    ext_len += olen;
+#endif
+
+#if defined(MBEDTLS_SSL_ALPN)
+    unsigned char *end = buf + MBEDTLS_SSL_OUT_CONTENT_LEN - 4;
+    if ((ret = mbedtls_ssl_write_alpn_ext(ssl, p + 2 + ext_len, end, &olen))
+        != 0) {
+        return ret;
+    }
+
+    ext_len += olen;
+#endif
+
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+    ssl_write_use_srtp_ext(ssl, p + 2 + ext_len, &olen);
+    ext_len += olen;
+#endif
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, total extension length: %" MBEDTLS_PRINTF_SIZET,
+                              ext_len));
+
+    if (ext_len > 0) {
+        MBEDTLS_PUT_UINT16_BE(ext_len, p, 0);
+        p += 2 + ext_len;
+    }
+
+    ssl->out_msglen  = p - buf;
+    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = MBEDTLS_SSL_HS_SERVER_HELLO;
+
+    ret = mbedtls_ssl_write_handshake_msg(ssl);
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server hello"));
+
+    return ret;
+}
+
+#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_certificate_request(mbedtls_ssl_context *ssl)
+{
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate request"));
+
+    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate request"));
+        ssl->state++;
+        return 0;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+}
+#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_certificate_request(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+    uint16_t dn_size, total_dn_size; /* excluding length bytes */
+    size_t ct_len, sa_len; /* including length bytes */
+    unsigned char *buf, *p;
+    const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
+    const mbedtls_x509_crt *crt;
+    int authmode;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate request"));
+
+    ssl->state++;
+
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    if (ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET) {
+        authmode = ssl->handshake->sni_authmode;
+    } else
+#endif
+    authmode = ssl->conf->authmode;
+
+    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info) ||
+        authmode == MBEDTLS_SSL_VERIFY_NONE) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate request"));
+        return 0;
+    }
+
+    /*
+     *     0  .   0   handshake type
+     *     1  .   3   handshake length
+     *     4  .   4   cert type count
+     *     5  .. m-1  cert types
+     *     m  .. m+1  sig alg length (TLS 1.2 only)
+     *    m+1 .. n-1  SignatureAndHashAlgorithms (TLS 1.2 only)
+     *     n  .. n+1  length of all DNs
+     *    n+2 .. n+3  length of DN 1
+     *    n+4 .. ...  Distinguished Name #1
+     *    ... .. ...  length of DN 2, etc.
+     */
+    buf = ssl->out_msg;
+    p = buf + 4;
+
+    /*
+     * Supported certificate types
+     *
+     *     ClientCertificateType certificate_types<1..2^8-1>;
+     *     enum { (255) } ClientCertificateType;
+     */
+    ct_len = 0;
+
+#if defined(MBEDTLS_RSA_C)
+    p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN;
+#endif
+#if defined(MBEDTLS_ECDSA_C)
+    p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN;
+#endif
+
+    p[0] = (unsigned char) ct_len++;
+    p += ct_len;
+
+    sa_len = 0;
+
+    /*
+     * Add signature_algorithms for verify (TLS 1.2)
+     *
+     *     SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>;
+     *
+     *     struct {
+     *           HashAlgorithm hash;
+     *           SignatureAlgorithm signature;
+     *     } SignatureAndHashAlgorithm;
+     *
+     *     enum { (255) } HashAlgorithm;
+     *     enum { (255) } SignatureAlgorithm;
+     */
+    const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl);
+    if (sig_alg == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_CONFIG;
+    }
+
+    for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) {
+        unsigned char hash = MBEDTLS_BYTE_1(*sig_alg);
+
+        if (mbedtls_ssl_set_calc_verify_md(ssl, hash)) {
+            continue;
+        }
+        if (!mbedtls_ssl_sig_alg_is_supported(ssl, *sig_alg)) {
+            continue;
+        }
+
+        /* Write elements at offsets starting from 1 (offset 0 is for the
+         * length). Thus the offset of each element is the length of the
+         * partial list including that element. */
+        sa_len += 2;
+        MBEDTLS_PUT_UINT16_BE(*sig_alg, p, sa_len);
+
+    }
+
+    /* Fill in list length. */
+    MBEDTLS_PUT_UINT16_BE(sa_len, p, 0);
+    sa_len += 2;
+    p += sa_len;
+
+    /*
+     * DistinguishedName certificate_authorities<0..2^16-1>;
+     * opaque DistinguishedName<1..2^16-1>;
+     */
+    p += 2;
+
+    total_dn_size = 0;
+
+    if (ssl->conf->cert_req_ca_list ==  MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED) {
+        /* NOTE: If trusted certificates are provisioned
+         *       via a CA callback (configured through
+         *       `mbedtls_ssl_conf_ca_cb()`, then the
+         *       CertificateRequest is currently left empty. */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+        if (ssl->handshake->dn_hints != NULL) {
+            crt = ssl->handshake->dn_hints;
+        } else
+#endif
+        if (ssl->conf->dn_hints != NULL) {
+            crt = ssl->conf->dn_hints;
+        } else
+#endif
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+        if (ssl->handshake->sni_ca_chain != NULL) {
+            crt = ssl->handshake->sni_ca_chain;
+        } else
+#endif
+        crt = ssl->conf->ca_chain;
+
+        while (crt != NULL && crt->version != 0) {
+            /* It follows from RFC 5280 A.1 that this length
+             * can be represented in at most 11 bits. */
+            dn_size = (uint16_t) crt->subject_raw.len;
+
+            if (end < p || (size_t) (end - p) < 2 + (size_t) dn_size) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("skipping CAs: buffer too short"));
+                break;
+            }
+
+            MBEDTLS_PUT_UINT16_BE(dn_size, p, 0);
+            p += 2;
+            memcpy(p, crt->subject_raw.p, dn_size);
+            p += dn_size;
+
+            MBEDTLS_SSL_DEBUG_BUF(3, "requested DN", p - dn_size, dn_size);
+
+            total_dn_size += 2 + dn_size;
+            crt = crt->next;
+        }
+    }
+
+    ssl->out_msglen  = p - buf;
+    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST;
+    MBEDTLS_PUT_UINT16_BE(total_dn_size, ssl->out_msg, 4 + ct_len + sa_len);
+
+    ret = mbedtls_ssl_write_handshake_msg(ssl);
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate request"));
+
+    return ret;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO) &&                      \
+    (defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED))
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    unsigned char buf[
+        PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
+    psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
+    uint16_t tls_id = 0;
+    psa_ecc_family_t ecc_family;
+    size_t key_len;
+    mbedtls_pk_context *pk;
+    mbedtls_ecp_keypair *key;
+
+    pk = mbedtls_ssl_own_key(ssl);
+
+    if (pk == NULL) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    switch (mbedtls_pk_get_type(pk)) {
+        case MBEDTLS_PK_OPAQUE:
+            if (!mbedtls_pk_can_do(pk, MBEDTLS_PK_ECKEY)) {
+                return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;
+            }
+
+            ssl->handshake->ecdh_psa_privkey =
+                *((mbedtls_svc_key_id_t *) pk->pk_ctx);
+
+            /* Key should not be destroyed in the TLS library */
+            ssl->handshake->ecdh_psa_privkey_is_external = 1;
+
+            status = psa_get_key_attributes(ssl->handshake->ecdh_psa_privkey,
+                                            &key_attributes);
+            if (status != PSA_SUCCESS) {
+                ssl->handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+                return PSA_TO_MBEDTLS_ERR(status);
+            }
+
+            ssl->handshake->ecdh_psa_type = psa_get_key_type(&key_attributes);
+            ssl->handshake->ecdh_bits = psa_get_key_bits(&key_attributes);
+
+            psa_reset_key_attributes(&key_attributes);
+
+            ret = 0;
+            break;
+        case MBEDTLS_PK_ECKEY:
+        case MBEDTLS_PK_ECKEY_DH:
+        case MBEDTLS_PK_ECDSA:
+            key = mbedtls_pk_ec(*pk);
+            if (key == NULL) {
+                return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+            }
+
+            tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(key->grp.id);
+            if (tls_id == 0) {
+                /* This elliptic curve is not supported */
+                return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+            }
+
+            /* If the above conversion to TLS ID was fine, then also this one will
+               be, so there is no need to check the return value here */
+            mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &ecc_family,
+                                                       &ssl->handshake->ecdh_bits);
+
+            ssl->handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR(ecc_family);
+
+            key_attributes = psa_key_attributes_init();
+            psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
+            psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
+            psa_set_key_type(&key_attributes,
+                             PSA_KEY_TYPE_ECC_KEY_PAIR(ssl->handshake->ecdh_psa_type));
+            psa_set_key_bits(&key_attributes, ssl->handshake->ecdh_bits);
+
+            key_len = PSA_BITS_TO_BYTES(key->grp.pbits);
+            ret = mbedtls_ecp_write_key(key, buf, key_len);
+            if (ret != 0) {
+                goto cleanup;
+            }
+
+            status = psa_import_key(&key_attributes, buf, key_len,
+                                    &ssl->handshake->ecdh_psa_privkey);
+            if (status != PSA_SUCCESS) {
+                ret = PSA_TO_MBEDTLS_ERR(status);
+                goto cleanup;
+            }
+
+            ret = 0;
+            break;
+        default:
+            ret = MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;
+    }
+
+cleanup:
+    mbedtls_platform_zeroize(buf, sizeof(buf));
+
+    return ret;
+}
+#elif defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    const mbedtls_pk_context *private_key = mbedtls_ssl_own_key(ssl);
+    if (private_key == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("got no server private key"));
+        return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED;
+    }
+
+    if (!mbedtls_pk_can_do(private_key, MBEDTLS_PK_ECKEY)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("server key not ECDH capable"));
+        return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;
+    }
+
+    if ((ret = mbedtls_ecdh_get_params(&ssl->handshake->ecdh_ctx,
+                                       mbedtls_pk_ec(*mbedtls_ssl_own_key(ssl)),
+                                       MBEDTLS_ECDH_OURS)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecdh_get_params"), ret);
+        return ret;
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
+          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \
+    defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_resume_server_key_exchange(mbedtls_ssl_context *ssl,
+                                          size_t *signature_len)
+{
+    /* Append the signature to ssl->out_msg, leaving 2 bytes for the
+     * signature length which will be added in ssl_write_server_key_exchange
+     * after the call to ssl_prepare_server_key_exchange.
+     * ssl_write_server_key_exchange also takes care of incrementing
+     * ssl->out_msglen. */
+    unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2;
+    size_t sig_max_len = (ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN
+                          - sig_start);
+    int ret = ssl->conf->f_async_resume(ssl,
+                                        sig_start, signature_len, sig_max_len);
+    if (ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) {
+        ssl->handshake->async_in_progress = 0;
+        mbedtls_ssl_set_async_operation_data(ssl, NULL);
+    }
+    MBEDTLS_SSL_DEBUG_RET(2, "ssl_resume_server_key_exchange", ret);
+    return ret;
+}
+#endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) &&
+          defined(MBEDTLS_SSL_ASYNC_PRIVATE) */
+
+/* Prepare the ServerKeyExchange message, up to and including
+ * calculating the signature if any, but excluding formatting the
+ * signature and sending the message. */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl,
+                                           size_t *signature_len)
+{
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED)
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
+    unsigned char *dig_signed = NULL;
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */
+
+    (void) ciphersuite_info; /* unused in some configurations */
+#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
+    (void) signature_len;
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+    size_t out_buf_len = ssl->out_buf_len - (ssl->out_msg - ssl->out_buf);
+#else
+    size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (ssl->out_msg - ssl->out_buf);
+#endif
+#endif
+
+    ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */
+
+    /*
+     *
+     * Part 1: Provide key exchange parameters for chosen ciphersuite.
+     *
+     */
+
+    /*
+     * - ECJPAKE key exchanges
+     */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) {
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        unsigned char *out_p = ssl->out_msg + ssl->out_msglen;
+        unsigned char *end_p = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN -
+                               ssl->out_msglen;
+        size_t output_offset = 0;
+        size_t output_len = 0;
+
+        /*
+         * The first 3 bytes are:
+         * [0] MBEDTLS_ECP_TLS_NAMED_CURVE
+         * [1, 2] elliptic curve's TLS ID
+         *
+         * However since we only support secp256r1 for now, we hardcode its
+         * TLS ID here
+         */
+        uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(
+            MBEDTLS_ECP_DP_SECP256R1);
+        if (tls_id == 0) {
+            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+        }
+        *out_p = MBEDTLS_ECP_TLS_NAMED_CURVE;
+        MBEDTLS_PUT_UINT16_BE(tls_id, out_p, 1);
+        output_offset += 3;
+
+        ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx,
+                                              out_p + output_offset,
+                                              end_p - out_p - output_offset, &output_len,
+                                              MBEDTLS_ECJPAKE_ROUND_TWO);
+        if (ret != 0) {
+            psa_destroy_key(ssl->handshake->psa_pake_password);
+            psa_pake_abort(&ssl->handshake->psa_pake_ctx);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret);
+            return ret;
+        }
+
+        output_offset += output_len;
+        ssl->out_msglen += output_offset;
+#else
+        size_t len = 0;
+
+        ret = mbedtls_ecjpake_write_round_two(
+            &ssl->handshake->ecjpake_ctx,
+            ssl->out_msg + ssl->out_msglen,
+            MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, &len,
+            ssl->conf->f_rng, ssl->conf->p_rng);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_write_round_two", ret);
+            return ret;
+        }
+
+        ssl->out_msglen += len;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    }
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+
+    /*
+     * For (EC)DHE key exchanges with PSK, parameters are prefixed by support
+     * identity hint (RFC 4279, Sec. 3). Until someone needs this feature,
+     * we use empty support identity hints here.
+     **/
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)   || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) {
+        ssl->out_msg[ssl->out_msglen++] = 0x00;
+        ssl->out_msg[ssl->out_msglen++] = 0x00;
+    }
+#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+
+    /*
+     * - DHE key exchanges
+     */
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED)
+    if (mbedtls_ssl_ciphersuite_uses_dhe(ciphersuite_info)) {
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        size_t len = 0;
+
+        if (ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("no DH parameters set"));
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+
+        /*
+         * Ephemeral DH parameters:
+         *
+         * struct {
+         *     opaque dh_p<1..2^16-1>;
+         *     opaque dh_g<1..2^16-1>;
+         *     opaque dh_Ys<1..2^16-1>;
+         * } ServerDHParams;
+         */
+        if ((ret = mbedtls_dhm_set_group(&ssl->handshake->dhm_ctx,
+                                         &ssl->conf->dhm_P,
+                                         &ssl->conf->dhm_G)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_set_group", ret);
+            return ret;
+        }
+
+        if ((ret = mbedtls_dhm_make_params(
+                 &ssl->handshake->dhm_ctx,
+                 (int) mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx),
+                 ssl->out_msg + ssl->out_msglen, &len,
+                 ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_make_params", ret);
+            return ret;
+        }
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
+        dig_signed = ssl->out_msg + ssl->out_msglen;
+#endif
+
+        ssl->out_msglen += len;
+
+        MBEDTLS_SSL_DEBUG_MPI(3, "DHM: X ", &ssl->handshake->dhm_ctx.X);
+        MBEDTLS_SSL_DEBUG_MPI(3, "DHM: P ", &ssl->handshake->dhm_ctx.P);
+        MBEDTLS_SSL_DEBUG_MPI(3, "DHM: G ", &ssl->handshake->dhm_ctx.G);
+        MBEDTLS_SSL_DEBUG_MPI(3, "DHM: GX", &ssl->handshake->dhm_ctx.GX);
+    }
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED */
+
+    /*
+     * - ECDHE key exchanges
+     */
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)
+    if (mbedtls_ssl_ciphersuite_uses_ecdhe(ciphersuite_info)) {
+        /*
+         * Ephemeral ECDH parameters:
+         *
+         * struct {
+         *     ECParameters curve_params;
+         *     ECPoint      public;
+         * } ServerECDHParams;
+         */
+        uint16_t *curr_tls_id = ssl->handshake->curves_tls_id;
+        const uint16_t *group_list = mbedtls_ssl_get_groups(ssl);
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        size_t len = 0;
+
+        /* Match our preference list against the offered curves */
+        if ((group_list == NULL) || (curr_tls_id == NULL)) {
+            return MBEDTLS_ERR_SSL_BAD_CONFIG;
+        }
+        for (; *group_list != 0; group_list++) {
+            for (curr_tls_id = ssl->handshake->curves_tls_id;
+                 *curr_tls_id != 0; curr_tls_id++) {
+                if (*curr_tls_id == *group_list) {
+                    goto curve_matching_done;
+                }
+            }
+        }
+
+curve_matching_done:
+        if (*curr_tls_id == 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("no matching curve for ECDHE"));
+            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+        }
+
+        MBEDTLS_SSL_DEBUG_MSG(2, ("ECDHE curve: %s",
+                                  mbedtls_ssl_get_curve_name_from_tls_id(*curr_tls_id)));
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+        psa_key_attributes_t key_attributes;
+        mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+        uint8_t *p = ssl->out_msg + ssl->out_msglen;
+        const size_t header_size = 4; // curve_type(1), namedcurve(2),
+                                      // data length(1)
+        const size_t data_length_size = 1;
+        psa_ecc_family_t ec_psa_family = 0;
+        size_t ec_bits = 0;
+
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH computation."));
+
+        /* Convert EC's TLS ID to PSA key type. */
+        if (mbedtls_ssl_get_psa_curve_info_from_tls_id(*curr_tls_id,
+                                                       &ec_psa_family,
+                                                       &ec_bits) == PSA_ERROR_NOT_SUPPORTED) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid ecc group parse."));
+            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+        }
+        handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR(ec_psa_family);
+        handshake->ecdh_bits = ec_bits;
+
+        key_attributes = psa_key_attributes_init();
+        psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
+        psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
+        psa_set_key_type(&key_attributes, handshake->ecdh_psa_type);
+        psa_set_key_bits(&key_attributes, handshake->ecdh_bits);
+
+        /*
+         * ECParameters curve_params
+         *
+         * First byte is curve_type, always named_curve
+         */
+        *p++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
+
+        /*
+         * Next two bytes are the namedcurve value
+         */
+        MBEDTLS_PUT_UINT16_BE(*curr_tls_id, p, 0);
+        p += 2;
+
+        /* Generate ECDH private key. */
+        status = psa_generate_key(&key_attributes,
+                                  &handshake->ecdh_psa_privkey);
+        if (status != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_generate_key", ret);
+            return ret;
+        }
+
+        /*
+         * ECPoint  public
+         *
+         * First byte is data length.
+         * It will be filled later. p holds now the data length location.
+         */
+
+        /* Export the public part of the ECDH private key from PSA.
+         * Make one byte space for the length.
+         */
+        unsigned char *own_pubkey = p + data_length_size;
+
+        size_t own_pubkey_max_len = (size_t) (MBEDTLS_SSL_OUT_CONTENT_LEN
+                                              - (own_pubkey - ssl->out_msg));
+
+        status = psa_export_public_key(handshake->ecdh_psa_privkey,
+                                       own_pubkey, own_pubkey_max_len,
+                                       &len);
+        if (status != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_export_public_key", ret);
+            (void) psa_destroy_key(handshake->ecdh_psa_privkey);
+            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+            return ret;
+        }
+
+        /* Store the length of the exported public key. */
+        *p = (uint8_t) len;
+
+        /* Determine full message length. */
+        len += header_size;
+#else
+        mbedtls_ecp_group_id curr_grp_id =
+            mbedtls_ssl_get_ecp_group_id_from_tls_id(*curr_tls_id);
+
+        if ((ret = mbedtls_ecdh_setup(&ssl->handshake->ecdh_ctx,
+                                      curr_grp_id)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecp_group_load", ret);
+            return ret;
+        }
+
+        if ((ret = mbedtls_ecdh_make_params(
+                 &ssl->handshake->ecdh_ctx, &len,
+                 ssl->out_msg + ssl->out_msglen,
+                 MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen,
+                 ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_make_params", ret);
+            return ret;
+        }
+
+        MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,
+                               MBEDTLS_DEBUG_ECDH_Q);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
+        dig_signed = ssl->out_msg + ssl->out_msglen;
+#endif
+
+        ssl->out_msglen += len;
+    }
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */
+
+    /*
+     *
+     * Part 2: For key exchanges involving the server signing the
+     *         exchange parameters, compute and add the signature here.
+     *
+     */
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
+    if (mbedtls_ssl_ciphersuite_uses_server_signature(ciphersuite_info)) {
+        if (dig_signed == NULL) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        }
+
+        size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed;
+        size_t hashlen = 0;
+        unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
+
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+        /*
+         * 2.1: Choose hash algorithm:
+         *      For TLS 1.2, obey signature-hash-algorithm extension
+         *      to choose appropriate hash.
+         */
+
+        mbedtls_pk_type_t sig_alg =
+            mbedtls_ssl_get_ciphersuite_sig_pk_alg(ciphersuite_info);
+
+        unsigned int sig_hash =
+            mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg(
+                ssl, mbedtls_ssl_sig_from_pk_alg(sig_alg));
+
+        mbedtls_md_type_t md_alg = mbedtls_ssl_md_alg_from_hash(sig_hash);
+
+        /*    For TLS 1.2, obey signature-hash-algorithm extension
+         *    (RFC 5246, Sec. 7.4.1.4.1). */
+        if (sig_alg == MBEDTLS_PK_NONE || md_alg == MBEDTLS_MD_NONE) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+            /* (... because we choose a cipher suite
+             *      only if there is a matching hash.) */
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        }
+
+        MBEDTLS_SSL_DEBUG_MSG(3, ("pick hash algorithm %u for signing", (unsigned) md_alg));
+
+        /*
+         * 2.2: Compute the hash to be signed
+         */
+        if (md_alg != MBEDTLS_MD_NONE) {
+            ret = mbedtls_ssl_get_key_exchange_md_tls1_2(ssl, hash, &hashlen,
+                                                         dig_signed,
+                                                         dig_signed_len,
+                                                         md_alg);
+            if (ret != 0) {
+                return ret;
+            }
+        } else {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        }
+
+        MBEDTLS_SSL_DEBUG_BUF(3, "parameters hash", hash, hashlen);
+
+        /*
+         * 2.3: Compute and add the signature
+         */
+        /*
+         * We need to specify signature and hash algorithm explicitly through
+         * a prefix to the signature.
+         *
+         * struct {
+         *    HashAlgorithm hash;
+         *    SignatureAlgorithm signature;
+         * } SignatureAndHashAlgorithm;
+         *
+         * struct {
+         *    SignatureAndHashAlgorithm algorithm;
+         *    opaque signature<0..2^16-1>;
+         * } DigitallySigned;
+         *
+         */
+
+        ssl->out_msg[ssl->out_msglen++] = mbedtls_ssl_hash_from_md_alg(md_alg);
+        ssl->out_msg[ssl->out_msglen++] = mbedtls_ssl_sig_from_pk_alg(sig_alg);
+
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+        if (ssl->conf->f_async_sign_start != NULL) {
+            ret = ssl->conf->f_async_sign_start(ssl,
+                                                mbedtls_ssl_own_cert(ssl),
+                                                md_alg, hash, hashlen);
+            switch (ret) {
+                case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH:
+                    /* act as if f_async_sign was null */
+                    break;
+                case 0:
+                    ssl->handshake->async_in_progress = 1;
+                    return ssl_resume_server_key_exchange(ssl, signature_len);
+                case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
+                    ssl->handshake->async_in_progress = 1;
+                    return MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS;
+                default:
+                    MBEDTLS_SSL_DEBUG_RET(1, "f_async_sign_start", ret);
+                    return ret;
+            }
+        }
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
+        if (mbedtls_ssl_own_key(ssl) == NULL) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("got no private key"));
+            return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED;
+        }
+
+        /* Append the signature to ssl->out_msg, leaving 2 bytes for the
+         * signature length which will be added in ssl_write_server_key_exchange
+         * after the call to ssl_prepare_server_key_exchange.
+         * ssl_write_server_key_exchange also takes care of incrementing
+         * ssl->out_msglen. */
+        if ((ret = mbedtls_pk_sign(mbedtls_ssl_own_key(ssl),
+                                   md_alg, hash, hashlen,
+                                   ssl->out_msg + ssl->out_msglen + 2,
+                                   out_buf_len - ssl->out_msglen - 2,
+                                   signature_len,
+                                   ssl->conf->f_rng,
+                                   ssl->conf->p_rng)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_sign", ret);
+            return ret;
+        }
+    }
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */
+
+    return 0;
+}
+
+/* Prepare the ServerKeyExchange message and send it. For ciphersuites
+ * that do not include a ServerKeyExchange message, do nothing. Either
+ * way, if successful, move on to the next step in the SSL state
+ * machine. */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_server_key_exchange(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t signature_len = 0;
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED)
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write server key exchange"));
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED)
+    /* Extract static ECDH parameters and abort if ServerKeyExchange
+     * is not needed. */
+    if (mbedtls_ssl_ciphersuite_no_pfs(ciphersuite_info)) {
+        /* For suites involving ECDH, extract DH parameters
+         * from certificate at this point. */
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED)
+        if (mbedtls_ssl_ciphersuite_uses_ecdh(ciphersuite_info)) {
+            ret = ssl_get_ecdh_params_from_cert(ssl);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "ssl_get_ecdh_params_from_cert", ret);
+                return ret;
+            }
+        }
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */
+
+        /* Key exchanges not involving ephemeral keys don't use
+         * ServerKeyExchange, so end here. */
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write server key exchange"));
+        ssl->state++;
+        return 0;
+    }
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \
+    defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+    /* If we have already prepared the message and there is an ongoing
+     * signature operation, resume signing. */
+    if (ssl->handshake->async_in_progress != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("resuming signature operation"));
+        ret = ssl_resume_server_key_exchange(ssl, &signature_len);
+    } else
+#endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) &&
+          defined(MBEDTLS_SSL_ASYNC_PRIVATE) */
+    {
+        /* ServerKeyExchange is needed. Prepare the message. */
+        ret = ssl_prepare_server_key_exchange(ssl, &signature_len);
+    }
+
+    if (ret != 0) {
+        /* If we're starting to write a new message, set ssl->out_msglen
+         * to 0. But if we're resuming after an asynchronous message,
+         * out_msglen is the amount of data written so far and mst be
+         * preserved. */
+        if (ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server key exchange (pending)"));
+        } else {
+            ssl->out_msglen = 0;
+        }
+        return ret;
+    }
+
+    /* If there is a signature, write its length.
+     * ssl_prepare_server_key_exchange already wrote the signature
+     * itself at its proper place in the output buffer. */
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
+    if (signature_len != 0) {
+        ssl->out_msg[ssl->out_msglen++] = MBEDTLS_BYTE_1(signature_len);
+        ssl->out_msg[ssl->out_msglen++] = MBEDTLS_BYTE_0(signature_len);
+
+        MBEDTLS_SSL_DEBUG_BUF(3, "my signature",
+                              ssl->out_msg + ssl->out_msglen,
+                              signature_len);
+
+        /* Skip over the already-written signature */
+        ssl->out_msglen += signature_len;
+    }
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */
+
+    /* Add header and send. */
+    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE;
+
+    ssl->state++;
+
+    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret);
+        return ret;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server key exchange"));
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_server_hello_done(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write server hello done"));
+
+    ssl->out_msglen  = 4;
+    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = MBEDTLS_SSL_HS_SERVER_HELLO_DONE;
+
+    ssl->state++;
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        mbedtls_ssl_send_flight_completed(ssl);
+    }
+#endif
+
+    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret);
+        return ret;
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        (ret = mbedtls_ssl_flight_transmit(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret);
+        return ret;
+    }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server hello done"));
+
+    return 0;
+}
+
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
+    defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_client_dh_public(mbedtls_ssl_context *ssl, unsigned char **p,
+                                      const unsigned char *end)
+{
+    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    size_t n;
+
+    /*
+     * Receive G^Y mod P, premaster = (G^Y)^X mod P
+     */
+    if (*p + 2 > end) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message"));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    n = ((*p)[0] << 8) | (*p)[1];
+    *p += 2;
+
+    if (*p + n > end) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message"));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    if ((ret = mbedtls_dhm_read_public(&ssl->handshake->dhm_ctx, *p, n)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_read_public", ret);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    *p += n;
+
+    MBEDTLS_SSL_DEBUG_MPI(3, "DHM: GY", &ssl->handshake->dhm_ctx.GY);
+
+    return ret;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) ||                           \
+    defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
+
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_resume_decrypt_pms(mbedtls_ssl_context *ssl,
+                                  unsigned char *peer_pms,
+                                  size_t *peer_pmslen,
+                                  size_t peer_pmssize)
+{
+    int ret = ssl->conf->f_async_resume(ssl,
+                                        peer_pms, peer_pmslen, peer_pmssize);
+    if (ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) {
+        ssl->handshake->async_in_progress = 0;
+        mbedtls_ssl_set_async_operation_data(ssl, NULL);
+    }
+    MBEDTLS_SSL_DEBUG_RET(2, "ssl_decrypt_encrypted_pms", ret);
+    return ret;
+}
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_decrypt_encrypted_pms(mbedtls_ssl_context *ssl,
+                                     const unsigned char *p,
+                                     const unsigned char *end,
+                                     unsigned char *peer_pms,
+                                     size_t *peer_pmslen,
+                                     size_t peer_pmssize)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    mbedtls_x509_crt *own_cert = mbedtls_ssl_own_cert(ssl);
+    if (own_cert == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("got no local certificate"));
+        return MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE;
+    }
+    mbedtls_pk_context *public_key = &own_cert->pk;
+    mbedtls_pk_context *private_key = mbedtls_ssl_own_key(ssl);
+    size_t len = mbedtls_pk_get_len(public_key);
+
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+    /* If we have already started decoding the message and there is an ongoing
+     * decryption operation, resume signing. */
+    if (ssl->handshake->async_in_progress != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("resuming decryption operation"));
+        return ssl_resume_decrypt_pms(ssl,
+                                      peer_pms, peer_pmslen, peer_pmssize);
+    }
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
+    /*
+     * Prepare to decrypt the premaster using own private RSA key
+     */
+    if (p + 2 > end) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message"));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+    if (*p++ != MBEDTLS_BYTE_1(len) ||
+        *p++ != MBEDTLS_BYTE_0(len)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message"));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    if (p + len != end) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message"));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /*
+     * Decrypt the premaster secret
+     */
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+    if (ssl->conf->f_async_decrypt_start != NULL) {
+        ret = ssl->conf->f_async_decrypt_start(ssl,
+                                               mbedtls_ssl_own_cert(ssl),
+                                               p, len);
+        switch (ret) {
+            case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH:
+                /* act as if f_async_decrypt_start was null */
+                break;
+            case 0:
+                ssl->handshake->async_in_progress = 1;
+                return ssl_resume_decrypt_pms(ssl,
+                                              peer_pms,
+                                              peer_pmslen,
+                                              peer_pmssize);
+            case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
+                ssl->handshake->async_in_progress = 1;
+                return MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS;
+            default:
+                MBEDTLS_SSL_DEBUG_RET(1, "f_async_decrypt_start", ret);
+                return ret;
+        }
+    }
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
+    if (!mbedtls_pk_can_do(private_key, MBEDTLS_PK_RSA)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("got no RSA private key"));
+        return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED;
+    }
+
+    ret = mbedtls_pk_decrypt(private_key, p, len,
+                             peer_pms, peer_pmslen, peer_pmssize,
+                             ssl->conf->f_rng, ssl->conf->p_rng);
+    return ret;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_encrypted_pms(mbedtls_ssl_context *ssl,
+                                   const unsigned char *p,
+                                   const unsigned char *end,
+                                   size_t pms_offset)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *pms = ssl->handshake->premaster + pms_offset;
+    unsigned char ver[2];
+    unsigned char fake_pms[48], peer_pms[48];
+    unsigned char mask;
+    size_t i, peer_pmslen;
+    unsigned int diff;
+
+    /* In case of a failure in decryption, the decryption may write less than
+     * 2 bytes of output, but we always read the first two bytes. It doesn't
+     * matter in the end because diff will be nonzero in that case due to
+     * ret being nonzero, and we only care whether diff is 0.
+     * But do initialize peer_pms and peer_pmslen for robustness anyway. This
+     * also makes memory analyzers happy (don't access uninitialized memory,
+     * even if it's an unsigned char). */
+    peer_pms[0] = peer_pms[1] = ~0;
+    peer_pmslen = 0;
+
+    ret = ssl_decrypt_encrypted_pms(ssl, p, end,
+                                    peer_pms,
+                                    &peer_pmslen,
+                                    sizeof(peer_pms));
+
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+    if (ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) {
+        return ret;
+    }
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+
+    mbedtls_ssl_write_version(ver, ssl->conf->transport,
+                              ssl->session_negotiate->tls_version);
+
+    /* Avoid data-dependent branches while checking for invalid
+     * padding, to protect against timing-based Bleichenbacher-type
+     * attacks. */
+    diff  = (unsigned int) ret;
+    diff |= peer_pmslen ^ 48;
+    diff |= peer_pms[0] ^ ver[0];
+    diff |= peer_pms[1] ^ ver[1];
+
+    /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */
+    mask = mbedtls_ct_uint_mask(diff);
+
+    /*
+     * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding
+     * must not cause the connection to end immediately; instead, send a
+     * bad_record_mac later in the handshake.
+     * To protect against timing-based variants of the attack, we must
+     * not have any branch that depends on whether the decryption was
+     * successful. In particular, always generate the fake premaster secret,
+     * regardless of whether it will ultimately influence the output or not.
+     */
+    ret = ssl->conf->f_rng(ssl->conf->p_rng, fake_pms, sizeof(fake_pms));
+    if (ret != 0) {
+        /* It's ok to abort on an RNG failure, since this does not reveal
+         * anything about the RSA decryption. */
+        return ret;
+    }
+
+#if defined(MBEDTLS_SSL_DEBUG_ALL)
+    if (diff != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message"));
+    }
+#endif
+
+    if (sizeof(ssl->handshake->premaster) < pms_offset ||
+        sizeof(ssl->handshake->premaster) - pms_offset < 48) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+    ssl->handshake->pmslen = 48;
+
+    /* Set pms to either the true or the fake PMS, without
+     * data-dependent branches. */
+    for (i = 0; i < ssl->handshake->pmslen; i++) {
+        pms[i] = (mask & fake_pms[i]) | ((~mask) & peer_pms[i]);
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_client_psk_identity(mbedtls_ssl_context *ssl, unsigned char **p,
+                                         const unsigned char *end)
+{
+    int ret = 0;
+    uint16_t n;
+
+    if (ssl_conf_has_psk_or_cb(ssl->conf) == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("got no pre-shared key"));
+        return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED;
+    }
+
+    /*
+     * Receive client pre-shared key identity name
+     */
+    if (end - *p < 2) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message"));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    n = ((*p)[0] << 8) | (*p)[1];
+    *p += 2;
+
+    if (n == 0 || n > end - *p) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message"));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    if (ssl->conf->f_psk != NULL) {
+        if (ssl->conf->f_psk(ssl->conf->p_psk, ssl, *p, n) != 0) {
+            ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;
+        }
+    } else {
+        /* Identity is not a big secret since clients send it in the clear,
+         * but treat it carefully anyway, just in case */
+        if (n != ssl->conf->psk_identity_len ||
+            mbedtls_ct_memcmp(ssl->conf->psk_identity, *p, n) != 0) {
+            ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;
+        }
+    }
+
+    if (ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) {
+        MBEDTLS_SSL_DEBUG_BUF(3, "Unknown PSK identity", *p, n);
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY);
+        return MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;
+    }
+
+    *p += n;
+
+    return 0;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+    unsigned char *p, *end;
+
+    ciphersuite_info = ssl->handshake->ciphersuite_info;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client key exchange"));
+
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && \
+    (defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED))
+    if ((ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
+         ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA) &&
+        (ssl->handshake->async_in_progress != 0)) {
+        /* We've already read a record and there is an asynchronous
+         * operation in progress to decrypt it. So skip reading the
+         * record. */
+        MBEDTLS_SSL_DEBUG_MSG(3, ("will resume decryption of previously-read record"));
+    } else
+#endif
+    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
+        return ret;
+    }
+
+    p = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl);
+    end = ssl->in_msg + ssl->in_hslen;
+
+    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message"));
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
+
+    if (ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message"));
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
+
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA) {
+        if ((ret = ssl_parse_client_dh_public(ssl, &p, end)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_dh_public"), ret);
+            return ret;
+        }
+
+        if (p != end) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange"));
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+
+        if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx,
+                                           ssl->handshake->premaster,
+                                           MBEDTLS_PREMASTER_SIZE,
+                                           &ssl->handshake->pmslen,
+                                           ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+
+        MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K);
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ||                   \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||                      \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA ||
+        ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA) {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        size_t data_len = (size_t) (*p++);
+        size_t buf_len = (size_t) (end - p);
+        psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+        mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Read the peer's public key."));
+
+        /*
+         * We must have at least two bytes (1 for length, at least 1 for data)
+         */
+        if (buf_len < 2) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid buffer length"));
+            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+        }
+
+        if (data_len < 1 || data_len > buf_len) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid data length"));
+            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+        }
+
+        /* Store peer's ECDH public key. */
+        memcpy(handshake->ecdh_psa_peerkey, p, data_len);
+        handshake->ecdh_psa_peerkey_len = data_len;
+
+        /* Compute ECDH shared secret. */
+        status = psa_raw_key_agreement(
+            PSA_ALG_ECDH, handshake->ecdh_psa_privkey,
+            handshake->ecdh_psa_peerkey, handshake->ecdh_psa_peerkey_len,
+            handshake->premaster, sizeof(handshake->premaster),
+            &handshake->pmslen);
+        if (status != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_raw_key_agreement", ret);
+            if (handshake->ecdh_psa_privkey_is_external == 0) {
+                (void) psa_destroy_key(handshake->ecdh_psa_privkey);
+            }
+            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+            return ret;
+        }
+
+        if (handshake->ecdh_psa_privkey_is_external == 0) {
+            status = psa_destroy_key(handshake->ecdh_psa_privkey);
+
+            if (status != PSA_SUCCESS) {
+                ret = PSA_TO_MBEDTLS_ERR(status);
+                MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret);
+                return ret;
+            }
+        }
+        handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+#else
+        if ((ret = mbedtls_ecdh_read_public(&ssl->handshake->ecdh_ctx,
+                                            p, end - p)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_read_public", ret);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+
+        MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,
+                               MBEDTLS_DEBUG_ECDH_QP);
+
+        if ((ret = mbedtls_ecdh_calc_secret(&ssl->handshake->ecdh_ctx,
+                                            &ssl->handshake->pmslen,
+                                            ssl->handshake->premaster,
+                                            MBEDTLS_MPI_MAX_SIZE,
+                                            ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_calc_secret", ret);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+
+        MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,
+                               MBEDTLS_DEBUG_ECDH_Z);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK) {
+        if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret);
+            return ret;
+        }
+
+        if (p != end) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange"));
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
+        if ((ret = mbedtls_ssl_psk_derive_premaster(ssl,
+                                                    ciphersuite_info->key_exchange)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret);
+            return ret;
+        }
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) {
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+        if (ssl->handshake->async_in_progress != 0) {
+            /* There is an asynchronous operation in progress to
+             * decrypt the encrypted premaster secret, so skip
+             * directly to resuming this operation. */
+            MBEDTLS_SSL_DEBUG_MSG(3, ("PSK identity already parsed"));
+            /* Update p to skip the PSK identity. ssl_parse_encrypted_pms
+             * won't actually use it, but maintain p anyway for robustness. */
+            p += ssl->conf->psk_identity_len + 2;
+        } else
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+        if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret);
+            return ret;
+        }
+
+        if ((ret = ssl_parse_encrypted_pms(ssl, p, end, 2)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_encrypted_pms"), ret);
+            return ret;
+        }
+
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
+        if ((ret = mbedtls_ssl_psk_derive_premaster(ssl,
+                                                    ciphersuite_info->key_exchange)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret);
+            return ret;
+        }
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK) {
+        if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret);
+            return ret;
+        }
+        if ((ret = ssl_parse_client_dh_public(ssl, &p, end)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_dh_public"), ret);
+            return ret;
+        }
+
+        if (p != end) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange"));
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        unsigned char *pms = ssl->handshake->premaster;
+        unsigned char *pms_end = pms + sizeof(ssl->handshake->premaster);
+        size_t pms_len;
+
+        /* Write length only when we know the actual value */
+        if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx,
+                                           pms + 2, pms_end - (pms + 2), &pms_len,
+                                           ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret);
+            return ret;
+        }
+        MBEDTLS_PUT_UINT16_BE(pms_len, pms, 0);
+        pms += 2 + pms_len;
+
+        MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K);
+#else
+        if ((ret = mbedtls_ssl_psk_derive_premaster(ssl,
+                                                    ciphersuite_info->key_exchange)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret);
+            return ret;
+        }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+        psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED;
+        uint8_t ecpoint_len;
+
+        mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+        if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret);
+            psa_destroy_key(handshake->ecdh_psa_privkey);
+            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+            return ret;
+        }
+
+        /* Keep a copy of the peer's public key */
+        if (p >= end) {
+            psa_destroy_key(handshake->ecdh_psa_privkey);
+            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+
+        ecpoint_len = *(p++);
+        if ((size_t) (end - p) < ecpoint_len) {
+            psa_destroy_key(handshake->ecdh_psa_privkey);
+            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+
+        if (ecpoint_len > sizeof(handshake->ecdh_psa_peerkey)) {
+            psa_destroy_key(handshake->ecdh_psa_privkey);
+            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+        }
+
+        memcpy(handshake->ecdh_psa_peerkey, p, ecpoint_len);
+        handshake->ecdh_psa_peerkey_len = ecpoint_len;
+        p += ecpoint_len;
+
+        /* As RFC 5489 section 2, the premaster secret is formed as follows:
+         * - a uint16 containing the length (in octets) of the ECDH computation
+         * - the octet string produced by the ECDH computation
+         * - a uint16 containing the length (in octets) of the PSK
+         * - the PSK itself
+         */
+        unsigned char *psm = ssl->handshake->premaster;
+        const unsigned char * const psm_end =
+            psm + sizeof(ssl->handshake->premaster);
+        /* uint16 to store length (in octets) of the ECDH computation */
+        const size_t zlen_size = 2;
+        size_t zlen = 0;
+
+        /* Compute ECDH shared secret. */
+        status = psa_raw_key_agreement(PSA_ALG_ECDH,
+                                       handshake->ecdh_psa_privkey,
+                                       handshake->ecdh_psa_peerkey,
+                                       handshake->ecdh_psa_peerkey_len,
+                                       psm + zlen_size,
+                                       psm_end - (psm + zlen_size),
+                                       &zlen);
+
+        destruction_status = psa_destroy_key(handshake->ecdh_psa_privkey);
+        handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+
+        if (status != PSA_SUCCESS) {
+            return PSA_TO_MBEDTLS_ERR(status);
+        } else if (destruction_status != PSA_SUCCESS) {
+            return PSA_TO_MBEDTLS_ERR(destruction_status);
+        }
+
+        /* Write the ECDH computation length before the ECDH computation */
+        MBEDTLS_PUT_UINT16_BE(zlen, psm, 0);
+        psm += zlen_size + zlen;
+
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+        if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret);
+            return ret;
+        }
+
+        if ((ret = mbedtls_ecdh_read_public(&ssl->handshake->ecdh_ctx,
+                                            p, end - p)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_read_public", ret);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+
+        MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,
+                               MBEDTLS_DEBUG_ECDH_QP);
+
+        if ((ret = mbedtls_ssl_psk_derive_premaster(ssl,
+                                                    ciphersuite_info->key_exchange)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret);
+            return ret;
+        }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA) {
+        if ((ret = ssl_parse_encrypted_pms(ssl, p, end, 0)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_parse_encrypted_pms_secret"), ret);
+            return ret;
+        }
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+    if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        if ((ret = mbedtls_psa_ecjpake_read_round(
+                 &ssl->handshake->psa_pake_ctx, p, end - p,
+                 MBEDTLS_ECJPAKE_ROUND_TWO)) != 0) {
+            psa_destroy_key(ssl->handshake->psa_pake_password);
+            psa_pake_abort(&ssl->handshake->psa_pake_ctx);
+
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round two", ret);
+            return ret;
+        }
+#else
+        ret = mbedtls_ecjpake_read_round_two(&ssl->handshake->ecjpake_ctx,
+                                             p, end - p);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_read_round_two", ret);
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        }
+
+        ret = mbedtls_ecjpake_derive_secret(&ssl->handshake->ecjpake_ctx,
+                                            ssl->handshake->premaster, 32, &ssl->handshake->pmslen,
+                                            ssl->conf->f_rng, ssl->conf->p_rng);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_derive_secret", ret);
+            return ret;
+        }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+    {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_derive_keys", ret);
+        return ret;
+    }
+
+    ssl->state++;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse client key exchange"));
+
+    return 0;
+}
+
+#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl)
+{
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate verify"));
+
+    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate verify"));
+        ssl->state++;
+        return 0;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+}
+#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    size_t i, sig_len;
+    unsigned char hash[48];
+    unsigned char *hash_start = hash;
+    size_t hashlen;
+    mbedtls_pk_type_t pk_alg;
+    mbedtls_md_type_t md_alg;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+    mbedtls_pk_context *peer_pk;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate verify"));
+
+    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate verify"));
+        ssl->state++;
+        return 0;
+    }
+
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    if (ssl->session_negotiate->peer_cert == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate verify"));
+        ssl->state++;
+        return 0;
+    }
+#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+    if (ssl->session_negotiate->peer_cert_digest == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate verify"));
+        ssl->state++;
+        return 0;
+    }
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
+    /* Read the message without adding it to the checksum */
+    ret = mbedtls_ssl_read_record(ssl, 0 /* no checksum update */);
+    if (0 != ret) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_read_record"), ret);
+        return ret;
+    }
+
+    ssl->state++;
+
+    /* Process the message contents */
+    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ||
+        ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message"));
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
+
+    i = mbedtls_ssl_hs_hdr_len(ssl);
+
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    peer_pk = &ssl->handshake->peer_pubkey;
+#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+    if (ssl->session_negotiate->peer_cert == NULL) {
+        /* Should never happen */
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+    peer_pk = &ssl->session_negotiate->peer_cert->pk;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
+    /*
+     *  struct {
+     *     SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only
+     *     opaque signature<0..2^16-1>;
+     *  } DigitallySigned;
+     */
+    if (i + 2 > ssl->in_hslen) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message"));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /*
+     * Hash
+     */
+    md_alg = mbedtls_ssl_md_alg_from_hash(ssl->in_msg[i]);
+
+    if (md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md(ssl, ssl->in_msg[i])) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("peer not adhering to requested sig_alg"
+                                  " for verify message"));
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+#if !defined(MBEDTLS_MD_SHA1)
+    if (MBEDTLS_MD_SHA1 == md_alg) {
+        hash_start += 16;
+    }
+#endif
+
+    /* Info from md_alg will be used instead */
+    hashlen = 0;
+
+    i++;
+
+    /*
+     * Signature
+     */
+    if ((pk_alg = mbedtls_ssl_pk_alg_from_sig(ssl->in_msg[i]))
+        == MBEDTLS_PK_NONE) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("peer not adhering to requested sig_alg"
+                                  " for verify message"));
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    /*
+     * Check the certificate's key type matches the signature alg
+     */
+    if (!mbedtls_pk_can_do(peer_pk, pk_alg)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("sig_alg doesn't match cert key"));
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    i++;
+
+    if (i + 2 > ssl->in_hslen) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message"));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    sig_len = (ssl->in_msg[i] << 8) | ssl->in_msg[i+1];
+    i += 2;
+
+    if (i + sig_len != ssl->in_hslen) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message"));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /* Calculate hash and verify signature */
+    {
+        size_t dummy_hlen;
+        ret = ssl->handshake->calc_verify(ssl, hash, &dummy_hlen);
+        if (0 != ret) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("calc_verify"), ret);
+            return ret;
+        }
+    }
+
+    if ((ret = mbedtls_pk_verify(peer_pk,
+                                 md_alg, hash_start, hashlen,
+                                 ssl->in_msg + i, sig_len)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_verify", ret);
+        return ret;
+    }
+
+    ret = mbedtls_ssl_update_handshake_status(ssl);
+    if (0 != ret) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_update_handshake_status"), ret);
+        return ret;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate verify"));
+
+    return ret;
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_new_session_ticket(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t tlen;
+    uint32_t lifetime;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write new session ticket"));
+
+    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = MBEDTLS_SSL_HS_NEW_SESSION_TICKET;
+
+    /*
+     * struct {
+     *     uint32 ticket_lifetime_hint;
+     *     opaque ticket<0..2^16-1>;
+     * } NewSessionTicket;
+     *
+     * 4  .  7   ticket_lifetime_hint (0 = unspecified)
+     * 8  .  9   ticket_len (n)
+     * 10 .  9+n ticket content
+     */
+
+    if ((ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket,
+                                         ssl->session_negotiate,
+                                         ssl->out_msg + 10,
+                                         ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN,
+                                         &tlen, &lifetime)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_ticket_write", ret);
+        tlen = 0;
+    }
+
+    MBEDTLS_PUT_UINT32_BE(lifetime, ssl->out_msg, 4);
+    MBEDTLS_PUT_UINT16_BE(tlen, ssl->out_msg, 8);
+    ssl->out_msglen = 10 + tlen;
+
+    /*
+     * Morally equivalent to updating ssl->state, but NewSessionTicket and
+     * ChangeCipherSpec share the same state.
+     */
+    ssl->handshake->new_session_ticket = 0;
+
+    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret);
+        return ret;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write new session ticket"));
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+/*
+ * SSL handshake -- server side -- single step
+ */
+int mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl)
+{
+    int ret = 0;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("server state: %d", ssl->state));
+
+    switch (ssl->state) {
+        case MBEDTLS_SSL_HELLO_REQUEST:
+            ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
+            break;
+
+        /*
+         *  <==   ClientHello
+         */
+        case MBEDTLS_SSL_CLIENT_HELLO:
+            ret = ssl_parse_client_hello(ssl);
+            break;
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+        case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT:
+            return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED;
+#endif
+
+        /*
+         *  ==>   ServerHello
+         *        Certificate
+         *      ( ServerKeyExchange  )
+         *      ( CertificateRequest )
+         *        ServerHelloDone
+         */
+        case MBEDTLS_SSL_SERVER_HELLO:
+            ret = ssl_write_server_hello(ssl);
+            break;
+
+        case MBEDTLS_SSL_SERVER_CERTIFICATE:
+            ret = mbedtls_ssl_write_certificate(ssl);
+            break;
+
+        case MBEDTLS_SSL_SERVER_KEY_EXCHANGE:
+            ret = ssl_write_server_key_exchange(ssl);
+            break;
+
+        case MBEDTLS_SSL_CERTIFICATE_REQUEST:
+            ret = ssl_write_certificate_request(ssl);
+            break;
+
+        case MBEDTLS_SSL_SERVER_HELLO_DONE:
+            ret = ssl_write_server_hello_done(ssl);
+            break;
+
+        /*
+         *  <== ( Certificate/Alert  )
+         *        ClientKeyExchange
+         *      ( CertificateVerify  )
+         *        ChangeCipherSpec
+         *        Finished
+         */
+        case MBEDTLS_SSL_CLIENT_CERTIFICATE:
+            ret = mbedtls_ssl_parse_certificate(ssl);
+            break;
+
+        case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:
+            ret = ssl_parse_client_key_exchange(ssl);
+            break;
+
+        case MBEDTLS_SSL_CERTIFICATE_VERIFY:
+            ret = ssl_parse_certificate_verify(ssl);
+            break;
+
+        case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC:
+            ret = mbedtls_ssl_parse_change_cipher_spec(ssl);
+            break;
+
+        case MBEDTLS_SSL_CLIENT_FINISHED:
+            ret = mbedtls_ssl_parse_finished(ssl);
+            break;
+
+        /*
+         *  ==> ( NewSessionTicket )
+         *        ChangeCipherSpec
+         *        Finished
+         */
+        case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC:
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+            if (ssl->handshake->new_session_ticket != 0) {
+                ret = ssl_write_new_session_ticket(ssl);
+            } else
+#endif
+            ret = mbedtls_ssl_write_change_cipher_spec(ssl);
+            break;
+
+        case MBEDTLS_SSL_SERVER_FINISHED:
+            ret = mbedtls_ssl_write_finished(ssl);
+            break;
+
+        case MBEDTLS_SSL_FLUSH_BUFFERS:
+            MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done"));
+            ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
+            break;
+
+        case MBEDTLS_SSL_HANDSHAKE_WRAPUP:
+            mbedtls_ssl_handshake_wrapup(ssl);
+            break;
+
+        default:
+            MBEDTLS_SSL_DEBUG_MSG(1, ("invalid state %d", ssl->state));
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    return ret;
+}
+
+void mbedtls_ssl_conf_preference_order(mbedtls_ssl_config *conf, int order)
+{
+    conf->respect_cli_pref = order;
+}
+
+#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_TLS1_2 */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls13_client.c b/lib/libmbedtls/mbedtls/library/ssl_tls13_client.c
new file mode 100644
index 0000000..a7feced
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls13_client.c
@@ -0,0 +1,3064 @@
+/*
+ *  TLS 1.3 client-side functions
+ *
+ *  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.
+ *
+ *  This file is part of mbed TLS ( https://tls.mbed.org )
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
+
+#include <string.h>
+
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
+#include "mbedtls/platform.h"
+
+#include "ssl_misc.h"
+#include "ssl_client.h"
+#include "ssl_tls13_keys.h"
+#include "ssl_debug_helpers.h"
+
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_ssl_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+
+/* Write extensions */
+
+/*
+ * ssl_tls13_write_supported_versions_ext():
+ *
+ * struct {
+ *      ProtocolVersion versions<2..254>;
+ * } SupportedVersions;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_supported_versions_ext(mbedtls_ssl_context *ssl,
+                                                  unsigned char *buf,
+                                                  unsigned char *end,
+                                                  size_t *out_len)
+{
+    unsigned char *p = buf;
+    unsigned char versions_len = (ssl->handshake->min_tls_version <=
+                                  MBEDTLS_SSL_VERSION_TLS1_2) ? 4 : 2;
+
+    *out_len = 0;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding supported versions extension"));
+
+    /* Check if we have space to write the extension:
+     * - extension_type         (2 bytes)
+     * - extension_data_length  (2 bytes)
+     * - versions_length        (1 byte )
+     * - versions               (2 or 4 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 5 + versions_len);
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, p, 0);
+    MBEDTLS_PUT_UINT16_BE(versions_len + 1, p, 2);
+    p += 4;
+
+    /* Length of versions */
+    *p++ = versions_len;
+
+    /* Write values of supported versions.
+     * They are defined by the configuration.
+     * Currently, we advertise only TLS 1.3 or both TLS 1.3 and TLS 1.2.
+     */
+    mbedtls_ssl_write_version(p, MBEDTLS_SSL_TRANSPORT_STREAM,
+                              MBEDTLS_SSL_VERSION_TLS1_3);
+    MBEDTLS_SSL_DEBUG_MSG(3, ("supported version: [3:4]"));
+
+
+    if (ssl->handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) {
+        mbedtls_ssl_write_version(p + 2, MBEDTLS_SSL_TRANSPORT_STREAM,
+                                  MBEDTLS_SSL_VERSION_TLS1_2);
+        MBEDTLS_SSL_DEBUG_MSG(3, ("supported version: [3:3]"));
+    }
+
+    *out_len = 5 + versions_len;
+
+    mbedtls_ssl_tls13_set_hs_sent_ext_mask(
+        ssl, MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS);
+
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_supported_versions_ext(mbedtls_ssl_context *ssl,
+                                                  const unsigned char *buf,
+                                                  const unsigned char *end)
+{
+    ((void) ssl);
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, 2);
+    if (mbedtls_ssl_read_version(buf, ssl->conf->transport) !=
+        MBEDTLS_SSL_VERSION_TLS1_3) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("unexpected version"));
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    if (&buf[2] != end) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("supported_versions ext data length incorrect"));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
+                                     MBEDTLS_ERR_SSL_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    return 0;
+}
+
+#if defined(MBEDTLS_SSL_ALPN)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_alpn_ext(mbedtls_ssl_context *ssl,
+                                    const unsigned char *buf, size_t len)
+{
+    const unsigned char *p = buf;
+    const unsigned char *end = buf + len;
+    size_t protocol_name_list_len, protocol_name_len;
+    const unsigned char *protocol_name_list_end;
+
+    /* If we didn't send it, the server shouldn't send it */
+    if (ssl->conf->alpn_list == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    /*
+     * opaque ProtocolName<1..2^8-1>;
+     *
+     * struct {
+     *     ProtocolName protocol_name_list<2..2^16-1>
+     * } ProtocolNameList;
+     *
+     * the "ProtocolNameList" MUST contain exactly one "ProtocolName"
+     */
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    protocol_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, protocol_name_list_len);
+    protocol_name_list_end = p + protocol_name_list_len;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end, 1);
+    protocol_name_len = *p++;
+
+    /* Check that the server chosen protocol was in our list and save it */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end, protocol_name_len);
+    for (const char **alpn = ssl->conf->alpn_list; *alpn != NULL; alpn++) {
+        if (protocol_name_len == strlen(*alpn) &&
+            memcmp(p, *alpn, protocol_name_len) == 0) {
+            ssl->alpn_chosen = *alpn;
+            return 0;
+        }
+    }
+
+    return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+}
+#endif /* MBEDTLS_SSL_ALPN */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_reset_key_share(mbedtls_ssl_context *ssl)
+{
+    uint16_t group_id = ssl->handshake->offered_group_id;
+
+    if (group_id == 0) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+#if defined(MBEDTLS_ECDH_C)
+    if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id)) {
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+        /* Destroy generated private key. */
+        status = psa_destroy_key(ssl->handshake->ecdh_psa_privkey);
+        if (status != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret);
+            return ret;
+        }
+
+        ssl->handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+        return 0;
+    } else
+#endif /* MBEDTLS_ECDH_C */
+    if (0 /* other KEMs? */) {
+        /* Do something */
+    }
+
+    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+}
+
+/*
+ * Functions for writing key_share extension.
+ */
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_get_default_group_id(mbedtls_ssl_context *ssl,
+                                          uint16_t *group_id)
+{
+    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+
+
+#if defined(MBEDTLS_ECDH_C)
+    const uint16_t *group_list = mbedtls_ssl_get_groups(ssl);
+    /* Pick first available ECDHE group compatible with TLS 1.3 */
+    if (group_list == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_CONFIG;
+    }
+
+    for (; *group_list != 0; group_list++) {
+        if ((mbedtls_ssl_get_psa_curve_info_from_tls_id(*group_list,
+                                                        NULL, NULL) == PSA_SUCCESS) &&
+            mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list)) {
+            *group_id = *group_list;
+            return 0;
+        }
+    }
+#else
+    ((void) ssl);
+    ((void) group_id);
+#endif /* MBEDTLS_ECDH_C */
+
+    /*
+     * Add DHE named groups here.
+     * Pick first available DHE group compatible with TLS 1.3
+     */
+
+    return ret;
+}
+
+/*
+ * ssl_tls13_write_key_share_ext
+ *
+ * Structure of key_share extension in ClientHello:
+ *
+ *  struct {
+ *          NamedGroup group;
+ *          opaque key_exchange<1..2^16-1>;
+ *      } KeyShareEntry;
+ *  struct {
+ *          KeyShareEntry client_shares<0..2^16-1>;
+ *      } KeyShareClientHello;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_key_share_ext(mbedtls_ssl_context *ssl,
+                                         unsigned char *buf,
+                                         unsigned char *end,
+                                         size_t *out_len)
+{
+    unsigned char *p = buf;
+    unsigned char *client_shares; /* Start of client_shares */
+    size_t client_shares_len;     /* Length of client_shares */
+    uint16_t group_id;
+    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+
+    *out_len = 0;
+
+    /* Check if we have space for header and length fields:
+     * - extension_type         (2 bytes)
+     * - extension_data_length  (2 bytes)
+     * - client_shares_length   (2 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6);
+    p += 6;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("client hello: adding key share extension"));
+
+    /* HRR could already have requested something else. */
+    group_id = ssl->handshake->offered_group_id;
+    if (!mbedtls_ssl_tls13_named_group_is_ecdhe(group_id) &&
+        !mbedtls_ssl_tls13_named_group_is_dhe(group_id)) {
+        MBEDTLS_SSL_PROC_CHK(ssl_tls13_get_default_group_id(ssl,
+                                                            &group_id));
+    }
+
+    /*
+     * Dispatch to type-specific key generation function.
+     *
+     * So far, we're only supporting ECDHE. With the introduction
+     * of PQC KEMs, we'll want to have multiple branches, one per
+     * type of KEM, and dispatch to the corresponding crypto. And
+     * only one key share entry is allowed.
+     */
+    client_shares = p;
+#if defined(MBEDTLS_ECDH_C)
+    if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id)) {
+        /* Pointer to group */
+        unsigned char *group = p;
+        /* Length of key_exchange */
+        size_t key_exchange_len = 0;
+
+        /* Check there is space for header of KeyShareEntry
+         * - group                  (2 bytes)
+         * - key_exchange_length    (2 bytes)
+         */
+        MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4);
+        p += 4;
+        ret = mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange(
+            ssl, group_id, p, end, &key_exchange_len);
+        p += key_exchange_len;
+        if (ret != 0) {
+            return ret;
+        }
+
+        /* Write group */
+        MBEDTLS_PUT_UINT16_BE(group_id, group, 0);
+        /* Write key_exchange_length */
+        MBEDTLS_PUT_UINT16_BE(key_exchange_len, group, 2);
+    } else
+#endif /* MBEDTLS_ECDH_C */
+    if (0 /* other KEMs? */) {
+        /* Do something */
+    } else {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    /* Length of client_shares */
+    client_shares_len = p - client_shares;
+    if (client_shares_len == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("No key share defined."));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+    /* Write extension_type */
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, buf, 0);
+    /* Write extension_data_length */
+    MBEDTLS_PUT_UINT16_BE(client_shares_len + 2, buf, 2);
+    /* Write client_shares_length */
+    MBEDTLS_PUT_UINT16_BE(client_shares_len, buf, 4);
+
+    /* Update offered_group_id field */
+    ssl->handshake->offered_group_id = group_id;
+
+    /* Output the total length of key_share extension. */
+    *out_len = p - buf;
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, key_share extension", buf, *out_len);
+
+    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE);
+
+cleanup:
+
+    return ret;
+}
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */
+
+/*
+ * ssl_tls13_parse_hrr_key_share_ext()
+ *      Parse key_share extension in Hello Retry Request
+ *
+ * struct {
+ *        NamedGroup selected_group;
+ * } KeyShareHelloRetryRequest;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_hrr_key_share_ext(mbedtls_ssl_context *ssl,
+                                             const unsigned char *buf,
+                                             const unsigned char *end)
+{
+#if defined(MBEDTLS_ECDH_C)
+    const unsigned char *p = buf;
+    int selected_group;
+    int found = 0;
+
+    const uint16_t *group_list = mbedtls_ssl_get_groups(ssl);
+    if (group_list == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_CONFIG;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "key_share extension", p, end - buf);
+
+    /* Read selected_group */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    selected_group = MBEDTLS_GET_UINT16_BE(p, 0);
+    MBEDTLS_SSL_DEBUG_MSG(3, ("selected_group ( %d )", selected_group));
+
+    /* Upon receipt of this extension in a HelloRetryRequest, the client
+     * MUST first verify that the selected_group field corresponds to a
+     * group which was provided in the "supported_groups" extension in the
+     * original ClientHello.
+     * The supported_group was based on the info in ssl->conf->group_list.
+     *
+     * If the server provided a key share that was not sent in the ClientHello
+     * then the client MUST abort the handshake with an "illegal_parameter" alert.
+     */
+    for (; *group_list != 0; group_list++) {
+        if ((mbedtls_ssl_get_psa_curve_info_from_tls_id(*group_list,
+                                                        NULL, NULL) == PSA_ERROR_NOT_SUPPORTED) ||
+            *group_list != selected_group) {
+            continue;
+        }
+
+        /* We found a match */
+        found = 1;
+        break;
+    }
+
+    /* Client MUST verify that the selected_group field does not
+     * correspond to a group which was provided in the "key_share"
+     * extension in the original ClientHello. If the server sent an
+     * HRR message with a key share already provided in the
+     * ClientHello then the client MUST abort the handshake with
+     * an "illegal_parameter" alert.
+     */
+    if (found == 0 || selected_group == ssl->handshake->offered_group_id) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid key share in HRR"));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(
+            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+            MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    /* Remember server's preference for next ClientHello */
+    ssl->handshake->offered_group_id = selected_group;
+
+    return 0;
+#else
+    (void) ssl;
+    (void) buf;
+    (void) end;
+    return MBEDTLS_ERR_SSL_BAD_CONFIG;
+#endif
+}
+
+/*
+ * ssl_tls13_parse_key_share_ext()
+ *      Parse key_share extension in Server Hello
+ *
+ * struct {
+ *        KeyShareEntry server_share;
+ * } KeyShareServerHello;
+ * struct {
+ *        NamedGroup group;
+ *        opaque key_exchange<1..2^16-1>;
+ * } KeyShareEntry;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_key_share_ext(mbedtls_ssl_context *ssl,
+                                         const unsigned char *buf,
+                                         const unsigned char *end)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const unsigned char *p = buf;
+    uint16_t group, offered_group;
+
+    /* ...
+     * NamedGroup group; (2 bytes)
+     * ...
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    group = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+
+    /* Check that the chosen group matches the one we offered. */
+    offered_group = ssl->handshake->offered_group_id;
+    if (offered_group != group) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("Invalid server key share, our group %u, their group %u",
+                               (unsigned) offered_group, (unsigned) group));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
+                                     MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+#if defined(MBEDTLS_ECDH_C)
+    if (mbedtls_ssl_tls13_named_group_is_ecdhe(group)) {
+        if (mbedtls_ssl_get_psa_curve_info_from_tls_id(group, NULL, NULL)
+            == PSA_ERROR_NOT_SUPPORTED) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid TLS curve group id"));
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        }
+
+        MBEDTLS_SSL_DEBUG_MSG(2, ("ECDH curve: %s",
+                                  mbedtls_ssl_get_curve_name_from_tls_id(group)));
+
+        ret = mbedtls_ssl_tls13_read_public_ecdhe_share(ssl, p, end - p);
+        if (ret != 0) {
+            return ret;
+        }
+    } else
+#endif /* MBEDTLS_ECDH_C */
+    if (0 /* other KEMs? */) {
+        /* Do something */
+    } else {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    return ret;
+}
+
+/*
+ * ssl_tls13_parse_cookie_ext()
+ *      Parse cookie extension in Hello Retry Request
+ *
+ * struct {
+ *        opaque cookie<1..2^16-1>;
+ * } Cookie;
+ *
+ * When sending a HelloRetryRequest, the server MAY provide a "cookie"
+ * extension to the client (this is an exception to the usual rule that
+ * the only extensions that may be sent are those that appear in the
+ * ClientHello).  When sending the new ClientHello, the client MUST copy
+ * the contents of the extension received in the HelloRetryRequest into
+ * a "cookie" extension in the new ClientHello.  Clients MUST NOT use
+ * cookies in their initial ClientHello in subsequent connections.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_cookie_ext(mbedtls_ssl_context *ssl,
+                                      const unsigned char *buf,
+                                      const unsigned char *end)
+{
+    uint16_t cookie_len;
+    const unsigned char *p = buf;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+    /* Retrieve length field of cookie */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    cookie_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, cookie_len);
+    MBEDTLS_SSL_DEBUG_BUF(3, "cookie extension", p, cookie_len);
+
+    mbedtls_free(handshake->cookie);
+    handshake->cookie_len = 0;
+    handshake->cookie = mbedtls_calloc(1, cookie_len);
+    if (handshake->cookie == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("alloc failed ( %ud bytes )",
+                               cookie_len));
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+    }
+
+    memcpy(handshake->cookie, p, cookie_len);
+    handshake->cookie_len = cookie_len;
+
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_cookie_ext(mbedtls_ssl_context *ssl,
+                                      unsigned char *buf,
+                                      unsigned char *end,
+                                      size_t *out_len)
+{
+    unsigned char *p = buf;
+    *out_len = 0;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+    if (handshake->cookie == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("no cookie to send; skip extension"));
+        return 0;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, cookie",
+                          handshake->cookie,
+                          handshake->cookie_len);
+
+    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->cookie_len + 2, p, 2);
+    MBEDTLS_PUT_UINT16_BE(handshake->cookie_len, p, 4);
+    p += 6;
+
+    /* Cookie */
+    memcpy(p, handshake->cookie, handshake->cookie_len);
+
+    *out_len = handshake->cookie_len + 6;
+
+    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_COOKIE);
+
+    return 0;
+}
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+/*
+ * ssl_tls13_write_psk_key_exchange_modes_ext() structure:
+ *
+ * enum { psk_ke( 0 ), psk_dhe_ke( 1 ), ( 255 ) } PskKeyExchangeMode;
+ *
+ * struct {
+ *     PskKeyExchangeMode ke_modes<1..255>;
+ * } PskKeyExchangeModes;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_psk_key_exchange_modes_ext(mbedtls_ssl_context *ssl,
+                                                      unsigned char *buf,
+                                                      unsigned char *end,
+                                                      size_t *out_len)
+{
+    unsigned char *p = buf;
+    int ke_modes_len = 0;
+
+    ((void) ke_modes_len);
+    *out_len = 0;
+
+    /* Skip writing extension if no PSK key exchange mode
+     * is enabled in the config.
+     */
+    if (!mbedtls_ssl_conf_tls13_some_psk_enabled(ssl)) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("skip psk_key_exchange_modes extension"));
+        return 0;
+    }
+
+    /* Require 7 bytes of data, otherwise fail,
+     * even if extension might be shorter.
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 7);
+    MBEDTLS_SSL_DEBUG_MSG(
+        3, ("client hello, adding psk_key_exchange_modes extension"));
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES, p, 0);
+
+    /* Skip extension length (2 bytes) and
+     * ke_modes length (1 byte) for now.
+     */
+    p += 5;
+
+    if (mbedtls_ssl_conf_tls13_psk_ephemeral_enabled(ssl)) {
+        *p++ = MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE;
+        ke_modes_len++;
+
+        MBEDTLS_SSL_DEBUG_MSG(4, ("Adding PSK-ECDHE key exchange mode"));
+    }
+
+    if (mbedtls_ssl_conf_tls13_psk_enabled(ssl)) {
+        *p++ = MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE;
+        ke_modes_len++;
+
+        MBEDTLS_SSL_DEBUG_MSG(4, ("Adding pure PSK key exchange mode"));
+    }
+
+    /* Now write the extension and ke_modes length */
+    MBEDTLS_PUT_UINT16_BE(ke_modes_len + 1, buf, 2);
+    buf[4] = ke_modes_len;
+
+    *out_len = p - buf;
+
+    mbedtls_ssl_tls13_set_hs_sent_ext_mask(
+        ssl, MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES);
+
+    return 0;
+}
+
+static psa_algorithm_t ssl_tls13_get_ciphersuite_hash_alg(int ciphersuite)
+{
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info = NULL;
+    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite);
+
+    if (ciphersuite_info != NULL) {
+        return mbedtls_psa_translate_md(ciphersuite_info->mac);
+    }
+
+    return PSA_ALG_NONE;
+}
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+static int ssl_tls13_has_configured_ticket(mbedtls_ssl_context *ssl)
+{
+    mbedtls_ssl_session *session = ssl->session_negotiate;
+    return ssl->handshake->resume &&
+           session != NULL && session->ticket != NULL &&
+           mbedtls_ssl_conf_tls13_check_kex_modes(
+        ssl, mbedtls_ssl_session_get_ticket_flags(
+            session, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL));
+}
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+static int ssl_tls13_early_data_has_valid_ticket(mbedtls_ssl_context *ssl)
+{
+    mbedtls_ssl_session *session = ssl->session_negotiate;
+    return ssl->handshake->resume &&
+           session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 &&
+           (session->ticket_flags &
+            MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA) &&
+           mbedtls_ssl_tls13_cipher_suite_is_offered(
+        ssl, session->ciphersuite);
+}
+#endif
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_ticket_get_identity(mbedtls_ssl_context *ssl,
+                                         psa_algorithm_t *hash_alg,
+                                         const unsigned char **identity,
+                                         size_t *identity_len)
+{
+    mbedtls_ssl_session *session = ssl->session_negotiate;
+
+    if (!ssl_tls13_has_configured_ticket(ssl)) {
+        return -1;
+    }
+
+    *hash_alg = ssl_tls13_get_ciphersuite_hash_alg(session->ciphersuite);
+    *identity = session->ticket;
+    *identity_len = session->ticket_len;
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_ticket_get_psk(mbedtls_ssl_context *ssl,
+                                    psa_algorithm_t *hash_alg,
+                                    const unsigned char **psk,
+                                    size_t *psk_len)
+{
+
+    mbedtls_ssl_session *session = ssl->session_negotiate;
+
+    if (!ssl_tls13_has_configured_ticket(ssl)) {
+        return -1;
+    }
+
+    *hash_alg = ssl_tls13_get_ciphersuite_hash_alg(session->ciphersuite);
+    *psk = session->resumption_key;
+    *psk_len = session->resumption_key_len;
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_psk_get_identity(mbedtls_ssl_context *ssl,
+                                      psa_algorithm_t *hash_alg,
+                                      const unsigned char **identity,
+                                      size_t *identity_len)
+{
+
+    if (!mbedtls_ssl_conf_has_static_psk(ssl->conf)) {
+        return -1;
+    }
+
+    *hash_alg = PSA_ALG_SHA_256;
+    *identity = ssl->conf->psk_identity;
+    *identity_len = ssl->conf->psk_identity_len;
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_psk_get_psk(mbedtls_ssl_context *ssl,
+                                 psa_algorithm_t *hash_alg,
+                                 const unsigned char **psk,
+                                 size_t *psk_len)
+{
+
+    if (!mbedtls_ssl_conf_has_static_psk(ssl->conf)) {
+        return -1;
+    }
+
+    *hash_alg = PSA_ALG_SHA_256;
+    *psk = ssl->conf->psk;
+    *psk_len = ssl->conf->psk_len;
+    return 0;
+}
+
+static int ssl_tls13_get_configured_psk_count(mbedtls_ssl_context *ssl)
+{
+    int configured_psk_count = 0;
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    if (ssl_tls13_has_configured_ticket(ssl)) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("Ticket is configured"));
+        configured_psk_count++;
+    }
+#endif
+    if (mbedtls_ssl_conf_has_static_psk(ssl->conf)) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("PSK is configured"));
+        configured_psk_count++;
+    }
+    return configured_psk_count;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_identity(mbedtls_ssl_context *ssl,
+                                    unsigned char *buf,
+                                    unsigned char *end,
+                                    const unsigned char *identity,
+                                    size_t identity_len,
+                                    uint32_t obfuscated_ticket_age,
+                                    size_t *out_len)
+{
+    ((void) ssl);
+    *out_len = 0;
+
+    /*
+     * - identity_len           (2 bytes)
+     * - identity               (psk_identity_len bytes)
+     * - obfuscated_ticket_age  (4 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6 + identity_len);
+
+    MBEDTLS_PUT_UINT16_BE(identity_len, buf, 0);
+    memcpy(buf + 2, identity, identity_len);
+    MBEDTLS_PUT_UINT32_BE(obfuscated_ticket_age, buf, 2 + identity_len);
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "write identity", buf, 6 + identity_len);
+
+    *out_len = 6 + identity_len;
+
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_binder(mbedtls_ssl_context *ssl,
+                                  unsigned char *buf,
+                                  unsigned char *end,
+                                  int psk_type,
+                                  psa_algorithm_t hash_alg,
+                                  const unsigned char *psk,
+                                  size_t psk_len,
+                                  size_t *out_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char binder_len;
+    unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+    size_t transcript_len = 0;
+
+    *out_len = 0;
+
+    binder_len = PSA_HASH_LENGTH(hash_alg);
+
+    /*
+     * - binder_len           (1 bytes)
+     * - binder               (binder_len bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 1 + binder_len);
+
+    buf[0] = binder_len;
+
+    /* Get current state of handshake transcript. */
+    ret = mbedtls_ssl_get_handshake_transcript(
+        ssl, mbedtls_hash_info_md_from_psa(hash_alg),
+        transcript, sizeof(transcript), &transcript_len);
+    if (ret != 0) {
+        return ret;
+    }
+
+    ret = mbedtls_ssl_tls13_create_psk_binder(ssl, hash_alg,
+                                              psk, psk_len, psk_type,
+                                              transcript, buf + 1);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_create_psk_binder", ret);
+        return ret;
+    }
+    MBEDTLS_SSL_DEBUG_BUF(4, "write binder", buf, 1 + binder_len);
+
+    *out_len = 1 + binder_len;
+
+    return 0;
+}
+
+/*
+ * mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext() structure:
+ *
+ * struct {
+ *   opaque identity<1..2^16-1>;
+ *   uint32 obfuscated_ticket_age;
+ * } PskIdentity;
+ *
+ * opaque PskBinderEntry<32..255>;
+ *
+ * struct {
+ *   PskIdentity identities<7..2^16-1>;
+ *   PskBinderEntry binders<33..2^16-1>;
+ * } OfferedPsks;
+ *
+ * struct {
+ *   select (Handshake.msg_type) {
+ *      case client_hello: OfferedPsks;
+ *      ...
+ *   };
+ * } PreSharedKeyExtension;
+ *
+ */
+int mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext(
+    mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end,
+    size_t *out_len, size_t *binders_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    int configured_psk_count = 0;
+    unsigned char *p = buf;
+    psa_algorithm_t hash_alg = PSA_ALG_NONE;
+    const unsigned char *identity;
+    size_t identity_len;
+    size_t l_binders_len = 0;
+    size_t output_len;
+
+    *out_len = 0;
+    *binders_len = 0;
+
+    /* Check if we have any PSKs to offer. If no, skip pre_shared_key */
+    configured_psk_count = ssl_tls13_get_configured_psk_count(ssl);
+    if (configured_psk_count == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("skip pre_shared_key extensions"));
+        return 0;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(4, ("Pre-configured PSK number = %d",
+                              configured_psk_count));
+
+    /* Check if we have space to write the extension, binders included.
+     * - extension_type         (2 bytes)
+     * - extension_data_len     (2 bytes)
+     * - identities_len         (2 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6);
+    p += 6;
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    if (ssl_tls13_ticket_get_identity(
+            ssl, &hash_alg, &identity, &identity_len) == 0) {
+#if defined(MBEDTLS_HAVE_TIME)
+        mbedtls_time_t now = mbedtls_time(NULL);
+        mbedtls_ssl_session *session = ssl->session_negotiate;
+        uint32_t obfuscated_ticket_age =
+            (uint32_t) (now - session->ticket_received);
+
+        /*
+         * The ticket timestamp is in seconds but the ticket age is in
+         * milliseconds. If the ticket was received at the end of a second and
+         * re-used here just at the beginning of the next second, the computed
+         * age `now - session->ticket_received` is equal to 1s thus 1000 ms
+         * while the actual age could be just a few milliseconds or tens of
+         * milliseconds. If the server has more accurate ticket timestamps
+         * (typically timestamps in milliseconds), as part of the processing of
+         * the ClientHello, it may compute a ticket lifetime smaller than the
+         * one computed here and potentially reject the ticket. To avoid that,
+         * remove one second to the ticket age if possible.
+         */
+        if (obfuscated_ticket_age > 0) {
+            obfuscated_ticket_age -= 1;
+        }
+
+        obfuscated_ticket_age *= 1000;
+        obfuscated_ticket_age += session->ticket_age_add;
+
+        ret = ssl_tls13_write_identity(ssl, p, end,
+                                       identity, identity_len,
+                                       obfuscated_ticket_age,
+                                       &output_len);
+#else
+        ret = ssl_tls13_write_identity(ssl, p, end, identity, identity_len,
+                                       0, &output_len);
+#endif /* MBEDTLS_HAVE_TIME */
+        if (ret != 0) {
+            return ret;
+        }
+
+        p += output_len;
+        l_binders_len += 1 + PSA_HASH_LENGTH(hash_alg);
+    }
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+    if (ssl_tls13_psk_get_identity(
+            ssl, &hash_alg, &identity, &identity_len) == 0) {
+
+        ret = ssl_tls13_write_identity(ssl, p, end, identity, identity_len, 0,
+                                       &output_len);
+        if (ret != 0) {
+            return ret;
+        }
+
+        p += output_len;
+        l_binders_len += 1 + PSA_HASH_LENGTH(hash_alg);
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3,
+                          ("client hello, adding pre_shared_key extension, "
+                           "omitting PSK binder list"));
+
+    /* Take into account the two bytes for the length of the binders. */
+    l_binders_len += 2;
+    /* Check if there is enough space for binders */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, l_binders_len);
+
+    /*
+     * - extension_type         (2 bytes)
+     * - extension_data_len     (2 bytes)
+     * - identities_len         (2 bytes)
+     */
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PRE_SHARED_KEY, buf, 0);
+    MBEDTLS_PUT_UINT16_BE(p - buf - 4 + l_binders_len, buf, 2);
+    MBEDTLS_PUT_UINT16_BE(p - buf - 6, buf, 4);
+
+    *out_len = (p - buf) + l_binders_len;
+    *binders_len = l_binders_len;
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "pre_shared_key identities", buf, p - buf);
+
+    return 0;
+}
+
+int mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext(
+    mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *p = buf;
+    psa_algorithm_t hash_alg = PSA_ALG_NONE;
+    const unsigned char *psk;
+    size_t psk_len;
+    size_t output_len;
+
+    /* Check if we have space to write binders_len.
+     * - binders_len         (2 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);
+    p += 2;
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    if (ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len) == 0) {
+
+        ret = ssl_tls13_write_binder(ssl, p, end,
+                                     MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION,
+                                     hash_alg, psk, psk_len,
+                                     &output_len);
+        if (ret != 0) {
+            return ret;
+        }
+        p += output_len;
+    }
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+    if (ssl_tls13_psk_get_psk(ssl, &hash_alg, &psk, &psk_len) == 0) {
+
+        ret = ssl_tls13_write_binder(ssl, p, end,
+                                     MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL,
+                                     hash_alg, psk, psk_len,
+                                     &output_len);
+        if (ret != 0) {
+            return ret;
+        }
+        p += output_len;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding PSK binder list."));
+
+    /*
+     * - binders_len         (2 bytes)
+     */
+    MBEDTLS_PUT_UINT16_BE(p - buf - 2, buf, 0);
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "pre_shared_key binders", buf, p - buf);
+
+    mbedtls_ssl_tls13_set_hs_sent_ext_mask(
+        ssl, MBEDTLS_TLS_EXT_PRE_SHARED_KEY);
+
+    return 0;
+}
+
+/*
+ * struct {
+ *   opaque identity<1..2^16-1>;
+ *   uint32 obfuscated_ticket_age;
+ * } PskIdentity;
+ *
+ * opaque PskBinderEntry<32..255>;
+ *
+ * struct {
+ *
+ *   select (Handshake.msg_type) {
+ *         ...
+ *         case server_hello: uint16 selected_identity;
+ *   };
+ *
+ * } PreSharedKeyExtension;
+ *
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_server_pre_shared_key_ext(mbedtls_ssl_context *ssl,
+                                                     const unsigned char *buf,
+                                                     const unsigned char *end)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    int selected_identity;
+    const unsigned char *psk;
+    size_t psk_len;
+    psa_algorithm_t hash_alg;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, 2);
+    selected_identity = MBEDTLS_GET_UINT16_BE(buf, 0);
+    ssl->handshake->selected_identity = (uint16_t) selected_identity;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("selected_identity = %d", selected_identity));
+
+    if (selected_identity >= ssl_tls13_get_configured_psk_count(ssl)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid PSK identity."));
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    if (selected_identity == 0 && ssl_tls13_has_configured_ticket(ssl)) {
+        ret = ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len);
+    } else
+#endif
+    if (mbedtls_ssl_conf_has_static_psk(ssl->conf)) {
+        ret = ssl_tls13_psk_get_psk(ssl, &hash_alg, &psk, &psk_len);
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+    if (ret != 0) {
+        return ret;
+    }
+
+    if (mbedtls_psa_translate_md(ssl->handshake->ciphersuite_info->mac)
+        != hash_alg) {
+        MBEDTLS_SSL_DEBUG_MSG(
+            1, ("Invalid ciphersuite for external psk."));
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    ret = mbedtls_ssl_set_hs_psk(ssl, psk, psk_len);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret);
+        return ret;
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
+
+int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl,
+                                              unsigned char *buf,
+                                              unsigned char *end,
+                                              size_t *out_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *p = buf;
+    size_t ext_len;
+
+    *out_len = 0;
+
+    /* Write supported_versions extension
+     *
+     * Supported Versions Extension is mandatory with TLS 1.3.
+     */
+    ret = ssl_tls13_write_supported_versions_ext(ssl, p, end, &ext_len);
+    if (ret != 0) {
+        return ret;
+    }
+    p += ext_len;
+
+    /* Echo the cookie if the server provided one in its preceding
+     * HelloRetryRequest message.
+     */
+    ret = ssl_tls13_write_cookie_ext(ssl, p, end, &ext_len);
+    if (ret != 0) {
+        return ret;
+    }
+    p += ext_len;
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
+    if (mbedtls_ssl_conf_tls13_some_ephemeral_enabled(ssl)) {
+        ret = ssl_tls13_write_key_share_ext(ssl, p, end, &ext_len);
+        if (ret != 0) {
+            return ret;
+        }
+        p += ext_len;
+    }
+#endif
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    if (mbedtls_ssl_conf_tls13_some_psk_enabled(ssl) &&
+        ssl_tls13_early_data_has_valid_ticket(ssl) &&
+        ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) {
+        ret = mbedtls_ssl_tls13_write_early_data_ext(ssl, p, end, &ext_len);
+        if (ret != 0) {
+            return ret;
+        }
+        p += ext_len;
+
+        /* Initializes the status to `rejected`. It will be updated to
+         * `accepted` if the EncryptedExtension message contain an early data
+         * indication extension.
+         */
+        ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write early_data extension"));
+        ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT;
+    }
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    /* For PSK-based key exchange we need the pre_shared_key extension
+     * and the psk_key_exchange_modes extension.
+     *
+     * The pre_shared_key extension MUST be the last extension in the
+     * ClientHello. Servers MUST check that it is the last extension and
+     * otherwise fail the handshake with an "illegal_parameter" alert.
+     *
+     * Add the psk_key_exchange_modes extension.
+     */
+    ret = ssl_tls13_write_psk_key_exchange_modes_ext(ssl, p, end, &ext_len);
+    if (ret != 0) {
+        return ret;
+    }
+    p += ext_len;
+#endif
+
+    *out_len = p - buf;
+
+    return 0;
+}
+
+int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl)
+{
+    ((void) ssl);
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    psa_algorithm_t hash_alg = PSA_ALG_NONE;
+    const unsigned char *psk;
+    size_t psk_len;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+
+    if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED) {
+#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+        mbedtls_ssl_handshake_set_state(
+            ssl, MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO);
+#endif
+        MBEDTLS_SSL_DEBUG_MSG(
+            1, ("Set hs psk for early data when writing the first psk"));
+
+        ret = ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(
+                1, "ssl_tls13_ticket_get_psk", ret);
+            return ret;
+        }
+
+        ret = mbedtls_ssl_set_hs_psk(ssl, psk, psk_len);
+        if (ret  != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret);
+            return ret;
+        }
+
+        /*
+         * Early data are going to be encrypted using the ciphersuite
+         * associated with the pre-shared key used for the handshake.
+         * Note that if the server rejects early data, the handshake
+         * based on the pre-shared key may complete successfully
+         * with a selected ciphersuite different from the ciphersuite
+         * associated with the pre-shared key. Only the hashes of the
+         * two ciphersuites have to be the same. In that case, the
+         * encrypted handshake data and application data are
+         * encrypted using a different ciphersuite than the one used for
+         * the rejected early data.
+         */
+        ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(
+            ssl->session_negotiate->ciphersuite);
+        ssl->handshake->ciphersuite_info = ciphersuite_info;
+
+        /* Enable psk and psk_ephemeral to make stage early happy */
+        ssl->handshake->key_exchange_mode =
+            MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL;
+
+        /* Start the TLS 1.3 key schedule:
+         *     Set the PSK and derive early secret.
+         */
+        ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(
+                1, "mbedtls_ssl_tls13_key_schedule_stage_early", ret);
+            return ret;
+        }
+
+        /* Derive early data key material */
+        ret = mbedtls_ssl_tls13_compute_early_transform(ssl);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(
+                1, "mbedtls_ssl_tls13_compute_early_transform", ret);
+            return ret;
+        }
+
+    }
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+    return 0;
+}
+/*
+ * Functions for parsing and processing Server Hello
+ */
+
+/**
+ * \brief Detect if the ServerHello contains a supported_versions extension
+ *        or not.
+ *
+ * \param[in] ssl  SSL context
+ * \param[in] buf  Buffer containing the ServerHello message
+ * \param[in] end  End of the buffer containing the ServerHello message
+ *
+ * \return 0 if the ServerHello does not contain a supported_versions extension
+ * \return 1 if the ServerHello contains a supported_versions extension
+ * \return A negative value if an error occurred while parsing the ServerHello.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_is_supported_versions_ext_present(
+    mbedtls_ssl_context *ssl,
+    const unsigned char *buf,
+    const unsigned char *end)
+{
+    const unsigned char *p = buf;
+    size_t legacy_session_id_echo_len;
+    size_t extensions_len;
+    const unsigned char *extensions_end;
+
+    /*
+     * Check there is enough data to access the legacy_session_id_echo vector
+     * length:
+     * - legacy_version                 2 bytes
+     * - random                         MBEDTLS_SERVER_HELLO_RANDOM_LEN bytes
+     * - legacy_session_id_echo length  1 byte
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 3);
+    p += MBEDTLS_SERVER_HELLO_RANDOM_LEN + 2;
+    legacy_session_id_echo_len = *p;
+
+    /*
+     * Jump to the extensions, jumping over:
+     * - legacy_session_id_echo     (legacy_session_id_echo_len + 1) bytes
+     * - cipher_suite               2 bytes
+     * - legacy_compression_method  1 byte
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_echo_len + 4);
+    p += legacy_session_id_echo_len + 4;
+
+    /* Case of no extension */
+    if (p == end) {
+        return 0;
+    }
+
+    /* ...
+     * Extension extensions<6..2^16-1>;
+     * ...
+     * struct {
+     *      ExtensionType extension_type; (2 bytes)
+     *      opaque extension_data<0..2^16-1>;
+     * } Extension;
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+
+    /* Check extensions do not go beyond the buffer of data. */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len);
+    extensions_end = p + extensions_len;
+
+    while (p < extensions_end) {
+        unsigned int extension_type;
+        size_t extension_data_len;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4);
+        extension_type = MBEDTLS_GET_UINT16_BE(p, 0);
+        extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);
+        p += 4;
+
+        if (extension_type == MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS) {
+            return 1;
+        }
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len);
+        p += extension_data_len;
+    }
+
+    return 0;
+}
+
+/* Returns a negative value on failure, and otherwise
+ * - 1 if the last eight bytes of the ServerHello random bytes indicate that
+ *     the server is TLS 1.3 capable but negotiating TLS 1.2 or below.
+ * - 0 otherwise
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_is_downgrade_negotiation(mbedtls_ssl_context *ssl,
+                                              const unsigned char *buf,
+                                              const unsigned char *end)
+{
+    /* First seven bytes of the magic downgrade strings, see RFC 8446 4.1.3 */
+    static const unsigned char magic_downgrade_string[] =
+    { 0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44 };
+    const unsigned char *last_eight_bytes_of_random;
+    unsigned char last_byte_of_random;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 2);
+    last_eight_bytes_of_random = buf + 2 + MBEDTLS_SERVER_HELLO_RANDOM_LEN - 8;
+
+    if (memcmp(last_eight_bytes_of_random,
+               magic_downgrade_string,
+               sizeof(magic_downgrade_string)) == 0) {
+        last_byte_of_random = last_eight_bytes_of_random[7];
+        return last_byte_of_random == 0 ||
+               last_byte_of_random == 1;
+    }
+
+    return 0;
+}
+
+/* Returns a negative value on failure, and otherwise
+ * - SSL_SERVER_HELLO or
+ * - SSL_SERVER_HELLO_HRR
+ * to indicate which message is expected and to be parsed next.
+ */
+#define SSL_SERVER_HELLO 0
+#define SSL_SERVER_HELLO_HRR 1
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_server_hello_is_hrr(mbedtls_ssl_context *ssl,
+                                   const unsigned char *buf,
+                                   const unsigned char *end)
+{
+
+    /* Check whether this message is a HelloRetryRequest ( HRR ) message.
+     *
+     * Server Hello and HRR are only distinguished by Random set to the
+     * special value of the SHA-256 of "HelloRetryRequest".
+     *
+     * struct {
+     *    ProtocolVersion legacy_version = 0x0303;
+     *    Random random;
+     *    opaque legacy_session_id_echo<0..32>;
+     *    CipherSuite cipher_suite;
+     *    uint8 legacy_compression_method = 0;
+     *    Extension extensions<6..2^16-1>;
+     * } ServerHello;
+     *
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end,
+                                 2 + sizeof(mbedtls_ssl_tls13_hello_retry_request_magic));
+
+    if (memcmp(buf + 2, mbedtls_ssl_tls13_hello_retry_request_magic,
+               sizeof(mbedtls_ssl_tls13_hello_retry_request_magic)) == 0) {
+        return SSL_SERVER_HELLO_HRR;
+    }
+
+    return SSL_SERVER_HELLO;
+}
+
+/*
+ * Returns a negative value on failure, and otherwise
+ * - SSL_SERVER_HELLO or
+ * - SSL_SERVER_HELLO_HRR or
+ * - SSL_SERVER_HELLO_TLS1_2
+ */
+#define SSL_SERVER_HELLO_TLS1_2 2
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_preprocess_server_hello(mbedtls_ssl_context *ssl,
+                                             const unsigned char *buf,
+                                             const unsigned char *end)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+    MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_is_supported_versions_ext_present(
+                                 ssl, buf, end));
+
+    if (ret == 0) {
+        MBEDTLS_SSL_PROC_CHK_NEG(
+            ssl_tls13_is_downgrade_negotiation(ssl, buf, end));
+
+        /* If the server is negotiating TLS 1.2 or below and:
+         * . we did not propose TLS 1.2 or
+         * . the server responded it is TLS 1.3 capable but negotiating a lower
+         *   version of the protocol and thus we are under downgrade attack
+         * abort the handshake with an "illegal parameter" alert.
+         */
+        if (handshake->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2 || ret) {
+            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                         MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+        }
+
+        ssl->keep_current_message = 1;
+        ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                                MBEDTLS_SSL_HS_SERVER_HELLO,
+                                                                buf, (size_t) (end - buf)));
+
+        if (mbedtls_ssl_conf_tls13_some_ephemeral_enabled(ssl)) {
+            ret = ssl_tls13_reset_key_share(ssl);
+            if (ret != 0) {
+                return ret;
+            }
+        }
+
+        return SSL_SERVER_HELLO_TLS1_2;
+    }
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    ssl->session_negotiate->endpoint = ssl->conf->endpoint;
+    ssl->session_negotiate->tls_version = ssl->tls_version;
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+    handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;
+
+    ret = ssl_server_hello_is_hrr(ssl, buf, end);
+    switch (ret) {
+        case SSL_SERVER_HELLO:
+            MBEDTLS_SSL_DEBUG_MSG(2, ("received ServerHello message"));
+            break;
+        case SSL_SERVER_HELLO_HRR:
+            MBEDTLS_SSL_DEBUG_MSG(2, ("received HelloRetryRequest message"));
+            /* If a client receives a second
+             * HelloRetryRequest in the same connection (i.e., where the ClientHello
+             * was itself in response to a HelloRetryRequest), it MUST abort the
+             * handshake with an "unexpected_message" alert.
+             */
+            if (handshake->hello_retry_request_count > 0) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("Multiple HRRs received"));
+                MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,
+                                             MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE);
+                return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+            }
+            /*
+             * Clients must abort the handshake with an "illegal_parameter"
+             * alert if the HelloRetryRequest would not result in any change
+             * in the ClientHello.
+             * In a PSK only key exchange that what we expect.
+             */
+            if (!mbedtls_ssl_conf_tls13_some_ephemeral_enabled(ssl)) {
+                MBEDTLS_SSL_DEBUG_MSG(1,
+                                      ("Unexpected HRR in pure PSK key exchange."));
+                MBEDTLS_SSL_PEND_FATAL_ALERT(
+                    MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                    MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+                return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+            }
+
+            handshake->hello_retry_request_count++;
+
+            break;
+    }
+
+cleanup:
+
+    return ret;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_check_server_hello_session_id_echo(mbedtls_ssl_context *ssl,
+                                                        const unsigned char **buf,
+                                                        const unsigned char *end)
+{
+    const unsigned char *p = *buf;
+    size_t legacy_session_id_echo_len;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1);
+    legacy_session_id_echo_len = *p++;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_echo_len);
+
+    /* legacy_session_id_echo */
+    if (ssl->session_negotiate->id_len != legacy_session_id_echo_len ||
+        memcmp(ssl->session_negotiate->id, p, legacy_session_id_echo_len) != 0) {
+        MBEDTLS_SSL_DEBUG_BUF(3, "Expected Session ID",
+                              ssl->session_negotiate->id,
+                              ssl->session_negotiate->id_len);
+        MBEDTLS_SSL_DEBUG_BUF(3, "Received Session ID", p,
+                              legacy_session_id_echo_len);
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    p += legacy_session_id_echo_len;
+    *buf = p;
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "Session ID", ssl->session_negotiate->id,
+                          ssl->session_negotiate->id_len);
+    return 0;
+}
+
+/* Parse ServerHello message and configure context
+ *
+ * struct {
+ *    ProtocolVersion legacy_version = 0x0303; // TLS 1.2
+ *    Random random;
+ *    opaque legacy_session_id_echo<0..32>;
+ *    CipherSuite cipher_suite;
+ *    uint8 legacy_compression_method = 0;
+ *    Extension extensions<6..2^16-1>;
+ * } ServerHello;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_server_hello(mbedtls_ssl_context *ssl,
+                                        const unsigned char *buf,
+                                        const unsigned char *end,
+                                        int is_hrr)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const unsigned char *p = buf;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    size_t extensions_len;
+    const unsigned char *extensions_end;
+    uint16_t cipher_suite;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+    int fatal_alert = 0;
+    uint32_t allowed_extensions_mask;
+    int hs_msg_type = is_hrr ? MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST :
+                      MBEDTLS_SSL_HS_SERVER_HELLO;
+
+    /*
+     * Check there is space for minimal fields
+     *
+     * - legacy_version             ( 2 bytes)
+     * - random                     (MBEDTLS_SERVER_HELLO_RANDOM_LEN bytes)
+     * - legacy_session_id_echo     ( 1 byte ), minimum size
+     * - cipher_suite               ( 2 bytes)
+     * - legacy_compression_method  ( 1 byte )
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 6);
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "server hello", p, end - p);
+    MBEDTLS_SSL_DEBUG_BUF(3, "server hello, version", p, 2);
+
+    /* ...
+     * ProtocolVersion legacy_version = 0x0303; // TLS 1.2
+     * ...
+     * with ProtocolVersion defined as:
+     * uint16 ProtocolVersion;
+     */
+    if (mbedtls_ssl_read_version(p, ssl->conf->transport) !=
+        MBEDTLS_SSL_VERSION_TLS1_2) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Unsupported version of TLS."));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION,
+                                     MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION);
+        ret = MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;
+        goto cleanup;
+    }
+    p += 2;
+
+    /* ...
+     * Random random;
+     * ...
+     * with Random defined as:
+     * opaque Random[MBEDTLS_SERVER_HELLO_RANDOM_LEN];
+     */
+    if (!is_hrr) {
+        memcpy(&handshake->randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN], p,
+               MBEDTLS_SERVER_HELLO_RANDOM_LEN);
+        MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes",
+                              p, MBEDTLS_SERVER_HELLO_RANDOM_LEN);
+    }
+    p += MBEDTLS_SERVER_HELLO_RANDOM_LEN;
+
+    /* ...
+     * opaque legacy_session_id_echo<0..32>;
+     * ...
+     */
+    if (ssl_tls13_check_server_hello_session_id_echo(ssl, &p, end) != 0) {
+        fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER;
+        goto cleanup;
+    }
+
+    /* ...
+     * CipherSuite cipher_suite;
+     * ...
+     * with CipherSuite defined as:
+     * uint8 CipherSuite[2];
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+
+
+    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite);
+    /*
+     * Check whether this ciphersuite is valid and offered.
+     */
+    if ((mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info,
+                                          ssl->tls_version,
+                                          ssl->tls_version) != 0) ||
+        !mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, cipher_suite)) {
+        fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER;
+    }
+    /*
+     * If we received an HRR before and that the proposed selected
+     * ciphersuite in this server hello is not the same as the one
+     * proposed in the HRR, we abort the handshake and send an
+     * "illegal_parameter" alert.
+     */
+    else if ((!is_hrr) && (handshake->hello_retry_request_count > 0) &&
+             (cipher_suite != ssl->session_negotiate->ciphersuite)) {
+        fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER;
+    }
+
+    if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("invalid ciphersuite(%04x) parameter",
+                                  cipher_suite));
+        goto cleanup;
+    }
+
+    /* Configure ciphersuites */
+    mbedtls_ssl_optimize_checksum(ssl, ciphersuite_info);
+
+    handshake->ciphersuite_info = ciphersuite_info;
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen ciphersuite: ( %04x ) - %s",
+                              cipher_suite, ciphersuite_info->name));
+
+#if defined(MBEDTLS_HAVE_TIME)
+    ssl->session_negotiate->start = time(NULL);
+#endif /* MBEDTLS_HAVE_TIME */
+
+    /* ...
+     * uint8 legacy_compression_method = 0;
+     * ...
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1);
+    if (p[0] != MBEDTLS_SSL_COMPRESS_NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad legacy compression method"));
+        fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER;
+        goto cleanup;
+    }
+    p++;
+
+    /* ...
+     * Extension extensions<6..2^16-1>;
+     * ...
+     * struct {
+     *      ExtensionType extension_type; (2 bytes)
+     *      opaque extension_data<0..2^16-1>;
+     * } Extension;
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+
+    /* Check extensions do not go beyond the buffer of data. */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len);
+    extensions_end = p + extensions_len;
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "server hello extensions", p, extensions_len);
+
+    handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;
+    allowed_extensions_mask = is_hrr ?
+                              MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_HRR :
+                              MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_SH;
+
+    while (p < extensions_end) {
+        unsigned int extension_type;
+        size_t extension_data_len;
+        const unsigned char *extension_data_end;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4);
+        extension_type = MBEDTLS_GET_UINT16_BE(p, 0);
+        extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);
+        p += 4;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len);
+        extension_data_end = p + extension_data_len;
+
+        ret = mbedtls_ssl_tls13_check_received_extension(
+            ssl, hs_msg_type, extension_type, allowed_extensions_mask);
+        if (ret != 0) {
+            return ret;
+        }
+
+        switch (extension_type) {
+            case MBEDTLS_TLS_EXT_COOKIE:
+
+                ret = ssl_tls13_parse_cookie_ext(ssl,
+                                                 p, extension_data_end);
+                if (ret != 0) {
+                    MBEDTLS_SSL_DEBUG_RET(1,
+                                          "ssl_tls13_parse_cookie_ext",
+                                          ret);
+                    goto cleanup;
+                }
+                break;
+
+            case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS:
+                ret = ssl_tls13_parse_supported_versions_ext(ssl,
+                                                             p,
+                                                             extension_data_end);
+                if (ret != 0) {
+                    goto cleanup;
+                }
+                break;
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+            case MBEDTLS_TLS_EXT_PRE_SHARED_KEY:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found pre_shared_key extension"));
+
+                if ((ret = ssl_tls13_parse_server_pre_shared_key_ext(
+                         ssl, p, extension_data_end)) != 0) {
+                    MBEDTLS_SSL_DEBUG_RET(
+                        1, ("ssl_tls13_parse_server_pre_shared_key_ext"), ret);
+                    return ret;
+                }
+                break;
+#endif
+
+            case MBEDTLS_TLS_EXT_KEY_SHARE:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found key_shares extension"));
+                if (!mbedtls_ssl_conf_tls13_some_ephemeral_enabled(ssl)) {
+                    fatal_alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT;
+                    goto cleanup;
+                }
+
+                if (is_hrr) {
+                    ret = ssl_tls13_parse_hrr_key_share_ext(ssl,
+                                                            p, extension_data_end);
+                } else {
+                    ret = ssl_tls13_parse_key_share_ext(ssl,
+                                                        p, extension_data_end);
+                }
+                if (ret != 0) {
+                    MBEDTLS_SSL_DEBUG_RET(1,
+                                          "ssl_tls13_parse_key_share_ext",
+                                          ret);
+                    goto cleanup;
+                }
+                break;
+
+            default:
+                ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+                goto cleanup;
+        }
+
+        p += extension_data_len;
+    }
+
+    MBEDTLS_SSL_PRINT_EXTS(3, hs_msg_type, handshake->received_extensions);
+
+cleanup:
+
+    if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT) {
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT,
+                                     MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION);
+        ret = MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION;
+    } else if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER) {
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+        ret = MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+    return ret;
+}
+
+#if defined(MBEDTLS_DEBUG_C)
+static const char *ssl_tls13_get_kex_mode_str(int mode)
+{
+    switch (mode) {
+        case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK:
+            return "psk";
+        case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL:
+            return "ephemeral";
+        case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL:
+            return "psk_ephemeral";
+        default:
+            return "unknown mode";
+    }
+}
+#endif /* MBEDTLS_DEBUG_C */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_postprocess_server_hello(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+    /* Determine the key exchange mode:
+     * 1) If both the pre_shared_key and key_share extensions were received
+     *    then the key exchange mode is PSK with EPHEMERAL.
+     * 2) If only the pre_shared_key extension was received then the key
+     *    exchange mode is PSK-only.
+     * 3) If only the key_share extension was received then the key
+     *    exchange mode is EPHEMERAL-only.
+     */
+    switch (handshake->received_extensions &
+            (MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | MBEDTLS_SSL_EXT_MASK(KEY_SHARE))) {
+        /* Only the pre_shared_key extension was received */
+        case MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY):
+            handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;
+            break;
+
+        /* Only the key_share extension was received */
+        case MBEDTLS_SSL_EXT_MASK(KEY_SHARE):
+            handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL;
+            break;
+
+        /* Both the pre_shared_key and key_share extensions were received */
+        case (MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | MBEDTLS_SSL_EXT_MASK(KEY_SHARE)):
+            handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
+            break;
+
+        /* Neither pre_shared_key nor key_share extension was received */
+        default:
+            MBEDTLS_SSL_DEBUG_MSG(1, ("Unknown key exchange."));
+            ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+            goto cleanup;
+    }
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA) &&
+        (handshake->selected_identity != 0 ||
+         handshake->ciphersuite_info->id !=
+         ssl->session_negotiate->ciphersuite)) {
+        /* RFC8446 4.2.11
+         * If the server supplies an "early_data" extension, the
+         * client MUST verify that the server's selected_identity
+         * is 0. If any other value is returned, the client MUST
+         * abort the handshake with an "illegal_parameter" alert.
+         *
+         * RFC 8446 4.2.10
+         * In order to accept early data, the server MUST have accepted a PSK
+         * cipher suite and selected the first key offered in the client's
+         * "pre_shared_key" extension. In addition, it MUST verify that the
+         * following values are the same as those associated with the
+         * selected PSK:
+         * - The TLS version number
+         * - The selected cipher suite
+         * - The selected ALPN [RFC7301] protocol, if any
+         *
+         * We check here that when early data is involved the server
+         * selected the cipher suite associated to the pre-shared key
+         * as it must have.
+         */
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+#endif
+
+    if (!mbedtls_ssl_conf_tls13_check_kex_modes(
+            ssl, handshake->key_exchange_mode)) {
+        ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+        MBEDTLS_SSL_DEBUG_MSG(2,
+                              ("Key exchange mode(%s) is not supported.",
+                               ssl_tls13_get_kex_mode_str(handshake->key_exchange_mode)));
+        goto cleanup;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3,
+                          ("Selected key exchange mode: %s",
+                           ssl_tls13_get_kex_mode_str(handshake->key_exchange_mode)));
+
+    /* Start the TLS 1.3 key scheduling if not already done.
+     *
+     * If we proposed early data then we have already derived an
+     * early secret using the selected PSK and its associated hash.
+     * It means that if the negotiated key exchange mode is psk or
+     * psk_ephemeral, we have already correctly computed the
+     * early secret and thus we do not do it again. In all other
+     * cases we compute it here.
+     */
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT ||
+        handshake->key_exchange_mode ==
+        MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL)
+#endif
+    {
+        ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(
+                1, "mbedtls_ssl_tls13_key_schedule_stage_early", ret);
+            goto cleanup;
+        }
+    }
+
+    ret = mbedtls_ssl_tls13_compute_handshake_transform(ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1,
+                              "mbedtls_ssl_tls13_compute_handshake_transform",
+                              ret);
+        goto cleanup;
+    }
+
+    mbedtls_ssl_set_inbound_transform(ssl, handshake->transform_handshake);
+    MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to handshake keys for inbound traffic"));
+    ssl->session_negotiate->ciphersuite = handshake->ciphersuite_info->id;
+    ssl->session_in = ssl->session_negotiate;
+
+cleanup:
+    if (ret != 0) {
+        MBEDTLS_SSL_PEND_FATAL_ALERT(
+            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
+            MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
+    }
+
+    return ret;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_postprocess_hrr(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    mbedtls_ssl_session_reset_msg_layer(ssl, 0);
+
+    /*
+     * We are going to re-generate a shared secret corresponding to the group
+     * selected by the server, which is different from the group for which we
+     * generated a shared secret in the first client hello.
+     * Thus, reset the shared secret.
+     */
+    ret = ssl_tls13_reset_key_share(ssl);
+    if (ret != 0) {
+        return ret;
+    }
+
+    ssl->session_negotiate->ciphersuite = ssl->handshake->ciphersuite_info->id;
+    return 0;
+}
+
+/*
+ * Wait and parse ServerHello handshake message.
+ * Handler for MBEDTLS_SSL_SERVER_HELLO
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_process_server_hello(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *buf = NULL;
+    size_t buf_len = 0;
+    int is_hrr = 0;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> %s", __func__));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(ssl,
+                                                               MBEDTLS_SSL_HS_SERVER_HELLO,
+                                                               &buf, &buf_len));
+
+    ret = ssl_tls13_preprocess_server_hello(ssl, buf, buf + buf_len);
+    if (ret < 0) {
+        goto cleanup;
+    } else {
+        is_hrr = (ret == SSL_SERVER_HELLO_HRR);
+    }
+
+    if (ret == SSL_SERVER_HELLO_TLS1_2) {
+        ret = 0;
+        goto cleanup;
+    }
+
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_server_hello(ssl, buf,
+                                                      buf + buf_len,
+                                                      is_hrr));
+    if (is_hrr) {
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_reset_transcript_for_hrr(ssl));
+    }
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                            MBEDTLS_SSL_HS_SERVER_HELLO, buf,
+                                                            buf_len));
+
+    if (is_hrr) {
+        MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_hrr(ssl));
+#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+        /* If not offering early data, the client sends a dummy CCS record
+         * immediately before its second flight. This may either be before
+         * its second ClientHello or before its encrypted handshake flight.
+         */
+        mbedtls_ssl_handshake_set_state(ssl,
+                                        MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO);
+#else
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);
+#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
+    } else {
+        MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_server_hello(ssl));
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS);
+    }
+
+cleanup:
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= %s ( %s )", __func__,
+                              is_hrr ? "HelloRetryRequest" : "ServerHello"));
+    return ret;
+}
+
+/*
+ *
+ * Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS
+ *
+ * The EncryptedExtensions message contains any extensions which
+ * should be protected, i.e., any which are not needed to establish
+ * the cryptographic context.
+ */
+
+/* Parse EncryptedExtensions message
+ * struct {
+ *     Extension extensions<0..2^16-1>;
+ * } EncryptedExtensions;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_encrypted_extensions(mbedtls_ssl_context *ssl,
+                                                const unsigned char *buf,
+                                                const unsigned char *end)
+{
+    int ret = 0;
+    size_t extensions_len;
+    const unsigned char *p = buf;
+    const unsigned char *extensions_end;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len);
+    extensions_end = p + extensions_len;
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "encrypted extensions", p, extensions_len);
+
+    handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;
+
+    while (p < extensions_end) {
+        unsigned int extension_type;
+        size_t extension_data_len;
+
+        /*
+         * struct {
+         *     ExtensionType extension_type; (2 bytes)
+         *     opaque extension_data<0..2^16-1>;
+         * } Extension;
+         */
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4);
+        extension_type = MBEDTLS_GET_UINT16_BE(p, 0);
+        extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);
+        p += 4;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len);
+
+        ret = mbedtls_ssl_tls13_check_received_extension(
+            ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, extension_type,
+            MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_EE);
+        if (ret != 0) {
+            return ret;
+        }
+
+        switch (extension_type) {
+#if defined(MBEDTLS_SSL_ALPN)
+            case MBEDTLS_TLS_EXT_ALPN:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension"));
+
+                if ((ret = ssl_tls13_parse_alpn_ext(ssl, p, (size_t) extension_data_len)) != 0) {
+                    return ret;
+                }
+
+                break;
+#endif /* MBEDTLS_SSL_ALPN */
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+            case MBEDTLS_TLS_EXT_EARLY_DATA:
+
+                if (extension_data_len != 0) {
+                    /* The message must be empty. */
+                    MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
+                                                 MBEDTLS_ERR_SSL_DECODE_ERROR);
+                    return MBEDTLS_ERR_SSL_DECODE_ERROR;
+                }
+
+                break;
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+            case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found record_size_limit extension"));
+
+                ret = mbedtls_ssl_tls13_parse_record_size_limit_ext(ssl, p, p + extension_data_len);
+
+                /* TODO: Return unconditionally here until we handle the record size limit correctly.
+                 *            Once handled correctly, only return in case of errors. */
+                return ret;
+
+                break;
+#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
+
+            default:
+                MBEDTLS_SSL_PRINT_EXT(
+                    3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
+                    extension_type, "( ignored )");
+                break;
+        }
+
+        p += extension_data_len;
+    }
+
+    MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
+                           handshake->received_extensions);
+
+    /* Check that we consumed all the message. */
+    if (p != end) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("EncryptedExtension lengths misaligned"));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
+                                     MBEDTLS_ERR_SSL_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    return ret;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_process_encrypted_extensions(mbedtls_ssl_context *ssl)
+{
+    int ret;
+    unsigned char *buf;
+    size_t buf_len;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse encrypted extensions"));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(ssl,
+                                                               MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
+                                                               &buf, &buf_len));
+
+    /* Process the message contents */
+    MBEDTLS_SSL_PROC_CHK(
+        ssl_tls13_parse_encrypted_extensions(ssl, buf, buf + buf_len));
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    if (ssl->handshake->received_extensions &
+        MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) {
+        ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED;
+    }
+#endif
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                            MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
+                                                            buf, buf_len));
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+    if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) {
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED);
+    } else {
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST);
+    }
+#else
+    ((void) ssl);
+    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED);
+#endif
+
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse encrypted extensions"));
+    return ret;
+
+}
+
+/*
+ * Handler for MBEDTLS_SSL_END_OF_EARLY_DATA
+ *
+ * RFC 8446 section 4.5
+ *
+ * struct {} EndOfEarlyData;
+ *
+ * If the server sent an "early_data" extension in EncryptedExtensions, the
+ * client MUST send an EndOfEarlyData message after receiving the server
+ * Finished. Otherwise, the client MUST NOT send an EndOfEarlyData message.
+ */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_end_of_early_data(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *buf = NULL;
+    size_t buf_len;
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write EndOfEarlyData"));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(
+                             ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA,
+                             &buf, &buf_len));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_hdr_to_checksum(
+                             ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, 0));
+
+    MBEDTLS_SSL_PROC_CHK(
+        mbedtls_ssl_finish_handshake_msg(ssl, buf_len, 0));
+
+    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);
+
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write EndOfEarlyData"));
+    return ret;
+}
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+/*
+ * STATE HANDLING: CertificateRequest
+ *
+ */
+#define SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST 0
+#define SSL_CERTIFICATE_REQUEST_SKIP           1
+/* Coordination:
+ * Deals with the ambiguity of not knowing if a CertificateRequest
+ * will be sent. Returns a negative code on failure, or
+ * - SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST
+ * - SSL_CERTIFICATE_REQUEST_SKIP
+ * indicating if a Certificate Request is expected or not.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_certificate_request_coordinate(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
+        return ret;
+    }
+    ssl->keep_current_message = 1;
+
+    if ((ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) &&
+        (ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST)) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("got a certificate request"));
+        return SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("got no certificate request"));
+
+    return SSL_CERTIFICATE_REQUEST_SKIP;
+}
+
+/*
+ * ssl_tls13_parse_certificate_request()
+ *     Parse certificate request
+ * struct {
+ *   opaque certificate_request_context<0..2^8-1>;
+ *   Extension extensions<2..2^16-1>;
+ * } CertificateRequest;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_certificate_request(mbedtls_ssl_context *ssl,
+                                               const unsigned char *buf,
+                                               const unsigned char *end)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const unsigned char *p = buf;
+    size_t certificate_request_context_len = 0;
+    size_t extensions_len = 0;
+    const unsigned char *extensions_end;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+    /* ...
+     * opaque certificate_request_context<0..2^8-1>
+     * ...
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1);
+    certificate_request_context_len = (size_t) p[0];
+    p += 1;
+
+    if (certificate_request_context_len > 0) {
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, certificate_request_context_len);
+        MBEDTLS_SSL_DEBUG_BUF(3, "Certificate Request Context",
+                              p, certificate_request_context_len);
+
+        handshake->certificate_request_context =
+            mbedtls_calloc(1, certificate_request_context_len);
+        if (handshake->certificate_request_context == NULL) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small"));
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        }
+        memcpy(handshake->certificate_request_context, p,
+               certificate_request_context_len);
+        p += certificate_request_context_len;
+    }
+
+    /* ...
+     * Extension extensions<2..2^16-1>;
+     * ...
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len);
+    extensions_end = p + extensions_len;
+
+    handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;
+
+    while (p < extensions_end) {
+        unsigned int extension_type;
+        size_t extension_data_len;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4);
+        extension_type = MBEDTLS_GET_UINT16_BE(p, 0);
+        extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);
+        p += 4;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len);
+
+        ret = mbedtls_ssl_tls13_check_received_extension(
+            ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, extension_type,
+            MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CR);
+        if (ret != 0) {
+            return ret;
+        }
+
+        switch (extension_type) {
+            case MBEDTLS_TLS_EXT_SIG_ALG:
+                MBEDTLS_SSL_DEBUG_MSG(3,
+                                      ("found signature algorithms extension"));
+                ret = mbedtls_ssl_parse_sig_alg_ext(ssl, p,
+                                                    p + extension_data_len);
+                if (ret != 0) {
+                    return ret;
+                }
+
+                break;
+
+            default:
+                MBEDTLS_SSL_PRINT_EXT(
+                    3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,
+                    extension_type, "( ignored )");
+                break;
+        }
+
+        p += extension_data_len;
+    }
+
+    MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,
+                           handshake->received_extensions);
+
+    /* Check that we consumed all the message. */
+    if (p != end) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("CertificateRequest misaligned"));
+        goto decode_error;
+    }
+
+    /* RFC 8446 section 4.3.2
+     *
+     * The "signature_algorithms" extension MUST be specified
+     */
+    if ((handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(SIG_ALG)) == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(3,
+                              ("no signature algorithms extension found"));
+        goto decode_error;
+    }
+
+    ssl->handshake->client_auth = 1;
+    return 0;
+
+decode_error:
+    MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
+                                 MBEDTLS_ERR_SSL_DECODE_ERROR);
+    return MBEDTLS_ERR_SSL_DECODE_ERROR;
+}
+
+/*
+ * Handler for  MBEDTLS_SSL_CERTIFICATE_REQUEST
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_process_certificate_request(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate request"));
+
+    MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_certificate_request_coordinate(ssl));
+
+    if (ret == SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST) {
+        unsigned char *buf;
+        size_t buf_len;
+
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(ssl,
+                                                                   MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,
+                                                                   &buf, &buf_len));
+
+        MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_request(ssl,
+                                                                 buf, buf + buf_len));
+
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                                MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,
+                                                                buf, buf_len));
+    } else if (ret == SSL_CERTIFICATE_REQUEST_SKIP) {
+        ret = 0;
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        goto cleanup;
+    }
+
+    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CERTIFICATE);
+
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate request"));
+    return ret;
+}
+
+/*
+ * Handler for MBEDTLS_SSL_SERVER_CERTIFICATE
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_process_server_certificate(mbedtls_ssl_context *ssl)
+{
+    int ret;
+
+    ret = mbedtls_ssl_tls13_process_certificate(ssl);
+    if (ret != 0) {
+        return ret;
+    }
+
+    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_VERIFY);
+    return 0;
+}
+
+/*
+ * Handler for MBEDTLS_SSL_CERTIFICATE_VERIFY
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl)
+{
+    int ret;
+
+    ret = mbedtls_ssl_tls13_process_certificate_verify(ssl);
+    if (ret != 0) {
+        return ret;
+    }
+
+    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED);
+    return 0;
+}
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+
+/*
+ * Handler for MBEDTLS_SSL_SERVER_FINISHED
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_process_server_finished(mbedtls_ssl_context *ssl)
+{
+    int ret;
+
+    ret = mbedtls_ssl_tls13_process_finished_message(ssl);
+    if (ret != 0) {
+        return ret;
+    }
+
+    ret = mbedtls_ssl_tls13_compute_application_transform(ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_PEND_FATAL_ALERT(
+            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
+            MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
+        return ret;
+    }
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED) {
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_END_OF_EARLY_DATA);
+    } else if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED) {
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);
+    } else
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+    {
+#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+        mbedtls_ssl_handshake_set_state(
+            ssl, MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED);
+#else
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);
+#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
+    }
+
+    return 0;
+}
+
+/*
+ * Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_client_certificate(mbedtls_ssl_context *ssl)
+{
+    int non_empty_certificate_msg = 0;
+
+    MBEDTLS_SSL_DEBUG_MSG(1,
+                          ("Switch to handshake traffic keys for outbound traffic"));
+    mbedtls_ssl_set_outbound_transform(ssl, ssl->handshake->transform_handshake);
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+    if (ssl->handshake->client_auth) {
+        int ret = mbedtls_ssl_tls13_write_certificate(ssl);
+        if (ret != 0) {
+            return ret;
+        }
+
+        if (mbedtls_ssl_own_cert(ssl) != NULL) {
+            non_empty_certificate_msg = 1;
+        }
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("skip write certificate"));
+    }
+#endif
+
+    if (non_empty_certificate_msg) {
+        mbedtls_ssl_handshake_set_state(ssl,
+                                        MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY);
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("skip write certificate verify"));
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED);
+    }
+
+    return 0;
+}
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+/*
+ * Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_client_certificate_verify(mbedtls_ssl_context *ssl)
+{
+    int ret = mbedtls_ssl_tls13_write_certificate_verify(ssl);
+
+    if (ret == 0) {
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED);
+    }
+
+    return ret;
+}
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+
+/*
+ * Handler for MBEDTLS_SSL_CLIENT_FINISHED
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_client_finished(mbedtls_ssl_context *ssl)
+{
+    int ret;
+
+    ret = mbedtls_ssl_tls13_write_finished_message(ssl);
+    if (ret != 0) {
+        return ret;
+    }
+
+    ret = mbedtls_ssl_tls13_compute_resumption_master_secret(ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1,
+                              "mbedtls_ssl_tls13_compute_resumption_master_secret ", ret);
+        return ret;
+    }
+
+    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_FLUSH_BUFFERS);
+    return 0;
+}
+
+/*
+ * Handler for MBEDTLS_SSL_FLUSH_BUFFERS
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_flush_buffers(mbedtls_ssl_context *ssl)
+{
+    MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done"));
+    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP);
+    return 0;
+}
+
+/*
+ * Handler for MBEDTLS_SSL_HANDSHAKE_WRAPUP
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl)
+{
+
+    mbedtls_ssl_tls13_handshake_wrapup(ssl);
+
+    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER);
+    return 0;
+}
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_new_session_ticket_exts(mbedtls_ssl_context *ssl,
+                                                   const unsigned char *buf,
+                                                   const unsigned char *end)
+{
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    const unsigned char *p = buf;
+
+
+    handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;
+
+    while (p < end) {
+        unsigned int extension_type;
+        size_t extension_data_len;
+        int ret;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4);
+        extension_type = MBEDTLS_GET_UINT16_BE(p, 0);
+        extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);
+        p += 4;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extension_data_len);
+
+        ret = mbedtls_ssl_tls13_check_received_extension(
+            ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, extension_type,
+            MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_NST);
+        if (ret != 0) {
+            return ret;
+        }
+
+        switch (extension_type) {
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+            case MBEDTLS_TLS_EXT_EARLY_DATA:
+                if (extension_data_len != 4) {
+                    MBEDTLS_SSL_PEND_FATAL_ALERT(
+                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
+                        MBEDTLS_ERR_SSL_DECODE_ERROR);
+                    return MBEDTLS_ERR_SSL_DECODE_ERROR;
+                }
+                if (ssl->session != NULL) {
+                    ssl->session->ticket_flags |=
+                        MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA;
+                }
+                break;
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
+            default:
+                MBEDTLS_SSL_PRINT_EXT(
+                    3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET,
+                    extension_type, "( ignored )");
+                break;
+        }
+
+        p +=  extension_data_len;
+    }
+
+    MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET,
+                           handshake->received_extensions);
+
+    return 0;
+}
+
+/*
+ * From RFC8446, page 74
+ *
+ * struct {
+ *    uint32 ticket_lifetime;
+ *    uint32 ticket_age_add;
+ *    opaque ticket_nonce<0..255>;
+ *    opaque ticket<1..2^16-1>;
+ *    Extension extensions<0..2^16-2>;
+ * } NewSessionTicket;
+ *
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_new_session_ticket(mbedtls_ssl_context *ssl,
+                                              unsigned char *buf,
+                                              unsigned char *end,
+                                              unsigned char **ticket_nonce,
+                                              size_t *ticket_nonce_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *p = buf;
+    mbedtls_ssl_session *session = ssl->session;
+    size_t ticket_len;
+    unsigned char *ticket;
+    size_t extensions_len;
+
+    *ticket_nonce = NULL;
+    *ticket_nonce_len = 0;
+    /*
+     *    ticket_lifetime   4 bytes
+     *    ticket_age_add    4 bytes
+     *    ticket_nonce_len  1 byte
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 9);
+
+    session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0);
+    MBEDTLS_SSL_DEBUG_MSG(3,
+                          ("ticket_lifetime: %u",
+                           (unsigned int) session->ticket_lifetime));
+
+    session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 4);
+    MBEDTLS_SSL_DEBUG_MSG(3,
+                          ("ticket_age_add: %u",
+                           (unsigned int) session->ticket_age_add));
+
+    *ticket_nonce_len = p[8];
+    p += 9;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, *ticket_nonce_len);
+    *ticket_nonce = p;
+    MBEDTLS_SSL_DEBUG_BUF(3, "ticket_nonce:", *ticket_nonce, *ticket_nonce_len);
+    p += *ticket_nonce_len;
+
+    /* Ticket */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    ticket_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, ticket_len);
+    MBEDTLS_SSL_DEBUG_BUF(3, "received ticket", p, ticket_len);
+
+    /* Check if we previously received a ticket already. */
+    if (session->ticket != NULL || session->ticket_len > 0) {
+        mbedtls_free(session->ticket);
+        session->ticket = NULL;
+        session->ticket_len = 0;
+    }
+
+    if ((ticket = mbedtls_calloc(1, ticket_len)) == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("ticket alloc failed"));
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+    }
+    memcpy(ticket, p, ticket_len);
+    p += ticket_len;
+    session->ticket = ticket;
+    session->ticket_len = ticket_len;
+
+    /* Clear all flags in ticket_flags */
+    mbedtls_ssl_session_clear_ticket_flags(
+        session, MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len);
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "ticket extension", p, extensions_len);
+
+    ret = ssl_tls13_parse_new_session_ticket_exts(ssl, p, p + extensions_len);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1,
+                              "ssl_tls13_parse_new_session_ticket_exts",
+                              ret);
+        return ret;
+    }
+
+    /* session has been updated, allow export */
+    session->exported = 0;
+
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_postprocess_new_session_ticket(mbedtls_ssl_context *ssl,
+                                                    unsigned char *ticket_nonce,
+                                                    size_t ticket_nonce_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ssl_session *session = ssl->session;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+    psa_algorithm_t psa_hash_alg;
+    int hash_length;
+
+#if defined(MBEDTLS_HAVE_TIME)
+    /* Store ticket creation time */
+    session->ticket_received = mbedtls_time(NULL);
+#endif
+
+    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(session->ciphersuite);
+    if (ciphersuite_info == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    psa_hash_alg = mbedtls_psa_translate_md(ciphersuite_info->mac);
+    hash_length = PSA_HASH_LENGTH(psa_hash_alg);
+    if (hash_length == -1 ||
+        (size_t) hash_length > sizeof(session->resumption_key)) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "resumption_master_secret",
+                          session->app_secrets.resumption_master_secret,
+                          hash_length);
+
+    /* Compute resumption key
+     *
+     *  HKDF-Expand-Label( resumption_master_secret,
+     *                    "resumption", ticket_nonce, Hash.length )
+     */
+    ret = mbedtls_ssl_tls13_hkdf_expand_label(
+        psa_hash_alg,
+        session->app_secrets.resumption_master_secret,
+        hash_length,
+        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(resumption),
+        ticket_nonce,
+        ticket_nonce_len,
+        session->resumption_key,
+        hash_length);
+
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(2,
+                              "Creating the ticket-resumed PSK failed",
+                              ret);
+        return ret;
+    }
+
+    session->resumption_key_len = hash_length;
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "Ticket-resumed PSK",
+                          session->resumption_key,
+                          session->resumption_key_len);
+
+    /* Set ticket_flags depends on the selected key exchange modes */
+    mbedtls_ssl_session_set_ticket_flags(
+        session, ssl->conf->tls13_kex_modes);
+    MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags);
+
+    return 0;
+}
+
+/*
+ * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_process_new_session_ticket(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *buf;
+    size_t buf_len;
+    unsigned char *ticket_nonce;
+    size_t ticket_nonce_len;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse new session ticket"));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(
+                             ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET,
+                             &buf, &buf_len));
+
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_new_session_ticket(
+                             ssl, buf, buf + buf_len,
+                             &ticket_nonce, &ticket_nonce_len));
+
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_new_session_ticket(
+                             ssl, ticket_nonce, ticket_nonce_len));
+
+    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER);
+
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse new session ticket"));
+    return ret;
+}
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl)
+{
+    int ret = 0;
+
+    switch (ssl->state) {
+        case MBEDTLS_SSL_HELLO_REQUEST:
+            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);
+            break;
+
+        case MBEDTLS_SSL_CLIENT_HELLO:
+            ret = mbedtls_ssl_write_client_hello(ssl);
+            break;
+
+        case MBEDTLS_SSL_SERVER_HELLO:
+            ret = ssl_tls13_process_server_hello(ssl);
+            break;
+
+        case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS:
+            ret = ssl_tls13_process_encrypted_extensions(ssl);
+            break;
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+        case MBEDTLS_SSL_CERTIFICATE_REQUEST:
+            ret = ssl_tls13_process_certificate_request(ssl);
+            break;
+
+        case MBEDTLS_SSL_SERVER_CERTIFICATE:
+            ret = ssl_tls13_process_server_certificate(ssl);
+            break;
+
+        case MBEDTLS_SSL_CERTIFICATE_VERIFY:
+            ret = ssl_tls13_process_certificate_verify(ssl);
+            break;
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+
+        case MBEDTLS_SSL_SERVER_FINISHED:
+            ret = ssl_tls13_process_server_finished(ssl);
+            break;
+
+        case MBEDTLS_SSL_END_OF_EARLY_DATA:
+            ret = ssl_tls13_write_end_of_early_data(ssl);
+            break;
+
+        case MBEDTLS_SSL_CLIENT_CERTIFICATE:
+            ret = ssl_tls13_write_client_certificate(ssl);
+            break;
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+        case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY:
+            ret = ssl_tls13_write_client_certificate_verify(ssl);
+            break;
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+
+        case MBEDTLS_SSL_CLIENT_FINISHED:
+            ret = ssl_tls13_write_client_finished(ssl);
+            break;
+
+        case MBEDTLS_SSL_FLUSH_BUFFERS:
+            ret = ssl_tls13_flush_buffers(ssl);
+            break;
+
+        case MBEDTLS_SSL_HANDSHAKE_WRAPUP:
+            ret = ssl_tls13_handshake_wrapup(ssl);
+            break;
+
+            /*
+             * Injection of dummy-CCS's for middlebox compatibility
+             */
+#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+        case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO:
+            ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
+            if (ret == 0) {
+                mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);
+            }
+            break;
+
+        case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED:
+            ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
+            if (ret == 0) {
+                mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);
+            }
+            break;
+
+        case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO:
+            ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
+            if (ret == 0) {
+                mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO);
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+                MBEDTLS_SSL_DEBUG_MSG(
+                    1, ("Switch to early data keys for outbound traffic"));
+                mbedtls_ssl_set_outbound_transform(
+                    ssl, ssl->handshake->transform_earlydata);
+#endif
+            }
+            break;
+#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+        case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET:
+            ret = ssl_tls13_process_new_session_ticket(ssl);
+            if (ret != 0) {
+                break;
+            }
+            ret = MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET;
+            break;
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+        default:
+            MBEDTLS_SSL_DEBUG_MSG(1, ("invalid state %d", ssl->state));
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    return ret;
+}
+
+#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_PROTO_TLS1_3 */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls13_generic.c b/lib/libmbedtls/mbedtls/library/ssl_tls13_generic.c
new file mode 100644
index 0000000..669a90a
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls13_generic.c
@@ -0,0 +1,1627 @@
+/*
+ *  TLS 1.3 functionality shared between client and server
+ *
+ *  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.
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_SSL_TLS_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
+
+#include <string.h>
+
+#include "mbedtls/error.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/oid.h"
+#include "mbedtls/platform.h"
+#include "mbedtls/constant_time.h"
+#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
+
+#include "ssl_misc.h"
+#include "ssl_tls13_invasive.h"
+#include "ssl_tls13_keys.h"
+#include "ssl_debug_helpers.h"
+
+#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
+
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_ssl_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+
+const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[
+    MBEDTLS_SERVER_HELLO_RANDOM_LEN] =
+{ 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
+  0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
+  0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
+  0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C };
+
+int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl,
+                                          unsigned hs_type,
+                                          unsigned char **buf,
+                                          size_t *buf_len)
+{
+    int ret;
+
+    if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
+        goto cleanup;
+    }
+
+    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ||
+        ssl->in_msg[0]  != hs_type) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Receive unexpected handshake message."));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,
+                                     MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE);
+        ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+        goto cleanup;
+    }
+
+    /*
+     * Jump handshake header (4 bytes, see Section 4 of RFC 8446).
+     *    ...
+     *    HandshakeType msg_type;
+     *    uint24 length;
+     *    ...
+     */
+    *buf = ssl->in_msg   + 4;
+    *buf_len = ssl->in_hslen - 4;
+
+cleanup:
+
+    return ret;
+}
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+/*
+ * STATE HANDLING: Read CertificateVerify
+ */
+/* Macro to express the maximum length of the verify structure.
+ *
+ * The structure is computed per TLS 1.3 specification as:
+ *   - 64 bytes of octet 32,
+ *   - 33 bytes for the context string
+ *        (which is either "TLS 1.3, client CertificateVerify"
+ *         or "TLS 1.3, server CertificateVerify"),
+ *   - 1 byte for the octet 0x0, which serves as a separator,
+ *   - 32 or 48 bytes for the Transcript-Hash(Handshake Context, Certificate)
+ *     (depending on the size of the transcript_hash)
+ *
+ * This results in a total size of
+ * - 130 bytes for a SHA256-based transcript hash, or
+ *   (64 + 33 + 1 + 32 bytes)
+ * - 146 bytes for a SHA384-based transcript hash.
+ *   (64 + 33 + 1 + 48 bytes)
+ *
+ */
+#define SSL_VERIFY_STRUCT_MAX_SIZE  (64 +                          \
+                                     33 +                          \
+                                     1 +                          \
+                                     MBEDTLS_TLS1_3_MD_MAX_SIZE    \
+                                     )
+
+/*
+ * The ssl_tls13_create_verify_structure() creates the verify structure.
+ * As input, it requires the transcript hash.
+ *
+ * The caller has to ensure that the buffer has size at least
+ * SSL_VERIFY_STRUCT_MAX_SIZE bytes.
+ */
+static void ssl_tls13_create_verify_structure(const unsigned char *transcript_hash,
+                                              size_t transcript_hash_len,
+                                              unsigned char *verify_buffer,
+                                              size_t *verify_buffer_len,
+                                              int from)
+{
+    size_t idx;
+
+    /* RFC 8446, Section 4.4.3:
+     *
+     * The digital signature [in the CertificateVerify message] is then
+     * computed over the concatenation of:
+     * -  A string that consists of octet 32 (0x20) repeated 64 times
+     * -  The context string
+     * -  A single 0 byte which serves as the separator
+     * -  The content to be signed
+     */
+    memset(verify_buffer, 0x20, 64);
+    idx = 64;
+
+    if (from == MBEDTLS_SSL_IS_CLIENT) {
+        memcpy(verify_buffer + idx, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(client_cv));
+        idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(client_cv);
+    } else { /* from == MBEDTLS_SSL_IS_SERVER */
+        memcpy(verify_buffer + idx, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(server_cv));
+        idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(server_cv);
+    }
+
+    verify_buffer[idx++] = 0x0;
+
+    memcpy(verify_buffer + idx, transcript_hash, transcript_hash_len);
+    idx += transcript_hash_len;
+
+    *verify_buffer_len = idx;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_certificate_verify(mbedtls_ssl_context *ssl,
+                                              const unsigned char *buf,
+                                              const unsigned char *end,
+                                              const unsigned char *verify_buffer,
+                                              size_t verify_buffer_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    const unsigned char *p = buf;
+    uint16_t algorithm;
+    size_t signature_len;
+    mbedtls_pk_type_t sig_alg;
+    mbedtls_md_type_t md_alg;
+    psa_algorithm_t hash_alg = PSA_ALG_NONE;
+    unsigned char verify_hash[PSA_HASH_MAX_SIZE];
+    size_t verify_hash_len;
+
+    void const *options = NULL;
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+    mbedtls_pk_rsassa_pss_options rsassa_pss_options;
+#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
+
+    /*
+     * struct {
+     *     SignatureScheme algorithm;
+     *     opaque signature<0..2^16-1>;
+     * } CertificateVerify;
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    algorithm = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+
+    /* RFC 8446 section 4.4.3
+     *
+     * If the CertificateVerify message is sent by a server, the signature algorithm
+     * MUST be one offered in the client's "signature_algorithms" extension unless
+     * no valid certificate chain can be produced without unsupported algorithms
+     *
+     * RFC 8446 section 4.4.2.2
+     *
+     * If the client cannot construct an acceptable chain using the provided
+     * certificates and decides to abort the handshake, then it MUST abort the handshake
+     * with an appropriate certificate-related alert (by default, "unsupported_certificate").
+     *
+     * Check if algorithm is an offered signature algorithm.
+     */
+    if (!mbedtls_ssl_sig_alg_is_offered(ssl, algorithm)) {
+        /* algorithm not in offered signature algorithms list */
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Received signature algorithm(%04x) is not "
+                                  "offered.",
+                                  (unsigned int) algorithm));
+        goto error;
+    }
+
+    if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg(
+            algorithm, &sig_alg, &md_alg) != 0) {
+        goto error;
+    }
+
+    hash_alg = mbedtls_hash_info_psa_from_md(md_alg);
+    if (hash_alg == 0) {
+        goto error;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate Verify: Signature algorithm ( %04x )",
+                              (unsigned int) algorithm));
+
+    /*
+     * Check the certificate's key type matches the signature alg
+     */
+    if (!mbedtls_pk_can_do(&ssl->session_negotiate->peer_cert->pk, sig_alg)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("signature algorithm doesn't match cert key"));
+        goto error;
+    }
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    signature_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, signature_len);
+
+    status = psa_hash_compute(hash_alg,
+                              verify_buffer,
+                              verify_buffer_len,
+                              verify_hash,
+                              sizeof(verify_hash),
+                              &verify_hash_len);
+    if (status != PSA_SUCCESS) {
+        MBEDTLS_SSL_DEBUG_RET(1, "hash computation PSA error", status);
+        goto error;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "verify hash", verify_hash, verify_hash_len);
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+    if (sig_alg == MBEDTLS_PK_RSASSA_PSS) {
+        rsassa_pss_options.mgf1_hash_id = md_alg;
+
+        rsassa_pss_options.expected_salt_len = PSA_HASH_LENGTH(hash_alg);
+        options = (const void *) &rsassa_pss_options;
+    }
+#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
+
+    if ((ret = mbedtls_pk_verify_ext(sig_alg, options,
+                                     &ssl->session_negotiate->peer_cert->pk,
+                                     md_alg, verify_hash, verify_hash_len,
+                                     p, signature_len)) == 0) {
+        return 0;
+    }
+    MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_verify_ext", ret);
+
+error:
+    /* RFC 8446 section 4.4.3
+     *
+     * If the verification fails, the receiver MUST terminate the handshake
+     * with a "decrypt_error" alert.
+     */
+    MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR,
+                                 MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
+    return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+
+}
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+
+int mbedtls_ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl)
+{
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char verify_buffer[SSL_VERIFY_STRUCT_MAX_SIZE];
+    size_t verify_buffer_len;
+    unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+    size_t transcript_len;
+    unsigned char *buf;
+    size_t buf_len;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate verify"));
+
+    MBEDTLS_SSL_PROC_CHK(
+        mbedtls_ssl_tls13_fetch_handshake_msg(ssl,
+                                              MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, &buf, &buf_len));
+
+    /* Need to calculate the hash of the transcript first
+     * before reading the message since otherwise it gets
+     * included in the transcript
+     */
+    ret = mbedtls_ssl_get_handshake_transcript(ssl,
+                                               ssl->handshake->ciphersuite_info->mac,
+                                               transcript, sizeof(transcript),
+                                               &transcript_len);
+    if (ret != 0) {
+        MBEDTLS_SSL_PEND_FATAL_ALERT(
+            MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR,
+            MBEDTLS_ERR_SSL_INTERNAL_ERROR);
+        return ret;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "handshake hash", transcript, transcript_len);
+
+    /* Create verify structure */
+    ssl_tls13_create_verify_structure(transcript,
+                                      transcript_len,
+                                      verify_buffer,
+                                      &verify_buffer_len,
+                                      (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) ?
+                                      MBEDTLS_SSL_IS_SERVER :
+                                      MBEDTLS_SSL_IS_CLIENT);
+
+    /* Process the message contents */
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_verify(ssl, buf,
+                                                            buf + buf_len, verify_buffer,
+                                                            verify_buffer_len));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                            MBEDTLS_SSL_HS_CERTIFICATE_VERIFY,
+                                                            buf, buf_len));
+
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate verify"));
+    MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_process_certificate_verify", ret);
+    return ret;
+#else
+    ((void) ssl);
+    MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+}
+
+/*
+ *
+ * STATE HANDLING: Incoming Certificate.
+ *
+ */
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+/*
+ * Structure of Certificate message:
+ *
+ * enum {
+ *     X509(0),
+ *     RawPublicKey(2),
+ *     (255)
+ * } CertificateType;
+ *
+ * struct {
+ *     select (certificate_type) {
+ *         case RawPublicKey:
+ *           * From RFC 7250 ASN.1_subjectPublicKeyInfo *
+ *           opaque ASN1_subjectPublicKeyInfo<1..2^24-1>;
+ *         case X509:
+ *           opaque cert_data<1..2^24-1>;
+ *     };
+ *     Extension extensions<0..2^16-1>;
+ * } CertificateEntry;
+ *
+ * struct {
+ *     opaque certificate_request_context<0..2^8-1>;
+ *     CertificateEntry certificate_list<0..2^24-1>;
+ * } Certificate;
+ *
+ */
+
+/* Parse certificate chain send by the server. */
+MBEDTLS_CHECK_RETURN_CRITICAL
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl,
+                                        const unsigned char *buf,
+                                        const unsigned char *end)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t certificate_request_context_len = 0;
+    size_t certificate_list_len = 0;
+    const unsigned char *p = buf;
+    const unsigned char *certificate_list_end;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4);
+    certificate_request_context_len = p[0];
+    certificate_list_len = MBEDTLS_GET_UINT24_BE(p, 1);
+    p += 4;
+
+    /* In theory, the certificate list can be up to 2^24 Bytes, but we don't
+     * support anything beyond 2^16 = 64K.
+     */
+    if ((certificate_request_context_len != 0) ||
+        (certificate_list_len >= 0x10000)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
+                                     MBEDTLS_ERR_SSL_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /* In case we tried to reuse a session but it failed */
+    if (ssl->session_negotiate->peer_cert != NULL) {
+        mbedtls_x509_crt_free(ssl->session_negotiate->peer_cert);
+        mbedtls_free(ssl->session_negotiate->peer_cert);
+    }
+
+    if (certificate_list_len == 0) {
+        ssl->session_negotiate->peer_cert = NULL;
+        ret = 0;
+        goto exit;
+    }
+
+    if ((ssl->session_negotiate->peer_cert =
+             mbedtls_calloc(1, sizeof(mbedtls_x509_crt))) == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("alloc( %" MBEDTLS_PRINTF_SIZET " bytes ) failed",
+                                  sizeof(mbedtls_x509_crt)));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR,
+                                     MBEDTLS_ERR_SSL_ALLOC_FAILED);
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+    }
+
+    mbedtls_x509_crt_init(ssl->session_negotiate->peer_cert);
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, certificate_list_len);
+    certificate_list_end = p + certificate_list_len;
+    while (p < certificate_list_end) {
+        size_t cert_data_len, extensions_len;
+        const unsigned char *extensions_end;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, 3);
+        cert_data_len = MBEDTLS_GET_UINT24_BE(p, 0);
+        p += 3;
+
+        /* In theory, the CRT can be up to 2^24 Bytes, but we don't support
+         * anything beyond 2^16 = 64K. Otherwise as in the TLS 1.2 code,
+         * check that we have a minimum of 128 bytes of data, this is not
+         * clear why we need that though.
+         */
+        if ((cert_data_len < 128) || (cert_data_len >= 0x10000)) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad Certificate message"));
+            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
+                                         MBEDTLS_ERR_SSL_DECODE_ERROR);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, cert_data_len);
+        ret = mbedtls_x509_crt_parse_der(ssl->session_negotiate->peer_cert,
+                                         p, cert_data_len);
+
+        switch (ret) {
+            case 0: /*ok*/
+                break;
+            case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND:
+                /* Ignore certificate with an unknown algorithm: maybe a
+                   prior certificate was already trusted. */
+                break;
+
+            case MBEDTLS_ERR_X509_ALLOC_FAILED:
+                MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR,
+                                             MBEDTLS_ERR_X509_ALLOC_FAILED);
+                MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret);
+                return ret;
+
+            case MBEDTLS_ERR_X509_UNKNOWN_VERSION:
+                MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT,
+                                             MBEDTLS_ERR_X509_UNKNOWN_VERSION);
+                MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret);
+                return ret;
+
+            default:
+                MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_BAD_CERT,
+                                             ret);
+                MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret);
+                return ret;
+        }
+
+        p += cert_data_len;
+
+        /* Certificate extensions length */
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, 2);
+        extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);
+        p += 2;
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, extensions_len);
+
+        extensions_end = p + extensions_len;
+        handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;
+
+        while (p < extensions_end) {
+            unsigned int extension_type;
+            size_t extension_data_len;
+
+            /*
+             * struct {
+             *     ExtensionType extension_type; (2 bytes)
+             *     opaque extension_data<0..2^16-1>;
+             * } Extension;
+             */
+            MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4);
+            extension_type = MBEDTLS_GET_UINT16_BE(p, 0);
+            extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);
+            p += 4;
+
+            MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len);
+
+            ret = mbedtls_ssl_tls13_check_received_extension(
+                ssl, MBEDTLS_SSL_HS_CERTIFICATE, extension_type,
+                MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CT);
+            if (ret != 0) {
+                return ret;
+            }
+
+            switch (extension_type) {
+                default:
+                    MBEDTLS_SSL_PRINT_EXT(
+                        3, MBEDTLS_SSL_HS_CERTIFICATE,
+                        extension_type, "( ignored )");
+                    break;
+            }
+
+            p += extension_data_len;
+        }
+
+        MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CERTIFICATE,
+                               handshake->received_extensions);
+    }
+
+exit:
+    /* Check that all the message is consumed. */
+    if (p != end) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad Certificate message"));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
+                                     MBEDTLS_ERR_SSL_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    MBEDTLS_SSL_DEBUG_CRT(3, "peer certificate", ssl->session_negotiate->peer_cert);
+
+    return ret;
+}
+#else
+MBEDTLS_CHECK_RETURN_CRITICAL
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl,
+                                        const unsigned char *buf,
+                                        const unsigned char *end)
+{
+    ((void) ssl);
+    ((void) buf);
+    ((void) end);
+    return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+}
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+/* Validate certificate chain sent by the server. */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl)
+{
+    int ret = 0;
+    int authmode = MBEDTLS_SSL_VERIFY_REQUIRED;
+    mbedtls_x509_crt *ca_chain;
+    mbedtls_x509_crl *ca_crl;
+    const char *ext_oid;
+    size_t ext_len;
+    uint32_t verify_result = 0;
+
+    /* If SNI was used, overwrite authentication mode
+     * from the configuration. */
+#if defined(MBEDTLS_SSL_SRV_C)
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+        if (ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET) {
+            authmode = ssl->handshake->sni_authmode;
+        } else
+#endif
+        authmode = ssl->conf->authmode;
+    }
+#endif
+
+    /*
+     * If the peer hasn't sent a certificate ( i.e. it sent
+     * an empty certificate chain ), this is reflected in the peer CRT
+     * structure being unset.
+     * Check for that and handle it depending on the
+     * authentication mode.
+     */
+    if (ssl->session_negotiate->peer_cert == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("peer has no certificate"));
+
+#if defined(MBEDTLS_SSL_SRV_C)
+        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
+            /* The client was asked for a certificate but didn't send
+             * one. The client should know what's going on, so we
+             * don't send an alert.
+             */
+            ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
+            if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL) {
+                return 0;
+            } else {
+                MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_NO_CERT,
+                                             MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE);
+                return MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE;
+            }
+        }
+#endif /* MBEDTLS_SSL_SRV_C */
+
+#if defined(MBEDTLS_SSL_CLI_C)
+        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_NO_CERT,
+                                         MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE);
+            return MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE;
+        }
+#endif /* MBEDTLS_SSL_CLI_C */
+    }
+
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    if (ssl->handshake->sni_ca_chain != NULL) {
+        ca_chain = ssl->handshake->sni_ca_chain;
+        ca_crl = ssl->handshake->sni_ca_crl;
+    } else
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+    {
+        ca_chain = ssl->conf->ca_chain;
+        ca_crl = ssl->conf->ca_crl;
+    }
+
+    /*
+     * Main check: verify certificate
+     */
+    ret = mbedtls_x509_crt_verify_with_profile(
+        ssl->session_negotiate->peer_cert,
+        ca_chain, ca_crl,
+        ssl->conf->cert_profile,
+        ssl->hostname,
+        &verify_result,
+        ssl->conf->f_vrfy, ssl->conf->p_vrfy);
+
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret);
+    }
+
+    /*
+     * Secondary checks: always done, but change 'ret' only if it was 0
+     */
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        ext_oid = MBEDTLS_OID_SERVER_AUTH;
+        ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH);
+    } else {
+        ext_oid = MBEDTLS_OID_CLIENT_AUTH;
+        ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH);
+    }
+
+    if ((mbedtls_x509_crt_check_key_usage(
+             ssl->session_negotiate->peer_cert,
+             MBEDTLS_X509_KU_DIGITAL_SIGNATURE) != 0) ||
+        (mbedtls_x509_crt_check_extended_key_usage(
+             ssl->session_negotiate->peer_cert,
+             ext_oid, ext_len) != 0)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)"));
+        if (ret == 0) {
+            ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
+        }
+    }
+
+    /* mbedtls_x509_crt_verify_with_profile is supposed to report a
+     * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED,
+     * with details encoded in the verification flags. All other kinds
+     * of error codes, including those from the user provided f_vrfy
+     * functions, are treated as fatal and lead to a failure of
+     * mbedtls_ssl_tls13_parse_certificate even if verification was optional.
+     */
+    if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
+        (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
+         ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE)) {
+        ret = 0;
+    }
+
+    if (ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("got no CA chain"));
+        ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
+    }
+
+    if (ret != 0) {
+        /* The certificate may have been rejected for several reasons.
+           Pick one and send the corresponding alert. Which alert to send
+           may be a subject of debate in some cases. */
+        if (verify_result & MBEDTLS_X509_BADCERT_OTHER) {
+            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED, ret);
+        } else if (verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) {
+            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_BAD_CERT, ret);
+        } else if (verify_result & (MBEDTLS_X509_BADCERT_KEY_USAGE |
+                                    MBEDTLS_X509_BADCERT_EXT_KEY_USAGE |
+                                    MBEDTLS_X509_BADCERT_NS_CERT_TYPE |
+                                    MBEDTLS_X509_BADCERT_BAD_PK |
+                                    MBEDTLS_X509_BADCERT_BAD_KEY)) {
+            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT, ret);
+        } else if (verify_result & MBEDTLS_X509_BADCERT_EXPIRED) {
+            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED, ret);
+        } else if (verify_result & MBEDTLS_X509_BADCERT_REVOKED) {
+            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED, ret);
+        } else if (verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
+            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA, ret);
+        } else {
+            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN, ret);
+        }
+    }
+
+#if defined(MBEDTLS_DEBUG_C)
+    if (verify_result != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x",
+                                  (unsigned int) verify_result));
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear"));
+    }
+#endif /* MBEDTLS_DEBUG_C */
+
+    ssl->session_negotiate->verify_result = verify_result;
+    return ret;
+}
+#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl)
+{
+    ((void) ssl);
+    return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+}
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+
+int mbedtls_ssl_tls13_process_certificate(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate"));
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+    unsigned char *buf;
+    size_t buf_len;
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(
+                             ssl, MBEDTLS_SSL_HS_CERTIFICATE,
+                             &buf, &buf_len));
+
+    /* Parse the certificate chain sent by the peer. */
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_parse_certificate(ssl, buf,
+                                                             buf + buf_len));
+    /* Validate the certificate chain and set the verification results. */
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_validate_certificate(ssl));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                            MBEDTLS_SSL_HS_CERTIFICATE, buf,
+                                                            buf_len));
+
+cleanup:
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate"));
+    return ret;
+}
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+/*
+ *  enum {
+ *        X509(0),
+ *        RawPublicKey(2),
+ *        (255)
+ *    } CertificateType;
+ *
+ *    struct {
+ *        select (certificate_type) {
+ *            case RawPublicKey:
+ *              // From RFC 7250 ASN.1_subjectPublicKeyInfo
+ *              opaque ASN1_subjectPublicKeyInfo<1..2^24-1>;
+ *
+ *            case X509:
+ *              opaque cert_data<1..2^24-1>;
+ *        };
+ *        Extension extensions<0..2^16-1>;
+ *    } CertificateEntry;
+ *
+ *    struct {
+ *        opaque certificate_request_context<0..2^8-1>;
+ *        CertificateEntry certificate_list<0..2^24-1>;
+ *    } Certificate;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_certificate_body(mbedtls_ssl_context *ssl,
+                                            unsigned char *buf,
+                                            unsigned char *end,
+                                            size_t *out_len)
+{
+    const mbedtls_x509_crt *crt = mbedtls_ssl_own_cert(ssl);
+    unsigned char *p = buf;
+    unsigned char *certificate_request_context =
+        ssl->handshake->certificate_request_context;
+    unsigned char certificate_request_context_len =
+        ssl->handshake->certificate_request_context_len;
+    unsigned char *p_certificate_list_len;
+
+
+    /* ...
+     * opaque certificate_request_context<0..2^8-1>;
+     * ...
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, certificate_request_context_len + 1);
+    *p++ = certificate_request_context_len;
+    if (certificate_request_context_len > 0) {
+        memcpy(p, certificate_request_context, certificate_request_context_len);
+        p += certificate_request_context_len;
+    }
+
+    /* ...
+     * CertificateEntry certificate_list<0..2^24-1>;
+     * ...
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 3);
+    p_certificate_list_len = p;
+    p += 3;
+
+    MBEDTLS_SSL_DEBUG_CRT(3, "own certificate", crt);
+
+    while (crt != NULL) {
+        size_t cert_data_len = crt->raw.len;
+
+        MBEDTLS_SSL_CHK_BUF_PTR(p, end, cert_data_len + 3 + 2);
+        MBEDTLS_PUT_UINT24_BE(cert_data_len, p, 0);
+        p += 3;
+
+        memcpy(p, crt->raw.p, cert_data_len);
+        p += cert_data_len;
+        crt = crt->next;
+
+        /* Currently, we don't have any certificate extensions defined.
+         * Hence, we are sending an empty extension with length zero.
+         */
+        MBEDTLS_PUT_UINT16_BE(0, p, 0);
+        p += 2;
+    }
+
+    MBEDTLS_PUT_UINT24_BE(p - p_certificate_list_len - 3,
+                          p_certificate_list_len, 0);
+
+    *out_len = p - buf;
+
+    MBEDTLS_SSL_PRINT_EXTS(
+        3, MBEDTLS_SSL_HS_CERTIFICATE, ssl->handshake->sent_extensions);
+
+    return 0;
+}
+
+int mbedtls_ssl_tls13_write_certificate(mbedtls_ssl_context *ssl)
+{
+    int ret;
+    unsigned char *buf;
+    size_t buf_len, msg_len;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate"));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl,
+                                                         MBEDTLS_SSL_HS_CERTIFICATE, &buf,
+                                                         &buf_len));
+
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_body(ssl,
+                                                          buf,
+                                                          buf + buf_len,
+                                                          &msg_len));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                            MBEDTLS_SSL_HS_CERTIFICATE, buf,
+                                                            msg_len));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
+                             ssl, buf_len, msg_len));
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate"));
+    return ret;
+}
+
+/*
+ * STATE HANDLING: Output Certificate Verify
+ */
+int mbedtls_ssl_tls13_check_sig_alg_cert_key_match(uint16_t sig_alg,
+                                                   mbedtls_pk_context *key)
+{
+    mbedtls_pk_type_t pk_type = mbedtls_ssl_sig_from_pk(key);
+    size_t key_size = mbedtls_pk_get_bitlen(key);
+
+    switch (pk_type) {
+        case MBEDTLS_SSL_SIG_ECDSA:
+            switch (key_size) {
+                case 256:
+                    return
+                        sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256;
+
+                case 384:
+                    return
+                        sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384;
+
+                case 521:
+                    return
+                        sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512;
+                default:
+                    break;
+            }
+            break;
+
+        case MBEDTLS_SSL_SIG_RSA:
+            switch (sig_alg) {
+                case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: /* Intentional fallthrough */
+                case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: /* Intentional fallthrough */
+                case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512:
+                    return 1;
+
+                default:
+                    break;
+            }
+            break;
+
+        default:
+            break;
+    }
+
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_certificate_verify_body(mbedtls_ssl_context *ssl,
+                                                   unsigned char *buf,
+                                                   unsigned char *end,
+                                                   size_t *out_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *p = buf;
+    mbedtls_pk_context *own_key;
+
+    unsigned char handshake_hash[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+    size_t handshake_hash_len;
+    unsigned char verify_buffer[SSL_VERIFY_STRUCT_MAX_SIZE];
+    size_t verify_buffer_len;
+
+    uint16_t *sig_alg = ssl->handshake->received_sig_algs;
+    size_t signature_len = 0;
+
+    *out_len = 0;
+
+    own_key = mbedtls_ssl_own_key(ssl);
+    if (own_key == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    ret = mbedtls_ssl_get_handshake_transcript(ssl,
+                                               ssl->handshake->ciphersuite_info->mac,
+                                               handshake_hash,
+                                               sizeof(handshake_hash),
+                                               &handshake_hash_len);
+    if (ret != 0) {
+        return ret;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "handshake hash",
+                          handshake_hash,
+                          handshake_hash_len);
+
+    ssl_tls13_create_verify_structure(handshake_hash, handshake_hash_len,
+                                      verify_buffer, &verify_buffer_len,
+                                      ssl->conf->endpoint);
+
+    /*
+     *  struct {
+     *    SignatureScheme algorithm;
+     *    opaque signature<0..2^16-1>;
+     *  } CertificateVerify;
+     */
+    /* Check there is space for the algorithm identifier (2 bytes) and the
+     * signature length (2 bytes).
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4);
+
+    for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) {
+        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+        mbedtls_pk_type_t pk_type = MBEDTLS_PK_NONE;
+        mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;
+        psa_algorithm_t psa_algorithm = PSA_ALG_NONE;
+        unsigned char verify_hash[PSA_HASH_MAX_SIZE];
+        size_t verify_hash_len;
+
+        if (!mbedtls_ssl_sig_alg_is_offered(ssl, *sig_alg)) {
+            continue;
+        }
+
+        if (!mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(*sig_alg)) {
+            continue;
+        }
+
+        if (!mbedtls_ssl_tls13_check_sig_alg_cert_key_match(*sig_alg, own_key)) {
+            continue;
+        }
+
+        if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg(
+                *sig_alg, &pk_type, &md_alg) != 0) {
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        }
+
+        /* Hash verify buffer with indicated hash function */
+        psa_algorithm = mbedtls_hash_info_psa_from_md(md_alg);
+        status = psa_hash_compute(psa_algorithm,
+                                  verify_buffer,
+                                  verify_buffer_len,
+                                  verify_hash, sizeof(verify_hash),
+                                  &verify_hash_len);
+        if (status != PSA_SUCCESS) {
+            return PSA_TO_MBEDTLS_ERR(status);
+        }
+
+        MBEDTLS_SSL_DEBUG_BUF(3, "verify hash", verify_hash, verify_hash_len);
+
+        if ((ret = mbedtls_pk_sign_ext(pk_type, own_key,
+                                       md_alg, verify_hash, verify_hash_len,
+                                       p + 4, (size_t) (end - (p + 4)), &signature_len,
+                                       ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("CertificateVerify signature failed with %s",
+                                      mbedtls_ssl_sig_alg_to_str(*sig_alg)));
+            MBEDTLS_SSL_DEBUG_RET(2, "mbedtls_pk_sign_ext", ret);
+
+            /* The signature failed. This is possible if the private key
+             * was not suitable for the signature operation as purposely we
+             * did not check its suitability completely. Let's try with
+             * another signature algorithm.
+             */
+            continue;
+        }
+
+        MBEDTLS_SSL_DEBUG_MSG(2, ("CertificateVerify signature with %s",
+                                  mbedtls_ssl_sig_alg_to_str(*sig_alg)));
+
+        break;
+    }
+
+    if (*sig_alg == MBEDTLS_TLS1_3_SIG_NONE) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("no suitable signature algorithm"));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
+                                     MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+    MBEDTLS_PUT_UINT16_BE(*sig_alg, p, 0);
+    MBEDTLS_PUT_UINT16_BE(signature_len, p, 2);
+
+    *out_len = 4 + signature_len;
+
+    return 0;
+}
+
+int mbedtls_ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl)
+{
+    int ret = 0;
+    unsigned char *buf;
+    size_t buf_len, msg_len;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate verify"));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl,
+                                                         MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, &buf,
+                                                         &buf_len));
+
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_verify_body(
+                             ssl, buf, buf + buf_len, &msg_len));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                            MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, buf,
+                                                            msg_len));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
+                             ssl, buf_len, msg_len));
+
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate verify"));
+    return ret;
+}
+
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+
+/*
+ *
+ * STATE HANDLING: Incoming Finished message.
+ */
+/*
+ * Implementation
+ */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_preprocess_finished_message(mbedtls_ssl_context *ssl)
+{
+    int ret;
+
+    ret = mbedtls_ssl_tls13_calculate_verify_data(ssl,
+                                                  ssl->handshake->state_local.finished_in.digest,
+                                                  sizeof(ssl->handshake->state_local.finished_in.
+                                                         digest),
+                                                  &ssl->handshake->state_local.finished_in.digest_len,
+                                                  ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ?
+                                                  MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_calculate_verify_data", ret);
+        return ret;
+    }
+
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_finished_message(mbedtls_ssl_context *ssl,
+                                            const unsigned char *buf,
+                                            const unsigned char *end)
+{
+    /*
+     * struct {
+     *     opaque verify_data[Hash.length];
+     * } Finished;
+     */
+    const unsigned char *expected_verify_data =
+        ssl->handshake->state_local.finished_in.digest;
+    size_t expected_verify_data_len =
+        ssl->handshake->state_local.finished_in.digest_len;
+    /* Structural validation */
+    if ((size_t) (end - buf) != expected_verify_data_len) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message"));
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
+                                     MBEDTLS_ERR_SSL_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "verify_data (self-computed):",
+                          expected_verify_data,
+                          expected_verify_data_len);
+    MBEDTLS_SSL_DEBUG_BUF(4, "verify_data (received message):", buf,
+                          expected_verify_data_len);
+
+    /* Semantic validation */
+    if (mbedtls_ct_memcmp(buf,
+                          expected_verify_data,
+                          expected_verify_data_len) != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message"));
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR,
+                                     MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+    return 0;
+}
+
+int mbedtls_ssl_tls13_process_finished_message(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *buf;
+    size_t buf_len;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse finished message"));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(ssl,
+                                                               MBEDTLS_SSL_HS_FINISHED,
+                                                               &buf, &buf_len));
+
+    /* Preprocessing step: Compute handshake digest */
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_preprocess_finished_message(ssl));
+
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_finished_message(ssl, buf, buf + buf_len));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                            MBEDTLS_SSL_HS_FINISHED, buf, buf_len));
+
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse finished message"));
+    return ret;
+}
+
+/*
+ *
+ * STATE HANDLING: Write and send Finished message.
+ *
+ */
+/*
+ * Implement
+ */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_prepare_finished_message(mbedtls_ssl_context *ssl)
+{
+    int ret;
+
+    /* Compute transcript of handshake up to now. */
+    ret = mbedtls_ssl_tls13_calculate_verify_data(ssl,
+                                                  ssl->handshake->state_local.finished_out.digest,
+                                                  sizeof(ssl->handshake->state_local.finished_out.
+                                                         digest),
+                                                  &ssl->handshake->state_local.finished_out.digest_len,
+                                                  ssl->conf->endpoint);
+
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "calculate_verify_data failed", ret);
+        return ret;
+    }
+
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_finished_message_body(mbedtls_ssl_context *ssl,
+                                                 unsigned char *buf,
+                                                 unsigned char *end,
+                                                 size_t *out_len)
+{
+    size_t verify_data_len = ssl->handshake->state_local.finished_out.digest_len;
+    /*
+     * struct {
+     *     opaque verify_data[Hash.length];
+     * } Finished;
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(buf, end, verify_data_len);
+
+    memcpy(buf, ssl->handshake->state_local.finished_out.digest,
+           verify_data_len);
+
+    *out_len = verify_data_len;
+    return 0;
+}
+
+/* Main entry point: orchestrates the other functions */
+int mbedtls_ssl_tls13_write_finished_message(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *buf;
+    size_t buf_len, msg_len;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write finished message"));
+
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_finished_message(ssl));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl,
+                                                         MBEDTLS_SSL_HS_FINISHED, &buf, &buf_len));
+
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_finished_message_body(
+                             ssl, buf, buf + buf_len, &msg_len));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
+                                                            MBEDTLS_SSL_HS_FINISHED, buf, msg_len));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
+                             ssl, buf_len, msg_len));
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write finished message"));
+    return ret;
+}
+
+void mbedtls_ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl)
+{
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup"));
+
+    MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to application keys for inbound traffic"));
+    mbedtls_ssl_set_inbound_transform(ssl, ssl->transform_application);
+
+    MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to application keys for outbound traffic"));
+    mbedtls_ssl_set_outbound_transform(ssl, ssl->transform_application);
+
+    /*
+     * Free the previous session and switch to the current one.
+     */
+    if (ssl->session) {
+        mbedtls_ssl_session_free(ssl->session);
+        mbedtls_free(ssl->session);
+    }
+    ssl->session = ssl->session_negotiate;
+    ssl->session_negotiate = NULL;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup"));
+}
+
+/*
+ *
+ * STATE HANDLING: Write ChangeCipherSpec
+ *
+ */
+#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_change_cipher_spec_body(mbedtls_ssl_context *ssl,
+                                                   unsigned char *buf,
+                                                   unsigned char *end,
+                                                   size_t *olen)
+{
+    ((void) ssl);
+
+    MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 1);
+    buf[0] = 1;
+    *olen = 1;
+
+    return 0;
+}
+
+int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write change cipher spec"));
+
+    /* Write CCS message */
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_change_cipher_spec_body(
+                             ssl, ssl->out_msg,
+                             ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN,
+                             &ssl->out_msglen));
+
+    ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;
+
+    /* Dispatch message */
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_record(ssl, 0));
+
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write change cipher spec"));
+    return ret;
+}
+
+#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
+
+/* Early Data Indication Extension
+ *
+ * struct {
+ *   select ( Handshake.msg_type ) {
+ *     ...
+ *     case client_hello:         Empty;
+ *     case encrypted_extensions: Empty;
+ *   };
+ * } EarlyDataIndication;
+ */
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl,
+                                           unsigned char *buf,
+                                           const unsigned char *end,
+                                           size_t *out_len)
+{
+    unsigned char *p = buf;
+    *out_len = 0;
+    ((void) ssl);
+
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4);
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_EARLY_DATA, p, 0);
+    MBEDTLS_PUT_UINT16_BE(0, p, 2);
+
+    *out_len = 4;
+
+    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_EARLY_DATA);
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
+/* Reset SSL context and update hash for handling HRR.
+ *
+ * Replace Transcript-Hash(X) by
+ * Transcript-Hash( message_hash     ||
+ *                 00 00 Hash.length ||
+ *                 X )
+ * A few states of the handshake are preserved, including:
+ *   - session ID
+ *   - session ticket
+ *   - negotiated ciphersuite
+ */
+int mbedtls_ssl_reset_transcript_for_hrr(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char hash_transcript[PSA_HASH_MAX_SIZE + 4];
+    size_t hash_len;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("Reset SSL session for HRR"));
+
+    ret = mbedtls_ssl_get_handshake_transcript(ssl, ciphersuite_info->mac,
+                                               hash_transcript + 4,
+                                               PSA_HASH_MAX_SIZE,
+                                               &hash_len);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_handshake_transcript", ret);
+        return ret;
+    }
+
+    hash_transcript[0] = MBEDTLS_SSL_HS_MESSAGE_HASH;
+    hash_transcript[1] = 0;
+    hash_transcript[2] = 0;
+    hash_transcript[3] = (unsigned char) hash_len;
+
+    hash_len += 4;
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "Truncated handshake transcript",
+                          hash_transcript, hash_len);
+
+    /* Reset running hash and replace it with a hash of the transcript */
+    ret = mbedtls_ssl_reset_checksum(ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_reset_checksum", ret);
+        return ret;
+    }
+    ret = ssl->handshake->update_checksum(ssl, hash_transcript, hash_len);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret);
+        return ret;
+    }
+
+    return ret;
+}
+
+#if defined(MBEDTLS_ECDH_C)
+
+int mbedtls_ssl_tls13_read_public_ecdhe_share(mbedtls_ssl_context *ssl,
+                                              const unsigned char *buf,
+                                              size_t buf_len)
+{
+    uint8_t *p = (uint8_t *) buf;
+    const uint8_t *end = buf + buf_len;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+    /* Get size of the TLS opaque key_exchange field of the KeyShareEntry struct. */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    uint16_t peerkey_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+
+    /* Check if key size is consistent with given buffer length. */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, peerkey_len);
+
+    /* Store peer's ECDH public key. */
+    memcpy(handshake->ecdh_psa_peerkey, p, peerkey_len);
+    handshake->ecdh_psa_peerkey_len = peerkey_len;
+
+    return 0;
+}
+
+int mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange(
+    mbedtls_ssl_context *ssl,
+    uint16_t named_group,
+    unsigned char *buf,
+    unsigned char *end,
+    size_t *out_len)
+{
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    psa_key_attributes_t key_attributes;
+    size_t own_pubkey_len;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    psa_ecc_family_t ec_psa_family = 0;
+    size_t ec_bits = 0;
+
+    MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH computation."));
+
+    /* Convert EC's TLS ID to PSA key type. */
+    if (mbedtls_ssl_get_psa_curve_info_from_tls_id(named_group,
+                                                   &ec_psa_family,
+                                                   &ec_bits) == PSA_ERROR_NOT_SUPPORTED) {
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+    handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR(ec_psa_family);
+    ssl->handshake->ecdh_bits = ec_bits;
+
+    key_attributes = psa_key_attributes_init();
+    psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
+    psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
+    psa_set_key_type(&key_attributes, handshake->ecdh_psa_type);
+    psa_set_key_bits(&key_attributes, handshake->ecdh_bits);
+
+    /* Generate ECDH private key. */
+    status = psa_generate_key(&key_attributes,
+                              &handshake->ecdh_psa_privkey);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        MBEDTLS_SSL_DEBUG_RET(1, "psa_generate_key", ret);
+        return ret;
+
+    }
+
+    /* Export the public part of the ECDH private key from PSA. */
+    status = psa_export_public_key(handshake->ecdh_psa_privkey,
+                                   buf, (size_t) (end - buf),
+                                   &own_pubkey_len);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        MBEDTLS_SSL_DEBUG_RET(1, "psa_export_public_key", ret);
+        return ret;
+
+    }
+
+    *out_len = own_pubkey_len;
+
+    return 0;
+}
+#endif /* MBEDTLS_ECDH_C */
+
+/* RFC 8446 section 4.2
+ *
+ * If an implementation receives an extension which it recognizes and which is
+ * not specified for the message in which it appears, it MUST abort the handshake
+ * with an "illegal_parameter" alert.
+ *
+ */
+int mbedtls_ssl_tls13_check_received_extension(
+    mbedtls_ssl_context *ssl,
+    int hs_msg_type,
+    unsigned int received_extension_type,
+    uint32_t hs_msg_allowed_extensions_mask)
+{
+    uint32_t extension_mask = mbedtls_ssl_get_extension_mask(
+        received_extension_type);
+
+    MBEDTLS_SSL_PRINT_EXT(
+        3, hs_msg_type, received_extension_type, "received");
+
+    if ((extension_mask & hs_msg_allowed_extensions_mask) == 0) {
+        MBEDTLS_SSL_PRINT_EXT(
+            3, hs_msg_type, received_extension_type, "is illegal");
+        MBEDTLS_SSL_PEND_FATAL_ALERT(
+            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+            MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    ssl->handshake->received_extensions |= extension_mask;
+    /*
+     * If it is a message containing extension responses, check that we
+     * previously sent the extension.
+     */
+    switch (hs_msg_type) {
+        case MBEDTLS_SSL_HS_SERVER_HELLO:
+        case MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST:
+        case MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS:
+        case MBEDTLS_SSL_HS_CERTIFICATE:
+            /* Check if the received extension is sent by peer message.*/
+            if ((ssl->handshake->sent_extensions & extension_mask) != 0) {
+                return 0;
+            }
+            break;
+        default:
+            return 0;
+    }
+
+    MBEDTLS_SSL_PRINT_EXT(
+        3, hs_msg_type, received_extension_type, "is unsupported");
+    MBEDTLS_SSL_PEND_FATAL_ALERT(
+        MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT,
+        MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION);
+    return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION;
+}
+
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+/* RFC 8449, section 4:
+ *
+ * The ExtensionData of the "record_size_limit" extension is
+ * RecordSizeLimit:
+ *     uint16 RecordSizeLimit;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_parse_record_size_limit_ext(mbedtls_ssl_context *ssl,
+                                                  const unsigned char *buf,
+                                                  const unsigned char *end)
+{
+    const unsigned char *p = buf;
+    uint16_t record_size_limit;
+    const size_t extension_data_len = end - buf;
+
+    if (extension_data_len != MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH) {
+        MBEDTLS_SSL_DEBUG_MSG(2,
+                              ("record_size_limit extension has invalid length: %"
+                               MBEDTLS_PRINTF_SIZET " Bytes",
+                               extension_data_len));
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT(
+            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+            MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    record_size_limit = MBEDTLS_GET_UINT16_BE(p, 0);
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("RecordSizeLimit: %u Bytes", record_size_limit));
+
+    /* RFC 8449, section 4
+     *
+     * Endpoints MUST NOT send a "record_size_limit" extension with a value
+     * smaller than 64.  An endpoint MUST treat receipt of a smaller value
+     * as a fatal error and generate an "illegal_parameter" alert.
+     */
+    if (record_size_limit < MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN) {
+        MBEDTLS_SSL_PEND_FATAL_ALERT(
+            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+            MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(2,
+                          (
+                              "record_size_limit extension is still in development. Aborting handshake."));
+
+    MBEDTLS_SSL_PEND_FATAL_ALERT(
+        MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT,
+        MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION);
+    return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION;
+}
+#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
+
+#endif /* MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_PROTO_TLS1_3 */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls13_invasive.h b/lib/libmbedtls/mbedtls/library/ssl_tls13_invasive.h
new file mode 100644
index 0000000..3fb79a9
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls13_invasive.h
@@ -0,0 +1,35 @@
+/*
+ *  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_SSL_TLS13_INVASIVE_H
+#define MBEDTLS_SSL_TLS13_INVASIVE_H
+
+#include "common.h"
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+
+#include "psa/crypto.h"
+
+#if defined(MBEDTLS_TEST_HOOKS)
+int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl,
+                                        const unsigned char *buf,
+                                        const unsigned char *end);
+#endif /* MBEDTLS_TEST_HOOKS */
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+#endif /* MBEDTLS_SSL_TLS13_INVASIVE_H */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c b/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c
index 3de6f03..6edce50 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c
@@ -19,19 +19,30 @@
 
 #include "common.h"
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
-
-#include "mbedtls/hkdf.h"
-#include "mbedtls/ssl_internal.h"
-#include "ssl_tls13_keys.h"
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
 
 #include <stdint.h>
 #include <string.h>
 
-#define MBEDTLS_SSL_TLS1_3_LABEL( name, string )       \
+#include "mbedtls/hkdf.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
+#include "mbedtls/platform.h"
+
+#include "ssl_misc.h"
+#include "ssl_tls13_keys.h"
+#include "ssl_tls13_invasive.h"
+
+#include "psa/crypto.h"
+
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_ssl_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+
+#define MBEDTLS_SSL_TLS1_3_LABEL(name, string)       \
     .name = string,
 
-struct mbedtls_ssl_tls1_3_labels_struct const mbedtls_ssl_tls1_3_labels =
+struct mbedtls_ssl_tls13_labels_struct const mbedtls_ssl_tls13_labels =
 {
     /* This seems to work in C, despite the string literal being one
      * character too long due to the 0-termination. */
@@ -58,48 +69,48 @@
  *                   255 Bytes, so we require `desired_length` to be at most
  *                   255. This allows us to save a few Bytes of code by
  *                   hardcoding the writing of the high bytes.
- * - (label, llen): label + label length, without "tls13 " prefix
- *                  The label length MUST be less than or equal to
- *                  MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN
- *                  It is the caller's responsibility to ensure this.
- *                  All (label, label length) pairs used in TLS 1.3
- *                  can be obtained via MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN().
- * - (ctx, clen): context + context length
- *                The context length MUST be less than or equal to
- *                MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN
- *                It is the caller's responsibility to ensure this.
+ * - (label, label_len): label + label length, without "tls13 " prefix
+ *                       The label length MUST be less than or equal to
+ *                       MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN
+ *                       It is the caller's responsibility to ensure this.
+ *                       All (label, label length) pairs used in TLS 1.3
+ *                       can be obtained via MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN().
+ * - (ctx, ctx_len): context + context length
+ *                   The context length MUST be less than or equal to
+ *                   MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN
+ *                   It is the caller's responsibility to ensure this.
  * - dst: Target buffer for HkdfLabel structure,
  *        This MUST be a writable buffer of size
  *        at least SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN Bytes.
- * - dlen: Pointer at which to store the actual length of
- *         the HkdfLabel structure on success.
+ * - dst_len: Pointer at which to store the actual length of
+ *            the HkdfLabel structure on success.
  */
 
-static const char tls1_3_label_prefix[6] = "tls13 ";
+static const char tls13_label_prefix[6] = "tls13 ";
 
-#define SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( label_len, context_len ) \
-    (   2                  /* expansion length           */ \
-      + 1                  /* label length               */ \
-      + label_len                                           \
-      + 1                  /* context length             */ \
-      + context_len )
+#define SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN(label_len, context_len) \
+    (2                     /* expansion length           */ \
+     + 1                   /* label length               */ \
+     + label_len                                           \
+     + 1                   /* context length             */ \
+     + context_len)
 
 #define SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN                      \
     SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN(                             \
-                     sizeof(tls1_3_label_prefix) +                      \
-                     MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN,     \
-                     MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN )
+        sizeof(tls13_label_prefix) +                       \
+        MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN,     \
+        MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN)
 
-static void ssl_tls1_3_hkdf_encode_label(
-                            size_t desired_length,
-                            const unsigned char *label, size_t llen,
-                            const unsigned char *ctx, size_t clen,
-                            unsigned char *dst, size_t *dlen )
+static void ssl_tls13_hkdf_encode_label(
+    size_t desired_length,
+    const unsigned char *label, size_t label_len,
+    const unsigned char *ctx, size_t ctx_len,
+    unsigned char *dst, size_t *dst_len)
 {
     size_t total_label_len =
-        sizeof(tls1_3_label_prefix) + llen;
+        sizeof(tls13_label_prefix) + label_len;
     size_t total_hkdf_lbl_len =
-        SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( total_label_len, clen );
+        SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN(total_label_len, ctx_len);
 
     unsigned char *p = dst;
 
@@ -107,74 +118,136 @@
      * We're hardcoding the high byte to 0 here assuming that we never use
      * TLS 1.3 HKDF key expansion to more than 255 Bytes. */
 #if MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN > 255
-#error "The implementation of ssl_tls1_3_hkdf_encode_label() is not fit for the \
-        value of MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN"
+#error "The implementation of ssl_tls13_hkdf_encode_label() is not fit for the \
+    value of MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN"
 #endif
 
     *p++ = 0;
-    *p++ = MBEDTLS_BYTE_0( desired_length );
+    *p++ = MBEDTLS_BYTE_0(desired_length);
 
     /* Add label incl. prefix */
-    *p++ = MBEDTLS_BYTE_0( total_label_len );
-    memcpy( p, tls1_3_label_prefix, sizeof(tls1_3_label_prefix) );
-    p += sizeof(tls1_3_label_prefix);
-    memcpy( p, label, llen );
-    p += llen;
+    *p++ = MBEDTLS_BYTE_0(total_label_len);
+    memcpy(p, tls13_label_prefix, sizeof(tls13_label_prefix));
+    p += sizeof(tls13_label_prefix);
+    memcpy(p, label, label_len);
+    p += label_len;
 
     /* Add context value */
-    *p++ = MBEDTLS_BYTE_0( clen );
-    if( clen != 0 )
-        memcpy( p, ctx, clen );
+    *p++ = MBEDTLS_BYTE_0(ctx_len);
+    if (ctx_len != 0) {
+        memcpy(p, ctx, ctx_len);
+    }
 
     /* Return total length to the caller.  */
-    *dlen = total_hkdf_lbl_len;
+    *dst_len = total_hkdf_lbl_len;
 }
 
-int mbedtls_ssl_tls1_3_hkdf_expand_label(
-                     mbedtls_md_type_t hash_alg,
-                     const unsigned char *secret, size_t slen,
-                     const unsigned char *label, size_t llen,
-                     const unsigned char *ctx, size_t clen,
-                     unsigned char *buf, size_t blen )
+int mbedtls_ssl_tls13_hkdf_expand_label(
+    psa_algorithm_t hash_alg,
+    const unsigned char *secret, size_t secret_len,
+    const unsigned char *label, size_t label_len,
+    const unsigned char *ctx, size_t ctx_len,
+    unsigned char *buf, size_t buf_len)
 {
-    const mbedtls_md_info_t *md;
-    unsigned char hkdf_label[ SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN ];
-    size_t hkdf_label_len;
+    unsigned char hkdf_label[SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN];
+    size_t hkdf_label_len = 0;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_derivation_operation_t operation =
+        PSA_KEY_DERIVATION_OPERATION_INIT;
 
-    if( llen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN )
-    {
+    if (label_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN) {
         /* Should never happen since this is an internal
          * function, and we know statically which labels
          * are allowed. */
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    if( clen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN )
-    {
+    if (ctx_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN) {
         /* Should not happen, as above. */
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    if( blen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN )
-    {
+    if (buf_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN) {
         /* Should not happen, as above. */
-        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    md = mbedtls_md_info_from_type( hash_alg );
-    if( md == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    if (!PSA_ALG_IS_HASH(hash_alg)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    ssl_tls1_3_hkdf_encode_label( blen,
-                                  label, llen,
-                                  ctx, clen,
-                                  hkdf_label,
-                                  &hkdf_label_len );
+    ssl_tls13_hkdf_encode_label(buf_len,
+                                label, label_len,
+                                ctx, ctx_len,
+                                hkdf_label,
+                                &hkdf_label_len);
 
-    return( mbedtls_hkdf_expand( md,
-                                 secret, slen,
-                                 hkdf_label, hkdf_label_len,
-                                 buf, blen ) );
+    status = psa_key_derivation_setup(&operation, PSA_ALG_HKDF_EXPAND(hash_alg));
+
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    status = psa_key_derivation_input_bytes(&operation,
+                                            PSA_KEY_DERIVATION_INPUT_SECRET,
+                                            secret,
+                                            secret_len);
+
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    status = psa_key_derivation_input_bytes(&operation,
+                                            PSA_KEY_DERIVATION_INPUT_INFO,
+                                            hkdf_label,
+                                            hkdf_label_len);
+
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    status = psa_key_derivation_output_bytes(&operation,
+                                             buf,
+                                             buf_len);
+
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+cleanup:
+    abort_status = psa_key_derivation_abort(&operation);
+    status = (status == PSA_SUCCESS ? abort_status : status);
+    mbedtls_platform_zeroize(hkdf_label, hkdf_label_len);
+    return PSA_TO_MBEDTLS_ERR(status);
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_make_traffic_key(
+    psa_algorithm_t hash_alg,
+    const unsigned char *secret, size_t secret_len,
+    unsigned char *key, size_t key_len,
+    unsigned char *iv, size_t iv_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    ret = mbedtls_ssl_tls13_hkdf_expand_label(
+        hash_alg,
+        secret, secret_len,
+        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(key),
+        NULL, 0,
+        key, key_len);
+    if (ret != 0) {
+        return ret;
+    }
+
+    ret = mbedtls_ssl_tls13_hkdf_expand_label(
+        hash_alg,
+        secret, secret_len,
+        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(iv),
+        NULL, 0,
+        iv, iv_len);
+    return ret;
 }
 
 /*
@@ -193,157 +266,1596 @@
  * by the function caller. Note that we generate server and client side
  * keys in a single function call.
  */
-int mbedtls_ssl_tls1_3_make_traffic_keys(
-                     mbedtls_md_type_t hash_alg,
-                     const unsigned char *client_secret,
-                     const unsigned char *server_secret,
-                     size_t slen, size_t key_len, size_t iv_len,
-                     mbedtls_ssl_key_set *keys )
+int mbedtls_ssl_tls13_make_traffic_keys(
+    psa_algorithm_t hash_alg,
+    const unsigned char *client_secret,
+    const unsigned char *server_secret, size_t secret_len,
+    size_t key_len, size_t iv_len,
+    mbedtls_ssl_key_set *keys)
 {
     int ret = 0;
 
-    ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
-                    client_secret, slen,
-                    MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ),
-                    NULL, 0,
-                    keys->client_write_key, key_len );
-    if( ret != 0 )
-        return( ret );
+    ret = ssl_tls13_make_traffic_key(
+        hash_alg, client_secret, secret_len,
+        keys->client_write_key, key_len,
+        keys->client_write_iv, iv_len);
+    if (ret != 0) {
+        return ret;
+    }
 
-    ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
-                    server_secret, slen,
-                    MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ),
-                    NULL, 0,
-                    keys->server_write_key, key_len );
-    if( ret != 0 )
-        return( ret );
-
-    ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
-                    client_secret, slen,
-                    MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ),
-                    NULL, 0,
-                    keys->client_write_iv, iv_len );
-    if( ret != 0 )
-        return( ret );
-
-    ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
-                    server_secret, slen,
-                    MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ),
-                    NULL, 0,
-                    keys->server_write_iv, iv_len );
-    if( ret != 0 )
-        return( ret );
+    ret = ssl_tls13_make_traffic_key(
+        hash_alg, server_secret, secret_len,
+        keys->server_write_key, key_len,
+        keys->server_write_iv, iv_len);
+    if (ret != 0) {
+        return ret;
+    }
 
     keys->key_len = key_len;
     keys->iv_len = iv_len;
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_ssl_tls1_3_derive_secret(
-                   mbedtls_md_type_t hash_alg,
-                   const unsigned char *secret, size_t slen,
-                   const unsigned char *label, size_t llen,
-                   const unsigned char *ctx, size_t clen,
-                   int ctx_hashed,
-                   unsigned char *dstbuf, size_t buflen )
+int mbedtls_ssl_tls13_derive_secret(
+    psa_algorithm_t hash_alg,
+    const unsigned char *secret, size_t secret_len,
+    const unsigned char *label, size_t label_len,
+    const unsigned char *ctx, size_t ctx_len,
+    int ctx_hashed,
+    unsigned char *dstbuf, size_t dstbuf_len)
 {
     int ret;
-    unsigned char hashed_context[ MBEDTLS_MD_MAX_SIZE ];
+    unsigned char hashed_context[PSA_HASH_MAX_SIZE];
+    if (ctx_hashed == MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED) {
+        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 
-    const mbedtls_md_info_t *md;
-    md = mbedtls_md_info_from_type( hash_alg );
-    if( md == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    if( ctx_hashed == MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED )
-    {
-        ret = mbedtls_md( md, ctx, clen, hashed_context );
-        if( ret != 0 )
-            return( ret );
-        clen = mbedtls_md_get_size( md );
-    }
-    else
-    {
-        if( clen > sizeof(hashed_context) )
-        {
+        status = psa_hash_compute(hash_alg, ctx, ctx_len, hashed_context,
+                                  PSA_HASH_LENGTH(hash_alg), &ctx_len);
+        if (status != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            return ret;
+        }
+    } else {
+        if (ctx_len > sizeof(hashed_context)) {
             /* This should never happen since this function is internal
              * and the code sets `ctx_hashed` correctly.
              * Let's double-check nonetheless to not run at the risk
              * of getting a stack overflow. */
-            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
         }
 
-        memcpy( hashed_context, ctx, clen );
+        memcpy(hashed_context, ctx, ctx_len);
     }
 
-    return( mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
-                                                  secret, slen,
-                                                  label, llen,
-                                                  hashed_context, clen,
-                                                  dstbuf, buflen ) );
+    return mbedtls_ssl_tls13_hkdf_expand_label(hash_alg,
+                                               secret, secret_len,
+                                               label, label_len,
+                                               hashed_context, ctx_len,
+                                               dstbuf, dstbuf_len);
+
 }
 
-int mbedtls_ssl_tls1_3_evolve_secret(
-                   mbedtls_md_type_t hash_alg,
-                   const unsigned char *secret_old,
-                   const unsigned char *input, size_t input_len,
-                   unsigned char *secret_new )
+int mbedtls_ssl_tls13_evolve_secret(
+    psa_algorithm_t hash_alg,
+    const unsigned char *secret_old,
+    const unsigned char *input, size_t input_len,
+    unsigned char *secret_new)
 {
     int ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-    size_t hlen, ilen;
-    unsigned char tmp_secret[ MBEDTLS_MD_MAX_SIZE ] = { 0 };
-    unsigned char tmp_input [ MBEDTLS_MD_MAX_SIZE ] = { 0 };
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t hlen;
+    unsigned char tmp_secret[PSA_MAC_MAX_SIZE] = { 0 };
+    const unsigned char all_zeroes_input[MBEDTLS_TLS1_3_MD_MAX_SIZE] = { 0 };
+    const unsigned char *l_input = NULL;
+    size_t l_input_len;
 
-    const mbedtls_md_info_t *md;
-    md = mbedtls_md_info_from_type( hash_alg );
-    if( md == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    psa_key_derivation_operation_t operation =
+        PSA_KEY_DERIVATION_OPERATION_INIT;
 
-    hlen = mbedtls_md_get_size( md );
+    if (!PSA_ALG_IS_HASH(hash_alg)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    hlen = PSA_HASH_LENGTH(hash_alg);
 
     /* For non-initial runs, call Derive-Secret( ., "derived", "")
      * on the old secret. */
-    if( secret_old != NULL )
-    {
-        ret = mbedtls_ssl_tls1_3_derive_secret(
-                   hash_alg,
-                   secret_old, hlen,
-                   MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( derived ),
-                   NULL, 0, /* context */
-                   MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,
-                   tmp_secret, hlen );
-        if( ret != 0 )
+    if (secret_old != NULL) {
+        ret = mbedtls_ssl_tls13_derive_secret(
+            hash_alg,
+            secret_old, hlen,
+            MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(derived),
+            NULL, 0,        /* context */
+            MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,
+            tmp_secret, hlen);
+        if (ret != 0) {
             goto cleanup;
+        }
     }
 
-    if( input != NULL )
-    {
-        memcpy( tmp_input, input, input_len );
-        ilen = input_len;
-    }
-    else
-    {
-        ilen = hlen;
-    }
-
-    /* HKDF-Extract takes a salt and input key material.
-     * The salt is the old secret, and the input key material
-     * is the input secret (PSK / ECDHE). */
-    ret = mbedtls_hkdf_extract( md,
-                    tmp_secret, hlen,
-                    tmp_input, ilen,
-                    secret_new );
-    if( ret != 0 )
-        goto cleanup;
-
     ret = 0;
 
- cleanup:
+    if (input != NULL && input_len != 0) {
+        l_input = input;
+        l_input_len = input_len;
+    } else {
+        l_input = all_zeroes_input;
+        l_input_len = hlen;
+    }
 
-    mbedtls_platform_zeroize( tmp_secret, sizeof(tmp_secret) );
-    mbedtls_platform_zeroize( tmp_input,  sizeof(tmp_input)  );
-    return( ret );
+    status = psa_key_derivation_setup(&operation,
+                                      PSA_ALG_HKDF_EXTRACT(hash_alg));
+
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    status = psa_key_derivation_input_bytes(&operation,
+                                            PSA_KEY_DERIVATION_INPUT_SALT,
+                                            tmp_secret,
+                                            hlen);
+
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    status = psa_key_derivation_input_bytes(&operation,
+                                            PSA_KEY_DERIVATION_INPUT_SECRET,
+                                            l_input, l_input_len);
+
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    status = psa_key_derivation_output_bytes(&operation,
+                                             secret_new,
+                                             PSA_HASH_LENGTH(hash_alg));
+
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+cleanup:
+    abort_status = psa_key_derivation_abort(&operation);
+    status = (status == PSA_SUCCESS ? abort_status : status);
+    ret = (ret == 0 ? PSA_TO_MBEDTLS_ERR(status) : ret);
+    mbedtls_platform_zeroize(tmp_secret, sizeof(tmp_secret));
+    return ret;
 }
 
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
+int mbedtls_ssl_tls13_derive_early_secrets(
+    psa_algorithm_t hash_alg,
+    unsigned char const *early_secret,
+    unsigned char const *transcript, size_t transcript_len,
+    mbedtls_ssl_tls13_early_secrets *derived)
+{
+    int ret;
+    size_t const hash_len = PSA_HASH_LENGTH(hash_alg);
+
+    /* We should never call this function with an unknown hash,
+     * but add an assertion anyway. */
+    if (!PSA_ALG_IS_HASH(hash_alg)) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    /*
+     *            0
+     *            |
+     *            v
+     *  PSK ->  HKDF-Extract = Early Secret
+     *            |
+     *            +-----> Derive-Secret(., "c e traffic", ClientHello)
+     *            |                     = client_early_traffic_secret
+     *            |
+     *            +-----> Derive-Secret(., "e exp master", ClientHello)
+     *            |                     = early_exporter_master_secret
+     *            v
+     */
+
+    /* Create client_early_traffic_secret */
+    ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
+                                          early_secret, hash_len,
+                                          MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_e_traffic),
+                                          transcript, transcript_len,
+                                          MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
+                                          derived->client_early_traffic_secret,
+                                          hash_len);
+    if (ret != 0) {
+        return ret;
+    }
+
+    /* Create early exporter */
+    ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
+                                          early_secret, hash_len,
+                                          MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(e_exp_master),
+                                          transcript, transcript_len,
+                                          MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
+                                          derived->early_exporter_master_secret,
+                                          hash_len);
+    if (ret != 0) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int mbedtls_ssl_tls13_derive_handshake_secrets(
+    psa_algorithm_t hash_alg,
+    unsigned char const *handshake_secret,
+    unsigned char const *transcript, size_t transcript_len,
+    mbedtls_ssl_tls13_handshake_secrets *derived)
+{
+    int ret;
+    size_t const hash_len = PSA_HASH_LENGTH(hash_alg);
+
+    /* We should never call this function with an unknown hash,
+     * but add an assertion anyway. */
+    if (!PSA_ALG_IS_HASH(hash_alg)) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    /*
+     *
+     * Handshake Secret
+     * |
+     * +-----> Derive-Secret( ., "c hs traffic",
+     * |                     ClientHello...ServerHello )
+     * |                     = client_handshake_traffic_secret
+     * |
+     * +-----> Derive-Secret( ., "s hs traffic",
+     * |                     ClientHello...ServerHello )
+     * |                     = server_handshake_traffic_secret
+     *
+     */
+
+    /*
+     * Compute client_handshake_traffic_secret with
+     * Derive-Secret( ., "c hs traffic", ClientHello...ServerHello )
+     */
+
+    ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
+                                          handshake_secret, hash_len,
+                                          MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_hs_traffic),
+                                          transcript, transcript_len,
+                                          MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
+                                          derived->client_handshake_traffic_secret,
+                                          hash_len);
+    if (ret != 0) {
+        return ret;
+    }
+
+    /*
+     * Compute server_handshake_traffic_secret with
+     * Derive-Secret( ., "s hs traffic", ClientHello...ServerHello )
+     */
+
+    ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
+                                          handshake_secret, hash_len,
+                                          MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(s_hs_traffic),
+                                          transcript, transcript_len,
+                                          MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
+                                          derived->server_handshake_traffic_secret,
+                                          hash_len);
+    if (ret != 0) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int mbedtls_ssl_tls13_derive_application_secrets(
+    psa_algorithm_t hash_alg,
+    unsigned char const *application_secret,
+    unsigned char const *transcript, size_t transcript_len,
+    mbedtls_ssl_tls13_application_secrets *derived)
+{
+    int ret;
+    size_t const hash_len = PSA_HASH_LENGTH(hash_alg);
+
+    /* We should never call this function with an unknown hash,
+     * but add an assertion anyway. */
+    if (!PSA_ALG_IS_HASH(hash_alg)) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    /* Generate {client,server}_application_traffic_secret_0
+     *
+     * Master Secret
+     * |
+     * +-----> Derive-Secret( ., "c ap traffic",
+     * |                      ClientHello...server Finished )
+     * |                      = client_application_traffic_secret_0
+     * |
+     * +-----> Derive-Secret( ., "s ap traffic",
+     * |                      ClientHello...Server Finished )
+     * |                      = server_application_traffic_secret_0
+     * |
+     * +-----> Derive-Secret( ., "exp master",
+     * |                      ClientHello...server Finished)
+     * |                      = exporter_master_secret
+     *
+     */
+
+    ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
+                                          application_secret, hash_len,
+                                          MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_ap_traffic),
+                                          transcript, transcript_len,
+                                          MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
+                                          derived->client_application_traffic_secret_N,
+                                          hash_len);
+    if (ret != 0) {
+        return ret;
+    }
+
+    ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
+                                          application_secret, hash_len,
+                                          MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(s_ap_traffic),
+                                          transcript, transcript_len,
+                                          MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
+                                          derived->server_application_traffic_secret_N,
+                                          hash_len);
+    if (ret != 0) {
+        return ret;
+    }
+
+    ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
+                                          application_secret, hash_len,
+                                          MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(exp_master),
+                                          transcript, transcript_len,
+                                          MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
+                                          derived->exporter_master_secret,
+                                          hash_len);
+    if (ret != 0) {
+        return ret;
+    }
+
+    return 0;
+}
+
+/* Generate resumption_master_secret for use with the ticket exchange.
+ *
+ * This is not integrated with mbedtls_ssl_tls13_derive_application_secrets()
+ * because it uses the transcript hash up to and including ClientFinished. */
+int mbedtls_ssl_tls13_derive_resumption_master_secret(
+    psa_algorithm_t hash_alg,
+    unsigned char const *application_secret,
+    unsigned char const *transcript, size_t transcript_len,
+    mbedtls_ssl_tls13_application_secrets *derived)
+{
+    int ret;
+    size_t const hash_len = PSA_HASH_LENGTH(hash_alg);
+
+    /* We should never call this function with an unknown hash,
+     * but add an assertion anyway. */
+    if (!PSA_ALG_IS_HASH(hash_alg)) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
+                                          application_secret, hash_len,
+                                          MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(res_master),
+                                          transcript, transcript_len,
+                                          MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
+                                          derived->resumption_master_secret,
+                                          hash_len);
+
+    if (ret != 0) {
+        return ret;
+    }
+
+    return 0;
+}
+
+/**
+ * \brief Transition into application stage of TLS 1.3 key schedule.
+ *
+ *        The TLS 1.3 key schedule can be viewed as a simple state machine
+ *        with states Initial -> Early -> Handshake -> Application, and
+ *        this function represents the Handshake -> Application transition.
+ *
+ *        In the handshake stage, ssl_tls13_generate_application_keys()
+ *        can be used to derive the handshake traffic keys.
+ *
+ * \param ssl  The SSL context to operate on. This must be in key schedule
+ *             stage \c Handshake.
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_key_schedule_stage_application(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    psa_algorithm_t const hash_alg = mbedtls_hash_info_psa_from_md(
+        handshake->ciphersuite_info->mac);
+
+    /*
+     * Compute MasterSecret
+     */
+    ret = mbedtls_ssl_tls13_evolve_secret(hash_alg,
+                                          handshake->tls13_master_secrets.handshake,
+                                          NULL, 0,
+                                          handshake->tls13_master_secrets.app);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret);
+        return ret;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "Master secret",
+                          handshake->tls13_master_secrets.app, PSA_HASH_LENGTH(hash_alg));
+
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_calc_finished_core(psa_algorithm_t hash_alg,
+                                        unsigned char const *base_key,
+                                        unsigned char const *transcript,
+                                        unsigned char *dst,
+                                        size_t *dst_len)
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t hash_len = PSA_HASH_LENGTH(hash_alg);
+    unsigned char finished_key[PSA_MAC_MAX_SIZE];
+    int ret;
+    psa_algorithm_t alg;
+
+    /* We should never call this function with an unknown hash,
+     * but add an assertion anyway. */
+    if (!PSA_ALG_IS_HASH(hash_alg)) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    /* TLS 1.3 Finished message
+     *
+     * struct {
+     *     opaque verify_data[Hash.length];
+     * } Finished;
+     *
+     * verify_data =
+     *     HMAC( finished_key,
+     *            Hash( Handshake Context +
+     *                  Certificate*      +
+     *                  CertificateVerify* )
+     *    )
+     *
+     * finished_key =
+     *    HKDF-Expand-Label( BaseKey, "finished", "", Hash.length )
+     */
+
+    ret = mbedtls_ssl_tls13_hkdf_expand_label(
+        hash_alg, base_key, hash_len,
+        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(finished),
+        NULL, 0,
+        finished_key, hash_len);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    alg = PSA_ALG_HMAC(hash_alg);
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
+
+    status = psa_import_key(&attributes, finished_key, hash_len, &key);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        goto exit;
+    }
+
+    status = psa_mac_compute(key, alg, transcript, hash_len,
+                             dst, hash_len, dst_len);
+    ret = PSA_TO_MBEDTLS_ERR(status);
+
+exit:
+
+    status = psa_destroy_key(key);
+    if (ret == 0) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+    }
+
+    mbedtls_platform_zeroize(finished_key, sizeof(finished_key));
+
+    return ret;
+}
+
+int mbedtls_ssl_tls13_calculate_verify_data(mbedtls_ssl_context *ssl,
+                                            unsigned char *dst,
+                                            size_t dst_len,
+                                            size_t *actual_len,
+                                            int from)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+    size_t transcript_len;
+
+    unsigned char *base_key = NULL;
+    size_t base_key_len = 0;
+    mbedtls_ssl_tls13_handshake_secrets *tls13_hs_secrets =
+        &ssl->handshake->tls13_hs_secrets;
+
+    mbedtls_md_type_t const md_type = ssl->handshake->ciphersuite_info->mac;
+
+    psa_algorithm_t hash_alg = mbedtls_hash_info_psa_from_md(
+        ssl->handshake->ciphersuite_info->mac);
+    size_t const hash_len = PSA_HASH_LENGTH(hash_alg);
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> mbedtls_ssl_tls13_calculate_verify_data"));
+
+    if (from == MBEDTLS_SSL_IS_CLIENT) {
+        base_key = tls13_hs_secrets->client_handshake_traffic_secret;
+        base_key_len = sizeof(tls13_hs_secrets->client_handshake_traffic_secret);
+    } else {
+        base_key = tls13_hs_secrets->server_handshake_traffic_secret;
+        base_key_len = sizeof(tls13_hs_secrets->server_handshake_traffic_secret);
+    }
+
+    if (dst_len < hash_len) {
+        ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+        goto exit;
+    }
+
+    ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type,
+                                               transcript, sizeof(transcript),
+                                               &transcript_len);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_handshake_transcript", ret);
+        goto exit;
+    }
+    MBEDTLS_SSL_DEBUG_BUF(4, "handshake hash", transcript, transcript_len);
+
+    ret = ssl_tls13_calc_finished_core(hash_alg, base_key, transcript, dst, actual_len);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "verify_data for finished message", dst, hash_len);
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= mbedtls_ssl_tls13_calculate_verify_data"));
+
+exit:
+    /* Erase handshake secrets */
+    mbedtls_platform_zeroize(base_key, base_key_len);
+    mbedtls_platform_zeroize(transcript, sizeof(transcript));
+    return ret;
+}
+
+int mbedtls_ssl_tls13_create_psk_binder(mbedtls_ssl_context *ssl,
+                                        const psa_algorithm_t hash_alg,
+                                        unsigned char const *psk, size_t psk_len,
+                                        int psk_type,
+                                        unsigned char const *transcript,
+                                        unsigned char *result)
+{
+    int ret = 0;
+    unsigned char binder_key[PSA_MAC_MAX_SIZE];
+    unsigned char early_secret[PSA_MAC_MAX_SIZE];
+    size_t const hash_len = PSA_HASH_LENGTH(hash_alg);
+    size_t actual_len;
+
+#if !defined(MBEDTLS_DEBUG_C)
+    ssl = NULL; /* make sure we don't use it except for debug */
+    ((void) ssl);
+#endif
+
+    /* We should never call this function with an unknown hash,
+     * but add an assertion anyway. */
+    if (!PSA_ALG_IS_HASH(hash_alg)) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    /*
+     *            0
+     *            |
+     *            v
+     *  PSK ->  HKDF-Extract = Early Secret
+     *            |
+     *            +-----> Derive-Secret(., "ext binder" | "res binder", "")
+     *            |                     = binder_key
+     *            v
+     */
+
+    ret = mbedtls_ssl_tls13_evolve_secret(hash_alg,
+                                          NULL,           /* Old secret */
+                                          psk, psk_len,   /* Input      */
+                                          early_secret);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret);
+        goto exit;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "mbedtls_ssl_tls13_create_psk_binder",
+                          early_secret, hash_len);
+
+    if (psk_type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) {
+        ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
+                                              early_secret, hash_len,
+                                              MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(res_binder),
+                                              NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,
+                                              binder_key, hash_len);
+        MBEDTLS_SSL_DEBUG_MSG(4, ("Derive Early Secret with 'res binder'"));
+    } else {
+        ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
+                                              early_secret, hash_len,
+                                              MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(ext_binder),
+                                              NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,
+                                              binder_key, hash_len);
+        MBEDTLS_SSL_DEBUG_MSG(4, ("Derive Early Secret with 'ext binder'"));
+    }
+
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_derive_secret", ret);
+        goto exit;
+    }
+
+    /*
+     * The binding_value is computed in the same way as the Finished message
+     * but with the BaseKey being the binder_key.
+     */
+
+    ret = ssl_tls13_calc_finished_core(hash_alg, binder_key, transcript,
+                                       result, &actual_len);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "psk binder", result, actual_len);
+
+exit:
+
+    mbedtls_platform_zeroize(early_secret, sizeof(early_secret));
+    mbedtls_platform_zeroize(binder_key,   sizeof(binder_key));
+    return ret;
+}
+
+int mbedtls_ssl_tls13_populate_transform(mbedtls_ssl_transform *transform,
+                                         int endpoint,
+                                         int ciphersuite,
+                                         mbedtls_ssl_key_set const *traffic_keys,
+                                         mbedtls_ssl_context *ssl /* DEBUG ONLY */)
+{
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
+    int ret;
+    mbedtls_cipher_info_t const *cipher_info;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+    unsigned char const *key_enc;
+    unsigned char const *iv_enc;
+    unsigned char const *key_dec;
+    unsigned char const *iv_dec;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_key_type_t key_type;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_algorithm_t alg;
+    size_t key_bits;
+    psa_status_t status = PSA_SUCCESS;
+#endif
+
+#if !defined(MBEDTLS_DEBUG_C)
+    ssl = NULL; /* make sure we don't use it except for those cases */
+    (void) ssl;
+#endif
+
+    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite);
+    if (ciphersuite_info == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("ciphersuite info for %d not found",
+                                  ciphersuite));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
+    cipher_info = mbedtls_cipher_info_from_type(ciphersuite_info->cipher);
+    if (cipher_info == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("cipher info for %u not found",
+                                  ciphersuite_info->cipher));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    /*
+     * Setup cipher contexts in target transform
+     */
+    if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_enc,
+                                    cipher_info)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret);
+        return ret;
+    }
+
+    if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_dec,
+                                    cipher_info)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret);
+        return ret;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_SSL_SRV_C)
+    if (endpoint == MBEDTLS_SSL_IS_SERVER) {
+        key_enc = traffic_keys->server_write_key;
+        key_dec = traffic_keys->client_write_key;
+        iv_enc = traffic_keys->server_write_iv;
+        iv_dec = traffic_keys->client_write_iv;
+    } else
+#endif /* MBEDTLS_SSL_SRV_C */
+#if defined(MBEDTLS_SSL_CLI_C)
+    if (endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        key_enc = traffic_keys->client_write_key;
+        key_dec = traffic_keys->server_write_key;
+        iv_enc = traffic_keys->client_write_iv;
+        iv_dec = traffic_keys->server_write_iv;
+    } else
+#endif /* MBEDTLS_SSL_CLI_C */
+    {
+        /* should not happen */
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    memcpy(transform->iv_enc, iv_enc, traffic_keys->iv_len);
+    memcpy(transform->iv_dec, iv_dec, traffic_keys->iv_len);
+
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
+    if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_enc,
+                                     key_enc, cipher_info->key_bitlen,
+                                     MBEDTLS_ENCRYPT)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret);
+        return ret;
+    }
+
+    if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_dec,
+                                     key_dec, cipher_info->key_bitlen,
+                                     MBEDTLS_DECRYPT)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret);
+        return ret;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    /*
+     * Setup other fields in SSL transform
+     */
+
+    if ((ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG) != 0) {
+        transform->taglen  = 8;
+    } else {
+        transform->taglen  = 16;
+    }
+
+    transform->ivlen       = traffic_keys->iv_len;
+    transform->maclen      = 0;
+    transform->fixed_ivlen = transform->ivlen;
+    transform->tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
+
+    /* We add the true record content type (1 Byte) to the plaintext and
+     * then pad to the configured granularity. The minimum length of the
+     * type-extended and padded plaintext is therefore the padding
+     * granularity. */
+    transform->minlen =
+        transform->taglen + MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    /*
+     * Setup psa keys and alg
+     */
+    if ((status = mbedtls_ssl_cipher_to_psa(ciphersuite_info->cipher,
+                                            transform->taglen,
+                                            &alg,
+                                            &key_type,
+                                            &key_bits)) != PSA_SUCCESS) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_cipher_to_psa", PSA_TO_MBEDTLS_ERR(status));
+        return PSA_TO_MBEDTLS_ERR(status);
+    }
+
+    transform->psa_alg = alg;
+
+    if (alg != MBEDTLS_SSL_NULL_CIPHER) {
+        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
+        psa_set_key_algorithm(&attributes, alg);
+        psa_set_key_type(&attributes, key_type);
+
+        if ((status = psa_import_key(&attributes,
+                                     key_enc,
+                                     PSA_BITS_TO_BYTES(key_bits),
+                                     &transform->psa_key_enc)) != PSA_SUCCESS) {
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status));
+            return PSA_TO_MBEDTLS_ERR(status);
+        }
+
+        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
+
+        if ((status = psa_import_key(&attributes,
+                                     key_dec,
+                                     PSA_BITS_TO_BYTES(key_bits),
+                                     &transform->psa_key_dec)) != PSA_SUCCESS) {
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status));
+            return PSA_TO_MBEDTLS_ERR(status);
+        }
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_get_cipher_key_info(
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info,
+    size_t *key_len, size_t *iv_len)
+{
+    psa_key_type_t key_type;
+    psa_algorithm_t alg;
+    size_t taglen;
+    size_t key_bits;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if (ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG) {
+        taglen = 8;
+    } else {
+        taglen = 16;
+    }
+
+    status = mbedtls_ssl_cipher_to_psa(ciphersuite_info->cipher, taglen,
+                                       &alg, &key_type, &key_bits);
+    if (status != PSA_SUCCESS) {
+        return PSA_TO_MBEDTLS_ERR(status);
+    }
+
+    *key_len = PSA_BITS_TO_BYTES(key_bits);
+
+    /* TLS 1.3 only have AEAD ciphers, IV length is unconditionally 12 bytes */
+    *iv_len = 12;
+
+    return 0;
+}
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+/*
+ * ssl_tls13_generate_early_key() generates the key necessary for protecting
+ * the early application data and handshake messages as described in section 7
+ * of RFC 8446.
+ *
+ * NOTE: Only one key is generated, the key for the traffic from the client to
+ *       the server. The TLS 1.3 specification does not define a secret and thus
+ *       a key for server early traffic.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_generate_early_key(mbedtls_ssl_context *ssl,
+                                        mbedtls_ssl_key_set *traffic_keys)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_md_type_t md_type;
+    psa_algorithm_t hash_alg;
+    size_t hash_len;
+    unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+    size_t transcript_len;
+    size_t key_len;
+    size_t iv_len;
+    mbedtls_ssl_tls13_early_secrets tls13_early_secrets;
+
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_tls13_generate_early_key"));
+
+    ret = ssl_tls13_get_cipher_key_info(ciphersuite_info, &key_len, &iv_len);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_get_cipher_key_info", ret);
+        goto cleanup;
+    }
+
+    md_type = ciphersuite_info->mac;
+
+    hash_alg = mbedtls_hash_info_psa_from_md(ciphersuite_info->mac);
+    hash_len = PSA_HASH_LENGTH(hash_alg);
+
+    ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type,
+                                               transcript,
+                                               sizeof(transcript),
+                                               &transcript_len);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1,
+                              "mbedtls_ssl_get_handshake_transcript",
+                              ret);
+        goto cleanup;
+    }
+
+    ret = mbedtls_ssl_tls13_derive_early_secrets(
+        hash_alg, handshake->tls13_master_secrets.early,
+        transcript, transcript_len, &tls13_early_secrets);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(
+            1, "mbedtls_ssl_tls13_derive_early_secrets", ret);
+        goto cleanup;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(
+        4, "Client early traffic secret",
+        tls13_early_secrets.client_early_traffic_secret, hash_len);
+
+    /*
+     * Export client handshake traffic secret
+     */
+    if (ssl->f_export_keys != NULL) {
+        ssl->f_export_keys(
+            ssl->p_export_keys,
+            MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET,
+            tls13_early_secrets.client_early_traffic_secret,
+            hash_len,
+            handshake->randbytes,
+            handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,
+            MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */);
+    }
+
+    ret = ssl_tls13_make_traffic_key(
+        hash_alg,
+        tls13_early_secrets.client_early_traffic_secret,
+        hash_len, traffic_keys->client_write_key, key_len,
+        traffic_keys->client_write_iv, iv_len);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_make_traffic_key", ret);
+        goto cleanup;
+    }
+    traffic_keys->key_len = key_len;
+    traffic_keys->iv_len = iv_len;
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "client early write_key",
+                          traffic_keys->client_write_key,
+                          traffic_keys->key_len);
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "client early write_iv",
+                          traffic_keys->client_write_iv,
+                          traffic_keys->iv_len);
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_tls13_generate_early_key"));
+
+cleanup:
+    /* Erase early secrets and transcript */
+    mbedtls_platform_zeroize(
+        &tls13_early_secrets, sizeof(mbedtls_ssl_tls13_early_secrets));
+    mbedtls_platform_zeroize(transcript, sizeof(transcript));
+    return ret;
+}
+
+int mbedtls_ssl_tls13_compute_early_transform(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ssl_key_set traffic_keys;
+    mbedtls_ssl_transform *transform_earlydata = NULL;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+    /* Next evolution in key schedule: Establish early_data secret and
+     * key material. */
+    ret = ssl_tls13_generate_early_key(ssl, &traffic_keys);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_generate_early_key",
+                              ret);
+        goto cleanup;
+    }
+
+    transform_earlydata = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform));
+    if (transform_earlydata == NULL) {
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        goto cleanup;
+    }
+
+    ret = mbedtls_ssl_tls13_populate_transform(
+        transform_earlydata,
+        ssl->conf->endpoint,
+        handshake->ciphersuite_info->id,
+        &traffic_keys,
+        ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_populate_transform", ret);
+        goto cleanup;
+    }
+    handshake->transform_earlydata = transform_earlydata;
+
+cleanup:
+    mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys));
+    if (ret != 0) {
+        mbedtls_free(transform_earlydata);
+    }
+
+    return ret;
+}
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
+int mbedtls_ssl_tls13_key_schedule_stage_early(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    psa_algorithm_t hash_alg;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    unsigned char *psk = NULL;
+    size_t psk_len = 0;
+
+    if (handshake->ciphersuite_info == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("cipher suite info not found"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    hash_alg = mbedtls_hash_info_psa_from_md(handshake->ciphersuite_info->mac);
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) {
+        ret = mbedtls_ssl_tls13_export_handshake_psk(ssl, &psk, &psk_len);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_export_handshake_psk",
+                                  ret);
+            return ret;
+        }
+    }
+#endif
+
+    ret = mbedtls_ssl_tls13_evolve_secret(hash_alg, NULL, psk, psk_len,
+                                          handshake->tls13_master_secrets.early);
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
+    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    mbedtls_free((void *) psk);
+#endif
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret);
+        return ret;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "mbedtls_ssl_tls13_key_schedule_stage_early",
+                          handshake->tls13_master_secrets.early,
+                          PSA_HASH_LENGTH(hash_alg));
+    return 0;
+}
+
+/**
+ * \brief Compute TLS 1.3 handshake traffic keys.
+ *
+ *        ssl_tls13_generate_handshake_keys() generates keys necessary for
+ *        protecting the handshake messages, as described in Section 7 of
+ *        RFC 8446.
+ *
+ * \param ssl  The SSL context to operate on. This must be in
+ *             key schedule stage \c Handshake, see
+ *             ssl_tls13_key_schedule_stage_handshake().
+ * \param traffic_keys The address at which to store the handshake traffic
+ *                     keys. This must be writable but may be uninitialized.
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_generate_handshake_keys(mbedtls_ssl_context *ssl,
+                                             mbedtls_ssl_key_set *traffic_keys)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_md_type_t md_type;
+    psa_algorithm_t hash_alg;
+    size_t hash_len;
+    unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+    size_t transcript_len;
+    size_t key_len;
+    size_t iv_len;
+
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info;
+    mbedtls_ssl_tls13_handshake_secrets *tls13_hs_secrets = &handshake->tls13_hs_secrets;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_tls13_generate_handshake_keys"));
+
+    ret = ssl_tls13_get_cipher_key_info(ciphersuite_info, &key_len, &iv_len);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_get_cipher_key_info", ret);
+        return ret;
+    }
+
+    md_type = ciphersuite_info->mac;
+
+    hash_alg = mbedtls_hash_info_psa_from_md(ciphersuite_info->mac);
+    hash_len = PSA_HASH_LENGTH(hash_alg);
+
+    ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type,
+                                               transcript,
+                                               sizeof(transcript),
+                                               &transcript_len);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1,
+                              "mbedtls_ssl_get_handshake_transcript",
+                              ret);
+        return ret;
+    }
+
+    ret = mbedtls_ssl_tls13_derive_handshake_secrets(hash_alg,
+                                                     handshake->tls13_master_secrets.handshake,
+                                                     transcript, transcript_len, tls13_hs_secrets);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_derive_handshake_secrets",
+                              ret);
+        return ret;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "Client handshake traffic secret",
+                          tls13_hs_secrets->client_handshake_traffic_secret,
+                          hash_len);
+    MBEDTLS_SSL_DEBUG_BUF(4, "Server handshake traffic secret",
+                          tls13_hs_secrets->server_handshake_traffic_secret,
+                          hash_len);
+
+    /*
+     * Export client handshake traffic secret
+     */
+    if (ssl->f_export_keys != NULL) {
+        ssl->f_export_keys(ssl->p_export_keys,
+                           MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET,
+                           tls13_hs_secrets->client_handshake_traffic_secret,
+                           hash_len,
+                           handshake->randbytes,
+                           handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,
+                           MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */);
+
+        ssl->f_export_keys(ssl->p_export_keys,
+                           MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET,
+                           tls13_hs_secrets->server_handshake_traffic_secret,
+                           hash_len,
+                           handshake->randbytes,
+                           handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,
+                           MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */);
+    }
+
+    ret = mbedtls_ssl_tls13_make_traffic_keys(hash_alg,
+                                              tls13_hs_secrets->client_handshake_traffic_secret,
+                                              tls13_hs_secrets->server_handshake_traffic_secret,
+                                              hash_len, key_len, iv_len, traffic_keys);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_make_traffic_keys", ret);
+        goto exit;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "client_handshake write_key",
+                          traffic_keys->client_write_key,
+                          traffic_keys->key_len);
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "server_handshake write_key",
+                          traffic_keys->server_write_key,
+                          traffic_keys->key_len);
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "client_handshake write_iv",
+                          traffic_keys->client_write_iv,
+                          traffic_keys->iv_len);
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "server_handshake write_iv",
+                          traffic_keys->server_write_iv,
+                          traffic_keys->iv_len);
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_tls13_generate_handshake_keys"));
+
+exit:
+
+    return ret;
+}
+
+/**
+ * \brief Transition into handshake stage of TLS 1.3 key schedule.
+ *
+ *        The TLS 1.3 key schedule can be viewed as a simple state machine
+ *        with states Initial -> Early -> Handshake -> Application, and
+ *        this function represents the Early -> Handshake transition.
+ *
+ *        In the handshake stage, ssl_tls13_generate_handshake_keys()
+ *        can be used to derive the handshake traffic keys.
+ *
+ * \param ssl  The SSL context to operate on. This must be in key schedule
+ *             stage \c Early.
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_key_schedule_stage_handshake(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    psa_algorithm_t const hash_alg = mbedtls_hash_info_psa_from_md(
+        handshake->ciphersuite_info->mac);
+    unsigned char *shared_secret = NULL;
+    size_t shared_secret_len = 0;
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
+    /*
+     * Compute ECDHE secret used to compute the handshake secret from which
+     * client_handshake_traffic_secret and server_handshake_traffic_secret
+     * are derived in the handshake secret derivation stage.
+     */
+    if (mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) {
+        if (mbedtls_ssl_tls13_named_group_is_ecdhe(handshake->offered_group_id)) {
+#if defined(MBEDTLS_ECDH_C)
+            /* Compute ECDH shared secret. */
+            psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+            psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+            status = psa_get_key_attributes(handshake->ecdh_psa_privkey,
+                                            &key_attributes);
+            if (status != PSA_SUCCESS) {
+                ret = PSA_TO_MBEDTLS_ERR(status);
+            }
+
+            shared_secret_len = PSA_BITS_TO_BYTES(
+                psa_get_key_bits(&key_attributes));
+            shared_secret = mbedtls_calloc(1, shared_secret_len);
+            if (shared_secret == NULL) {
+                return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+            }
+
+            status = psa_raw_key_agreement(
+                PSA_ALG_ECDH, handshake->ecdh_psa_privkey,
+                handshake->ecdh_psa_peerkey, handshake->ecdh_psa_peerkey_len,
+                shared_secret, shared_secret_len, &shared_secret_len);
+            if (status != PSA_SUCCESS) {
+                ret = PSA_TO_MBEDTLS_ERR(status);
+                MBEDTLS_SSL_DEBUG_RET(1, "psa_raw_key_agreement", ret);
+                goto cleanup;
+            }
+
+            status = psa_destroy_key(handshake->ecdh_psa_privkey);
+            if (status != PSA_SUCCESS) {
+                ret = PSA_TO_MBEDTLS_ERR(status);
+                MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret);
+                goto cleanup;
+            }
+
+            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+#endif /* MBEDTLS_ECDH_C */
+        } else {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("Group not supported."));
+            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+        }
+    }
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */
+
+    /*
+     * Compute the Handshake Secret
+     */
+    ret = mbedtls_ssl_tls13_evolve_secret(hash_alg,
+                                          handshake->tls13_master_secrets.early,
+                                          shared_secret, shared_secret_len,
+                                          handshake->tls13_master_secrets.handshake);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret);
+        goto cleanup;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "Handshake secret",
+                          handshake->tls13_master_secrets.handshake,
+                          PSA_HASH_LENGTH(hash_alg));
+
+cleanup:
+    if (shared_secret != NULL) {
+        mbedtls_platform_zeroize(shared_secret, shared_secret_len);
+        mbedtls_free(shared_secret);
+    }
+
+    return ret;
+}
+
+/**
+ * \brief Compute TLS 1.3 application traffic keys.
+ *
+ *        ssl_tls13_generate_application_keys() generates application traffic
+ *        keys, since any record following a 1-RTT Finished message MUST be
+ *        encrypted under the application traffic key.
+ *
+ * \param ssl  The SSL context to operate on. This must be in
+ *             key schedule stage \c Application, see
+ *             ssl_tls13_key_schedule_stage_application().
+ * \param traffic_keys The address at which to store the application traffic
+ *                     keys. This must be writable but may be uninitialized.
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_generate_application_keys(
+    mbedtls_ssl_context *ssl,
+    mbedtls_ssl_key_set *traffic_keys)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+    /* Address at which to store the application secrets */
+    mbedtls_ssl_tls13_application_secrets * const app_secrets =
+        &ssl->session_negotiate->app_secrets;
+
+    /* Holding the transcript up to and including the ServerFinished */
+    unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+    size_t transcript_len;
+
+    /* Variables relating to the hash for the chosen ciphersuite. */
+    mbedtls_md_type_t md_type;
+
+    psa_algorithm_t hash_alg;
+    size_t hash_len;
+
+    /* Variables relating to the cipher for the chosen ciphersuite. */
+    size_t key_len, iv_len;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> derive application traffic keys"));
+
+    /* Extract basic information about hash and ciphersuite */
+
+    ret = ssl_tls13_get_cipher_key_info(handshake->ciphersuite_info,
+                                        &key_len, &iv_len);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_get_cipher_key_info", ret);
+        goto cleanup;
+    }
+
+    md_type = handshake->ciphersuite_info->mac;
+
+    hash_alg = mbedtls_hash_info_psa_from_md(handshake->ciphersuite_info->mac);
+    hash_len = PSA_HASH_LENGTH(hash_alg);
+
+    /* Compute current handshake transcript. It's the caller's responsibility
+     * to call this at the right time, that is, after the ServerFinished. */
+
+    ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type,
+                                               transcript, sizeof(transcript),
+                                               &transcript_len);
+    if (ret != 0) {
+        goto cleanup;
+    }
+
+    /* Compute application secrets from master secret and transcript hash. */
+
+    ret = mbedtls_ssl_tls13_derive_application_secrets(hash_alg,
+                                                       handshake->tls13_master_secrets.app,
+                                                       transcript, transcript_len,
+                                                       app_secrets);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1,
+                              "mbedtls_ssl_tls13_derive_application_secrets", ret);
+        goto cleanup;
+    }
+
+    /* Derive first epoch of IV + Key for application traffic. */
+
+    ret = mbedtls_ssl_tls13_make_traffic_keys(hash_alg,
+                                              app_secrets->client_application_traffic_secret_N,
+                                              app_secrets->server_application_traffic_secret_N,
+                                              hash_len, key_len, iv_len, traffic_keys);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_make_traffic_keys", ret);
+        goto cleanup;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "Client application traffic secret",
+                          app_secrets->client_application_traffic_secret_N,
+                          hash_len);
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "Server application traffic secret",
+                          app_secrets->server_application_traffic_secret_N,
+                          hash_len);
+
+    /*
+     * Export client/server application traffic secret 0
+     */
+    if (ssl->f_export_keys != NULL) {
+        ssl->f_export_keys(ssl->p_export_keys,
+                           MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET,
+                           app_secrets->client_application_traffic_secret_N, hash_len,
+                           handshake->randbytes,
+                           handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,
+                           MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by
+                                                       a new constant for TLS 1.3! */);
+
+        ssl->f_export_keys(ssl->p_export_keys,
+                           MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET,
+                           app_secrets->server_application_traffic_secret_N, hash_len,
+                           handshake->randbytes,
+                           handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,
+                           MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by
+                                                       a new constant for TLS 1.3! */);
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "client application_write_key:",
+                          traffic_keys->client_write_key, key_len);
+    MBEDTLS_SSL_DEBUG_BUF(4, "server application write key",
+                          traffic_keys->server_write_key, key_len);
+    MBEDTLS_SSL_DEBUG_BUF(4, "client application write IV",
+                          traffic_keys->client_write_iv, iv_len);
+    MBEDTLS_SSL_DEBUG_BUF(4, "server application write IV",
+                          traffic_keys->server_write_iv, iv_len);
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= derive application traffic keys"));
+
+cleanup:
+    /* randbytes is not used again */
+    mbedtls_platform_zeroize(ssl->handshake->randbytes,
+                             sizeof(ssl->handshake->randbytes));
+
+    mbedtls_platform_zeroize(transcript, sizeof(transcript));
+    return ret;
+}
+
+int mbedtls_ssl_tls13_compute_handshake_transform(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ssl_key_set traffic_keys;
+    mbedtls_ssl_transform *transform_handshake = NULL;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+    /* Compute handshake secret */
+    ret = ssl_tls13_key_schedule_stage_handshake(ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_derive_master_secret", ret);
+        goto cleanup;
+    }
+
+    /* Next evolution in key schedule: Establish handshake secret and
+     * key material. */
+    ret = ssl_tls13_generate_handshake_keys(ssl, &traffic_keys);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_generate_handshake_keys",
+                              ret);
+        goto cleanup;
+    }
+
+    transform_handshake = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform));
+    if (transform_handshake == NULL) {
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        goto cleanup;
+    }
+
+    ret = mbedtls_ssl_tls13_populate_transform(
+        transform_handshake,
+        ssl->conf->endpoint,
+        handshake->ciphersuite_info->id,
+        &traffic_keys,
+        ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_populate_transform", ret);
+        goto cleanup;
+    }
+    handshake->transform_handshake = transform_handshake;
+
+cleanup:
+    mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys));
+    if (ret != 0) {
+        mbedtls_free(transform_handshake);
+    }
+
+    return ret;
+}
+
+int mbedtls_ssl_tls13_compute_resumption_master_secret(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_md_type_t md_type;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+    size_t transcript_len;
+
+    MBEDTLS_SSL_DEBUG_MSG(2,
+                          ("=> mbedtls_ssl_tls13_compute_resumption_master_secret"));
+
+    md_type = handshake->ciphersuite_info->mac;
+
+    ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type,
+                                               transcript, sizeof(transcript),
+                                               &transcript_len);
+    if (ret != 0) {
+        return ret;
+    }
+
+    ret = mbedtls_ssl_tls13_derive_resumption_master_secret(
+        mbedtls_psa_translate_md(md_type),
+        handshake->tls13_master_secrets.app,
+        transcript, transcript_len,
+        &ssl->session_negotiate->app_secrets);
+    if (ret != 0) {
+        return ret;
+    }
+
+    /* Erase master secrets */
+    mbedtls_platform_zeroize(&handshake->tls13_master_secrets,
+                             sizeof(handshake->tls13_master_secrets));
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "Resumption master secret",
+                          ssl->session_negotiate->app_secrets.resumption_master_secret,
+                          PSA_HASH_LENGTH(mbedtls_psa_translate_md(md_type)));
+
+    MBEDTLS_SSL_DEBUG_MSG(2,
+                          ("<= mbedtls_ssl_tls13_compute_resumption_master_secret"));
+    return 0;
+}
+
+int mbedtls_ssl_tls13_compute_application_transform(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ssl_key_set traffic_keys;
+    mbedtls_ssl_transform *transform_application = NULL;
+
+    ret = ssl_tls13_key_schedule_stage_application(ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1,
+                              "ssl_tls13_key_schedule_stage_application", ret);
+        goto cleanup;
+    }
+
+    ret = ssl_tls13_generate_application_keys(ssl, &traffic_keys);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1,
+                              "ssl_tls13_generate_application_keys", ret);
+        goto cleanup;
+    }
+
+    transform_application =
+        mbedtls_calloc(1, sizeof(mbedtls_ssl_transform));
+    if (transform_application == NULL) {
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        goto cleanup;
+    }
+
+    ret = mbedtls_ssl_tls13_populate_transform(
+        transform_application,
+        ssl->conf->endpoint,
+        ssl->handshake->ciphersuite_info->id,
+        &traffic_keys,
+        ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_populate_transform", ret);
+        goto cleanup;
+    }
+
+    ssl->transform_application = transform_application;
+
+cleanup:
+
+    mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys));
+    if (ret != 0) {
+        mbedtls_free(transform_application);
+    }
+    return ret;
+}
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+int mbedtls_ssl_tls13_export_handshake_psk(mbedtls_ssl_context *ssl,
+                                           unsigned char **psk,
+                                           size_t *psk_len)
+{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    *psk_len = 0;
+    *psk = NULL;
+
+    if (mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    status = psa_get_key_attributes(ssl->handshake->psk_opaque, &key_attributes);
+    if (status != PSA_SUCCESS) {
+        return PSA_TO_MBEDTLS_ERR(status);
+    }
+
+    *psk_len = PSA_BITS_TO_BYTES(psa_get_key_bits(&key_attributes));
+    *psk = mbedtls_calloc(1, *psk_len);
+    if (*psk == NULL) {
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+    }
+
+    status = psa_export_key(ssl->handshake->psk_opaque,
+                            (uint8_t *) *psk, *psk_len, psk_len);
+    if (status != PSA_SUCCESS) {
+        mbedtls_free((void *) *psk);
+        *psk = NULL;
+        return PSA_TO_MBEDTLS_ERR(status);
+    }
+    return 0;
+#else
+    *psk = ssl->handshake->psk;
+    *psk_len = ssl->handshake->psk_len;
+    if (*psk == NULL) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+    return 0;
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
+}
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h b/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h
index 7089049..21e9b4d 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h
@@ -20,98 +20,112 @@
 #define MBEDTLS_SSL_TLS1_3_KEYS_H
 
 /* This requires MBEDTLS_SSL_TLS1_3_LABEL( idx, name, string ) to be defined at
- * the point of use. See e.g. the definition of mbedtls_ssl_tls1_3_labels_union
+ * the point of use. See e.g. the definition of mbedtls_ssl_tls13_labels_union
  * below. */
-#define MBEDTLS_SSL_TLS1_3_LABEL_LIST                               \
-    MBEDTLS_SSL_TLS1_3_LABEL( finished    , "finished"     ) \
-    MBEDTLS_SSL_TLS1_3_LABEL( resumption  , "resumption"   ) \
-    MBEDTLS_SSL_TLS1_3_LABEL( traffic_upd , "traffic upd"  ) \
-    MBEDTLS_SSL_TLS1_3_LABEL( exporter    , "exporter"     ) \
-    MBEDTLS_SSL_TLS1_3_LABEL( key         , "key"          ) \
-    MBEDTLS_SSL_TLS1_3_LABEL( iv          , "iv"           ) \
-    MBEDTLS_SSL_TLS1_3_LABEL( c_hs_traffic, "c hs traffic" ) \
-    MBEDTLS_SSL_TLS1_3_LABEL( c_ap_traffic, "c ap traffic" ) \
-    MBEDTLS_SSL_TLS1_3_LABEL( c_e_traffic , "c e traffic"  ) \
-    MBEDTLS_SSL_TLS1_3_LABEL( s_hs_traffic, "s hs traffic" ) \
-    MBEDTLS_SSL_TLS1_3_LABEL( s_ap_traffic, "s ap traffic" ) \
-    MBEDTLS_SSL_TLS1_3_LABEL( s_e_traffic , "s e traffic"  ) \
-    MBEDTLS_SSL_TLS1_3_LABEL( e_exp_master, "e exp master" ) \
-    MBEDTLS_SSL_TLS1_3_LABEL( res_master  , "res master"   ) \
-    MBEDTLS_SSL_TLS1_3_LABEL( exp_master  , "exp master"   ) \
-    MBEDTLS_SSL_TLS1_3_LABEL( ext_binder  , "ext binder"   ) \
-    MBEDTLS_SSL_TLS1_3_LABEL( res_binder  , "res binder"   ) \
-    MBEDTLS_SSL_TLS1_3_LABEL( derived     , "derived"      )
+#define MBEDTLS_SSL_TLS1_3_LABEL_LIST                                             \
+    MBEDTLS_SSL_TLS1_3_LABEL(finished, "finished") \
+    MBEDTLS_SSL_TLS1_3_LABEL(resumption, "resumption") \
+    MBEDTLS_SSL_TLS1_3_LABEL(traffic_upd, "traffic upd") \
+    MBEDTLS_SSL_TLS1_3_LABEL(exporter, "exporter") \
+    MBEDTLS_SSL_TLS1_3_LABEL(key, "key") \
+    MBEDTLS_SSL_TLS1_3_LABEL(iv, "iv") \
+    MBEDTLS_SSL_TLS1_3_LABEL(c_hs_traffic, "c hs traffic") \
+    MBEDTLS_SSL_TLS1_3_LABEL(c_ap_traffic, "c ap traffic") \
+    MBEDTLS_SSL_TLS1_3_LABEL(c_e_traffic, "c e traffic") \
+    MBEDTLS_SSL_TLS1_3_LABEL(s_hs_traffic, "s hs traffic") \
+    MBEDTLS_SSL_TLS1_3_LABEL(s_ap_traffic, "s ap traffic") \
+    MBEDTLS_SSL_TLS1_3_LABEL(s_e_traffic, "s e traffic") \
+    MBEDTLS_SSL_TLS1_3_LABEL(e_exp_master, "e exp master") \
+    MBEDTLS_SSL_TLS1_3_LABEL(res_master, "res master") \
+    MBEDTLS_SSL_TLS1_3_LABEL(exp_master, "exp master") \
+    MBEDTLS_SSL_TLS1_3_LABEL(ext_binder, "ext binder") \
+    MBEDTLS_SSL_TLS1_3_LABEL(res_binder, "res binder") \
+    MBEDTLS_SSL_TLS1_3_LABEL(derived, "derived") \
+    MBEDTLS_SSL_TLS1_3_LABEL(client_cv, "TLS 1.3, client CertificateVerify") \
+    MBEDTLS_SSL_TLS1_3_LABEL(server_cv, "TLS 1.3, server CertificateVerify")
 
-#define MBEDTLS_SSL_TLS1_3_LABEL( name, string )       \
-    const unsigned char name    [ sizeof(string) - 1 ];
+#define MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED 0
+#define MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED   1
 
-union mbedtls_ssl_tls1_3_labels_union
-{
+#define MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL   0
+#define MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION 1
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+
+#define MBEDTLS_SSL_TLS1_3_LABEL(name, string)       \
+    const unsigned char name    [sizeof(string) - 1];
+
+union mbedtls_ssl_tls13_labels_union {
     MBEDTLS_SSL_TLS1_3_LABEL_LIST
 };
-struct mbedtls_ssl_tls1_3_labels_struct
-{
+struct mbedtls_ssl_tls13_labels_struct {
     MBEDTLS_SSL_TLS1_3_LABEL_LIST
 };
 #undef MBEDTLS_SSL_TLS1_3_LABEL
 
-extern const struct mbedtls_ssl_tls1_3_labels_struct mbedtls_ssl_tls1_3_labels;
+extern const struct mbedtls_ssl_tls13_labels_struct mbedtls_ssl_tls13_labels;
 
-#define MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( LABEL )  \
-    mbedtls_ssl_tls1_3_labels.LABEL,              \
-    sizeof(mbedtls_ssl_tls1_3_labels.LABEL)
+#define MBEDTLS_SSL_TLS1_3_LBL_LEN(LABEL)  \
+    sizeof(mbedtls_ssl_tls13_labels.LABEL)
+
+#define MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(LABEL)  \
+    mbedtls_ssl_tls13_labels.LABEL,              \
+    MBEDTLS_SSL_TLS1_3_LBL_LEN(LABEL)
 
 #define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN  \
-    sizeof( union mbedtls_ssl_tls1_3_labels_union )
+    sizeof(union mbedtls_ssl_tls13_labels_union)
 
 /* The maximum length of HKDF contexts used in the TLS 1.3 standard.
  * Since contexts are always hashes of message transcripts, this can
  * be approximated from above by the maximum hash size. */
 #define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN  \
-    MBEDTLS_MD_MAX_SIZE
+    PSA_HASH_MAX_SIZE
 
 /* Maximum desired length for expanded key material generated
  * by HKDF-Expand-Label.
  *
  * Warning: If this ever needs to be increased, the implementation
- * ssl_tls1_3_hkdf_encode_label() in ssl_tls13_keys.c needs to be
+ * ssl_tls13_hkdf_encode_label() in ssl_tls13_keys.c needs to be
  * adjusted since it currently assumes that HKDF key expansion
  * is never used with more than 255 Bytes of output. */
 #define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN 255
 
 /**
- * \brief           The \c HKDF-Expand-Label function from
- *                  the TLS 1.3 standard RFC 8446.
+ * \brief            The \c HKDF-Expand-Label function from
+ *                   the TLS 1.3 standard RFC 8446.
  *
  * <tt>
- *                  HKDF-Expand-Label( Secret, Label, Context, Length ) =
+ *                   HKDF-Expand-Label( Secret, Label, Context, Length ) =
  *                       HKDF-Expand( Secret, HkdfLabel, Length )
  * </tt>
  *
- * \param hash_alg  The identifier for the hash algorithm to use.
- * \param secret    The \c Secret argument to \c HKDF-Expand-Label.
- *                  This must be a readable buffer of length \p slen Bytes.
- * \param slen      The length of \p secret in Bytes.
- * \param label     The \c Label argument to \c HKDF-Expand-Label.
- *                  This must be a readable buffer of length \p llen Bytes.
- * \param llen      The length of \p label in Bytes.
- * \param ctx       The \c Context argument to \c HKDF-Expand-Label.
- *                  This must be a readable buffer of length \p clen Bytes.
- * \param clen      The length of \p context in Bytes.
- * \param buf       The destination buffer to hold the expanded secret.
- *                  This must be a writable buffer of length \p blen Bytes.
- * \param blen      The desired size of the expanded secret in Bytes.
+ * \param hash_alg   The identifier for the hash algorithm to use.
+ * \param secret     The \c Secret argument to \c HKDF-Expand-Label.
+ *                   This must be a readable buffer of length
+ *                   \p secret_len Bytes.
+ * \param secret_len The length of \p secret in Bytes.
+ * \param label      The \c Label argument to \c HKDF-Expand-Label.
+ *                   This must be a readable buffer of length
+ *                   \p label_len Bytes.
+ * \param label_len  The length of \p label in Bytes.
+ * \param ctx        The \c Context argument to \c HKDF-Expand-Label.
+ *                   This must be a readable buffer of length \p ctx_len Bytes.
+ * \param ctx_len    The length of \p context in Bytes.
+ * \param buf        The destination buffer to hold the expanded secret.
+ *                   This must be a writable buffer of length \p buf_len Bytes.
+ * \param buf_len    The desired size of the expanded secret in Bytes.
  *
- * \returns         \c 0 on success.
- * \return          A negative error code on failure.
+ * \returns          \c 0 on success.
+ * \return           A negative error code on failure.
  */
 
-int mbedtls_ssl_tls1_3_hkdf_expand_label(
-                     mbedtls_md_type_t hash_alg,
-                     const unsigned char *secret, size_t slen,
-                     const unsigned char *label, size_t llen,
-                     const unsigned char *ctx, size_t clen,
-                     unsigned char *buf, size_t blen );
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_hkdf_expand_label(
+    psa_algorithm_t hash_alg,
+    const unsigned char *secret, size_t secret_len,
+    const unsigned char *label, size_t label_len,
+    const unsigned char *ctx, size_t ctx_len,
+    unsigned char *buf, size_t buf_len);
 
 /**
  * \brief           This function is part of the TLS 1.3 key schedule.
@@ -128,10 +142,12 @@
  * \param hash_alg      The identifier for the hash algorithm to be used
  *                      for the HKDF-based expansion of the secret.
  * \param client_secret The client traffic secret.
- *                      This must be a readable buffer of size \p slen Bytes
+ *                      This must be a readable buffer of size
+ *                      \p secret_len Bytes
  * \param server_secret The server traffic secret.
- *                      This must be a readable buffer of size \p slen Bytes
- * \param slen          Length of the secrets \p client_secret and
+ *                      This must be a readable buffer of size
+ *                      \p secret_len Bytes
+ * \param secret_len    Length of the secrets \p client_secret and
  *                      \p server_secret in Bytes.
  * \param key_len       The desired length of the key to be extracted in Bytes.
  * \param iv_len        The desired length of the IV to be extracted in Bytes.
@@ -142,16 +158,13 @@
  * \returns             A negative error code on failure.
  */
 
-int mbedtls_ssl_tls1_3_make_traffic_keys(
-                     mbedtls_md_type_t hash_alg,
-                     const unsigned char *client_secret,
-                     const unsigned char *server_secret,
-                     size_t slen, size_t key_len, size_t iv_len,
-                     mbedtls_ssl_key_set *keys );
-
-
-#define MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED 0
-#define MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED   1
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_make_traffic_keys(
+    psa_algorithm_t hash_alg,
+    const unsigned char *client_secret,
+    const unsigned char *server_secret, size_t secret_len,
+    size_t key_len, size_t iv_len,
+    mbedtls_ssl_key_set *keys);
 
 /**
  * \brief The \c Derive-Secret function from the TLS 1.3 standard RFC 8446.
@@ -166,15 +179,17 @@
  * \param hash_alg   The identifier for the hash function used for the
  *                   applications of HKDF.
  * \param secret     The \c Secret argument to the \c Derive-Secret function.
- *                   This must be a readable buffer of length \p slen Bytes.
- * \param slen       The length of \p secret in Bytes.
+ *                   This must be a readable buffer of length
+ *                   \p secret_len Bytes.
+ * \param secret_len The length of \p secret in Bytes.
  * \param label      The \c Label argument to the \c Derive-Secret function.
- *                   This must be a readable buffer of length \p llen Bytes.
- * \param llen       The length of \p label in Bytes.
+ *                   This must be a readable buffer of length
+ *                   \p label_len Bytes.
+ * \param label_len  The length of \p label in Bytes.
  * \param ctx        The hash of the \c Messages argument to the
  *                   \c Derive-Secret function, or the \c Messages argument
- *                   itself, depending on \p context_already_hashed.
- * \param clen       The length of \p hash.
+ *                   itself, depending on \p ctx_hashed.
+ * \param ctx_len    The length of \p ctx in Bytes.
  * \param ctx_hashed This indicates whether the \p ctx contains the hash of
  *                   the \c Messages argument in the application of the
  *                   \c Derive-Secret function
@@ -184,19 +199,197 @@
  *                   (value MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED).
  * \param dstbuf     The target buffer to write the output of
  *                   \c Derive-Secret to. This must be a writable buffer of
- *                   size \p buflen Bytes.
- * \param buflen     The length of \p dstbuf in Bytes.
+ *                   size \p dtsbuf_len Bytes.
+ * \param dstbuf_len The length of \p dstbuf in Bytes.
  *
  * \returns        \c 0 on success.
  * \returns        A negative error code on failure.
  */
-int mbedtls_ssl_tls1_3_derive_secret(
-                   mbedtls_md_type_t hash_alg,
-                   const unsigned char *secret, size_t slen,
-                   const unsigned char *label, size_t llen,
-                   const unsigned char *ctx, size_t clen,
-                   int ctx_hashed,
-                   unsigned char *dstbuf, size_t buflen );
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_derive_secret(
+    psa_algorithm_t hash_alg,
+    const unsigned char *secret, size_t secret_len,
+    const unsigned char *label, size_t label_len,
+    const unsigned char *ctx, size_t ctx_len,
+    int ctx_hashed,
+    unsigned char *dstbuf, size_t dstbuf_len);
+
+/**
+ * \brief Derive TLS 1.3 early data key material from early secret.
+ *
+ *        This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret()
+ *        with the appropriate labels.
+ *
+ * <tt>
+ *        Early Secret
+ *             |
+ *             +-----> Derive-Secret(., "c e traffic", ClientHello)
+ *             |                      = client_early_traffic_secret
+ *             |
+ *             +-----> Derive-Secret(., "e exp master", ClientHello)
+ *             .                      = early_exporter_master_secret
+ *             .
+ *             .
+ * </tt>
+ *
+ * \note  To obtain the actual key and IV for the early data traffic,
+ *        the client secret derived by this function need to be
+ *        further processed by mbedtls_ssl_tls13_make_traffic_keys().
+ *
+ * \note  The binder key, which is also generated from the early secret,
+ *        is omitted here. Its calculation is part of the separate routine
+ *        mbedtls_ssl_tls13_create_psk_binder().
+ *
+ * \param hash_alg     The hash algorithm associated with the PSK for which
+ *                     early data key material is being derived.
+ * \param early_secret The early secret from which the early data key material
+ *                     should be derived. This must be a readable buffer whose
+ *                     length is the digest size of the hash algorithm
+ *                     represented by \p md_size.
+ * \param transcript   The transcript of the handshake so far, calculated with
+ *                     respect to \p hash_alg. This must be a readable buffer
+ *                     whose length is the digest size of the hash algorithm
+ *                     represented by \p md_size.
+ * \param derived      The address of the structure in which to store
+ *                     the early data key material.
+ *
+ * \returns        \c 0 on success.
+ * \returns        A negative error code on failure.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_derive_early_secrets(
+    psa_algorithm_t hash_alg,
+    unsigned char const *early_secret,
+    unsigned char const *transcript, size_t transcript_len,
+    mbedtls_ssl_tls13_early_secrets *derived);
+
+/**
+ * \brief Derive TLS 1.3 handshake key material from the handshake secret.
+ *
+ *        This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret()
+ *        with the appropriate labels from the standard.
+ *
+ * <tt>
+ *        Handshake Secret
+ *              |
+ *              +-----> Derive-Secret( ., "c hs traffic",
+ *              |                      ClientHello...ServerHello )
+ *              |                      = client_handshake_traffic_secret
+ *              |
+ *              +-----> Derive-Secret( ., "s hs traffic",
+ *              .                      ClientHello...ServerHello )
+ *              .                      = server_handshake_traffic_secret
+ *              .
+ * </tt>
+ *
+ * \note  To obtain the actual key and IV for the encrypted handshake traffic,
+ *        the client and server secret derived by this function need to be
+ *        further processed by mbedtls_ssl_tls13_make_traffic_keys().
+ *
+ * \param hash_alg          The hash algorithm associated with the ciphersuite
+ *                          that's being used for the connection.
+ * \param handshake_secret  The handshake secret from which the handshake key
+ *                          material should be derived. This must be a readable
+ *                          buffer whose length is the digest size of the hash
+ *                          algorithm represented by \p md_size.
+ * \param transcript        The transcript of the handshake so far, calculated
+ *                          with respect to \p hash_alg. This must be a readable
+ *                          buffer whose length is the digest size of the hash
+ *                          algorithm represented by \p md_size.
+ * \param derived           The address of the structure in which to
+ *                          store the handshake key material.
+ *
+ * \returns        \c 0 on success.
+ * \returns        A negative error code on failure.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_derive_handshake_secrets(
+    psa_algorithm_t hash_alg,
+    unsigned char const *handshake_secret,
+    unsigned char const *transcript, size_t transcript_len,
+    mbedtls_ssl_tls13_handshake_secrets *derived);
+
+/**
+ * \brief Derive TLS 1.3 application key material from the master secret.
+ *
+ *        This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret()
+ *        with the appropriate labels from the standard.
+ *
+ * <tt>
+ *        Master Secret
+ *              |
+ *              +-----> Derive-Secret( ., "c ap traffic",
+ *              |                      ClientHello...server Finished )
+ *              |                      = client_application_traffic_secret_0
+ *              |
+ *              +-----> Derive-Secret( ., "s ap traffic",
+ *              |                      ClientHello...Server Finished )
+ *              |                      = server_application_traffic_secret_0
+ *              |
+ *              +-----> Derive-Secret( ., "exp master",
+ *              .                      ClientHello...server Finished)
+ *              .                      = exporter_master_secret
+ *              .
+ * </tt>
+ *
+ * \note  To obtain the actual key and IV for the (0-th) application traffic,
+ *        the client and server secret derived by this function need to be
+ *        further processed by mbedtls_ssl_tls13_make_traffic_keys().
+ *
+ * \param hash_alg          The hash algorithm associated with the ciphersuite
+ *                          that's being used for the connection.
+ * \param master_secret     The master secret from which the application key
+ *                          material should be derived. This must be a readable
+ *                          buffer whose length is the digest size of the hash
+ *                          algorithm represented by \p md_size.
+ * \param transcript        The transcript of the handshake up to and including
+ *                          the ServerFinished message, calculated with respect
+ *                          to \p hash_alg. This must be a readable buffer whose
+ *                          length is the digest size of the hash algorithm
+ *                          represented by \p hash_alg.
+ * \param derived           The address of the structure in which to
+ *                          store the application key material.
+ *
+ * \returns        \c 0 on success.
+ * \returns        A negative error code on failure.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_derive_application_secrets(
+    psa_algorithm_t hash_alg,
+    unsigned char const *master_secret,
+    unsigned char const *transcript, size_t transcript_len,
+    mbedtls_ssl_tls13_application_secrets *derived);
+
+/**
+ * \brief Derive TLS 1.3 resumption master secret from the master secret.
+ *
+ *        This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret()
+ *        with the appropriate labels from the standard.
+ *
+ * \param hash_alg          The hash algorithm used in the application for which
+ *                          key material is being derived.
+ * \param application_secret The application secret from which the resumption master
+ *                          secret should be derived. This must be a readable
+ *                          buffer whose length is the digest size of the hash
+ *                          algorithm represented by \p md_size.
+ * \param transcript        The transcript of the handshake up to and including
+ *                          the ClientFinished message, calculated with respect
+ *                          to \p hash_alg. This must be a readable buffer whose
+ *                          length is the digest size of the hash algorithm
+ *                          represented by \p hash_alg.
+ * \param transcript_len    The length of \p transcript in Bytes.
+ * \param derived           The address of the structure in which to
+ *                          store the resumption master secret.
+ *
+ * \returns        \c 0 on success.
+ * \returns        A negative error code on failure.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_derive_resumption_master_secret(
+    psa_algorithm_t hash_alg,
+    unsigned char const *application_secret,
+    unsigned char const *transcript, size_t transcript_len,
+    mbedtls_ssl_tls13_application_secrets *derived);
 
 /**
  * \brief Compute the next secret in the TLS 1.3 key schedule
@@ -228,7 +421,7 @@
  *
  * Each of the three secrets in turn is the basis for further
  * key derivations, such as the derivation of traffic keys and IVs;
- * see e.g. mbedtls_ssl_tls1_3_make_traffic_keys().
+ * see e.g. mbedtls_ssl_tls13_make_traffic_keys().
  *
  * This function implements one step in this evolution of secrets:
  *
@@ -265,10 +458,206 @@
  * \returns           A negative error code on failure.
  */
 
-int mbedtls_ssl_tls1_3_evolve_secret(
-                   mbedtls_md_type_t hash_alg,
-                   const unsigned char *secret_old,
-                   const unsigned char *input, size_t input_len,
-                   unsigned char *secret_new );
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_evolve_secret(
+    psa_algorithm_t hash_alg,
+    const unsigned char *secret_old,
+    const unsigned char *input, size_t input_len,
+    unsigned char *secret_new);
+
+/**
+ * \brief             Calculate a TLS 1.3 PSK binder.
+ *
+ * \param ssl         The SSL context. This is used for debugging only and may
+ *                    be \c NULL if MBEDTLS_DEBUG_C is disabled.
+ * \param hash_alg    The hash algorithm associated to the PSK \p psk.
+ * \param psk         The buffer holding the PSK for which to create a binder.
+ * \param psk_len     The size of \p psk in bytes.
+ * \param psk_type    This indicates whether the PSK \p psk is externally
+ *                    provisioned (#MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL) or a
+ *                    resumption PSK (#MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION).
+ * \param transcript  The handshake transcript up to the point where the
+ *                    PSK binder calculation happens. This must be readable,
+ *                    and its size must be equal to the digest size of
+ *                    the hash algorithm represented by \p hash_alg.
+ * \param result      The address at which to store the PSK binder on success.
+ *                    This must be writable, and its size must be equal to the
+ *                    digest size of  the hash algorithm represented by
+ *                    \p hash_alg.
+ *
+ * \returns           \c 0 on success.
+ * \returns           A negative error code on failure.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_create_psk_binder(mbedtls_ssl_context *ssl,
+                                        const psa_algorithm_t hash_alg,
+                                        unsigned char const *psk, size_t psk_len,
+                                        int psk_type,
+                                        unsigned char const *transcript,
+                                        unsigned char *result);
+
+/**
+ * \bref Setup an SSL transform structure representing the
+ *       record protection mechanism used by TLS 1.3
+ *
+ * \param transform    The SSL transform structure to be created. This must have
+ *                     been initialized through mbedtls_ssl_transform_init() and
+ *                     not used in any other way prior to calling this function.
+ *                     In particular, this function does not clean up the
+ *                     transform structure prior to installing the new keys.
+ * \param endpoint     Indicates whether the transform is for the client
+ *                     (value #MBEDTLS_SSL_IS_CLIENT) or the server
+ *                     (value #MBEDTLS_SSL_IS_SERVER).
+ * \param ciphersuite  The numerical identifier for the ciphersuite to use.
+ *                     This must be one of the identifiers listed in
+ *                     ssl_ciphersuites.h.
+ * \param traffic_keys The key material to use. No reference is stored in
+ *                     the SSL transform being generated, and the caller
+ *                     should destroy the key material afterwards.
+ * \param ssl          (Debug-only) The SSL context to use for debug output
+ *                     in case of failure. This parameter is only needed if
+ *                     #MBEDTLS_DEBUG_C is set, and is ignored otherwise.
+ *
+ * \return             \c 0 on success. In this case, \p transform is ready to
+ *                     be used with mbedtls_ssl_transform_decrypt() and
+ *                     mbedtls_ssl_transform_encrypt().
+ * \return             A negative error code on failure.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_populate_transform(mbedtls_ssl_transform *transform,
+                                         int endpoint,
+                                         int ciphersuite,
+                                         mbedtls_ssl_key_set const *traffic_keys,
+                                         mbedtls_ssl_context *ssl);
+
+/*
+ * TLS 1.3 key schedule evolutions
+ *
+ *   Early -> Handshake -> Application
+ *
+ * Small wrappers around mbedtls_ssl_tls13_evolve_secret().
+ */
+
+/**
+ * \brief Begin TLS 1.3 key schedule by calculating early secret.
+ *
+ *        The TLS 1.3 key schedule can be viewed as a simple state machine
+ *        with states Initial -> Early -> Handshake -> Application, and
+ *        this function represents the Initial -> Early transition.
+ *
+ * \param ssl  The SSL context to operate on.
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_key_schedule_stage_early(mbedtls_ssl_context *ssl);
+
+/**
+ * \brief Compute TLS 1.3 resumption master secret.
+ *
+ * \param ssl  The SSL context to operate on. This must be in
+ *             key schedule stage \c Application, see
+ *             mbedtls_ssl_tls13_key_schedule_stage_application().
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_compute_resumption_master_secret(mbedtls_ssl_context *ssl);
+
+/**
+ * \brief Calculate the verify_data value for the client or server TLS 1.3
+ * Finished message.
+ *
+ * \param ssl  The SSL context to operate on. This must be in
+ *             key schedule stage \c Handshake, see
+ *             mbedtls_ssl_tls13_key_schedule_stage_application().
+ * \param dst        The address at which to write the verify_data value.
+ * \param dst_len    The size of \p dst in bytes.
+ * \param actual_len The address at which to store the amount of data
+ *                   actually written to \p dst upon success.
+ * \param which      The message to calculate the `verify_data` for:
+ *                   - #MBEDTLS_SSL_IS_CLIENT for the Client's Finished message
+ *                   - #MBEDTLS_SSL_IS_SERVER for the Server's Finished message
+ *
+ * \note       Both client and server call this function twice, once to
+ *             generate their own Finished message, and once to verify the
+ *             peer's Finished message.
+
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_calculate_verify_data(mbedtls_ssl_context *ssl,
+                                            unsigned char *dst,
+                                            size_t dst_len,
+                                            size_t *actual_len,
+                                            int which);
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+/**
+ * \brief Compute TLS 1.3 early transform
+ *
+ * \param ssl  The SSL context to operate on.
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ *
+ * \warning    The function does not compute the early master secret. Call
+ *             mbedtls_ssl_tls13_key_schedule_stage_early() before to
+ *             call this function to generate the early master secret.
+ * \note       For a client/server endpoint, the function computes only the
+ *             encryption/decryption part of the transform as the decryption/
+ *             encryption part is not defined by the specification (no early
+ *             traffic from the server to the client).
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_compute_early_transform(mbedtls_ssl_context *ssl);
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
+/**
+ * \brief Compute TLS 1.3 handshake transform
+ *
+ * \param ssl  The SSL context to operate on. The early secret must have been
+ *             computed.
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_compute_handshake_transform(mbedtls_ssl_context *ssl);
+
+/**
+ * \brief Compute TLS 1.3 application transform
+ *
+ * \param ssl  The SSL context to operate on. The early secret must have been
+ *             computed.
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_compute_application_transform(mbedtls_ssl_context *ssl);
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+/**
+ * \brief Export TLS 1.3 PSK from handshake context
+ *
+ * \param[in]   ssl  The SSL context to operate on.
+ * \param[out]  psk  PSK output pointer.
+ * \param[out]  psk_len Length of PSK.
+ *
+ * \returns     \c 0 if there is a configured PSK and it was exported
+ *              successfully.
+ * \returns     A negative error code on failure.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_export_handshake_psk(mbedtls_ssl_context *ssl,
+                                           unsigned char **psk,
+                                           size_t *psk_len);
+#endif
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
 #endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls13_server.c b/lib/libmbedtls/mbedtls/library/ssl_tls13_server.c
new file mode 100644
index 0000000..b5a0c9e
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls13_server.c
@@ -0,0 +1,3084 @@
+/*
+ *  TLS 1.3 server-side functions
+ *
+ *  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.
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
+
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
+#include "mbedtls/platform.h"
+#include "mbedtls/constant_time.h"
+
+#include "ssl_misc.h"
+#include "ssl_tls13_keys.h"
+#include "ssl_debug_helpers.h"
+
+
+static const mbedtls_ssl_ciphersuite_t *ssl_tls13_validate_peer_ciphersuite(
+    mbedtls_ssl_context *ssl,
+    unsigned int cipher_suite)
+{
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+    if (!mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, cipher_suite)) {
+        return NULL;
+    }
+
+    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite);
+    if ((mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info,
+                                          ssl->tls_version,
+                                          ssl->tls_version) != 0)) {
+        return NULL;
+    }
+    return ciphersuite_info;
+}
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+/* From RFC 8446:
+ *
+ *   enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode;
+ *   struct {
+ *       PskKeyExchangeMode ke_modes<1..255>;
+ *   } PskKeyExchangeModes;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_key_exchange_modes_ext(mbedtls_ssl_context *ssl,
+                                                  const unsigned char *buf,
+                                                  const unsigned char *end)
+{
+    const unsigned char *p = buf;
+    size_t ke_modes_len;
+    int ke_modes = 0;
+
+    /* Read ke_modes length (1 Byte) */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1);
+    ke_modes_len = *p++;
+    /* Currently, there are only two PSK modes, so even without looking
+     * at the content, something's wrong if the list has more than 2 items. */
+    if (ke_modes_len > 2) {
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, ke_modes_len);
+
+    while (ke_modes_len-- != 0) {
+        switch (*p++) {
+            case MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE:
+                ke_modes |= MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;
+                MBEDTLS_SSL_DEBUG_MSG(3, ("Found PSK KEX MODE"));
+                break;
+            case MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE:
+                ke_modes |= MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
+                MBEDTLS_SSL_DEBUG_MSG(3, ("Found PSK_EPHEMERAL KEX MODE"));
+                break;
+            default:
+                MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                             MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+                return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+        }
+    }
+
+    ssl->handshake->tls13_kex_modes = ke_modes;
+    return 0;
+}
+
+#define SSL_TLS1_3_OFFERED_PSK_NOT_MATCH   1
+#define SSL_TLS1_3_OFFERED_PSK_MATCH       0
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_offered_psks_check_identity_match_ticket(
+    mbedtls_ssl_context *ssl,
+    const unsigned char *identity,
+    size_t identity_len,
+    uint32_t obfuscated_ticket_age,
+    mbedtls_ssl_session *session)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *ticket_buffer;
+#if defined(MBEDTLS_HAVE_TIME)
+    mbedtls_time_t now;
+    uint64_t age_in_s;
+    int64_t age_diff_in_ms;
+#endif
+
+    ((void) obfuscated_ticket_age);
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> check_identity_match_ticket"));
+
+    /* Ticket parser is not configured, Skip */
+    if (ssl->conf->f_ticket_parse == NULL || identity_len == 0) {
+        return 0;
+    }
+
+    /* We create a copy of the encrypted ticket since the ticket parsing
+     * function is allowed to use its input buffer as an output buffer
+     * (in-place decryption). We do, however, need the original buffer for
+     * computing the PSK binder value.
+     */
+    ticket_buffer = mbedtls_calloc(1, identity_len);
+    if (ticket_buffer == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small"));
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+    }
+    memcpy(ticket_buffer, identity, identity_len);
+
+    if ((ret = ssl->conf->f_ticket_parse(ssl->conf->p_ticket,
+                                         session,
+                                         ticket_buffer, identity_len)) != 0) {
+        if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) {
+            MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is not authentic"));
+        } else if (ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) {
+            MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is expired"));
+        } else {
+            MBEDTLS_SSL_DEBUG_RET(1, "ticket_parse", ret);
+        }
+    }
+
+    /* We delete the temporary buffer */
+    mbedtls_free(ticket_buffer);
+
+    if (ret != 0) {
+        goto exit;
+    }
+
+    /* RFC 8446 section 4.2.9
+     *
+     * Servers SHOULD NOT send NewSessionTicket with tickets that are not
+     * compatible with the advertised modes; however, if a server does so,
+     * the impact will just be that the client's attempts at resumption fail.
+     *
+     * We regard the ticket with incompatible key exchange modes as not match.
+     */
+    ret = MBEDTLS_ERR_ERROR_GENERIC_ERROR;
+    MBEDTLS_SSL_PRINT_TICKET_FLAGS(4,
+                                   session->ticket_flags);
+    if (mbedtls_ssl_tls13_check_kex_modes(
+            ssl,
+            mbedtls_ssl_session_get_ticket_flags(
+                session,
+                MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL))) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("No suitable key exchange mode"));
+        goto exit;
+    }
+
+    ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
+#if defined(MBEDTLS_HAVE_TIME)
+    now = mbedtls_time(NULL);
+
+    if (now < session->start) {
+        MBEDTLS_SSL_DEBUG_MSG(
+            3, ("Invalid ticket start time ( now=%" MBEDTLS_PRINTF_LONGLONG
+                ", start=%" MBEDTLS_PRINTF_LONGLONG " )",
+                (long long) now, (long long) session->start));
+        goto exit;
+    }
+
+    age_in_s = (uint64_t) (now - session->start);
+
+    /* RFC 8446 section 4.6.1
+     *
+     * Servers MUST NOT use any value greater than 604800 seconds (7 days).
+     *
+     * RFC 8446 section 4.2.11.1
+     *
+     * Clients MUST NOT attempt to use tickets which have ages greater than
+     * the "ticket_lifetime" value which was provided with the ticket.
+     *
+     * For time being, the age MUST be less than 604800 seconds (7 days).
+     */
+    if (age_in_s > 604800) {
+        MBEDTLS_SSL_DEBUG_MSG(
+            3, ("Ticket age exceeds limitation ticket_age=%lu",
+                (long unsigned int) age_in_s));
+        goto exit;
+    }
+
+    /* RFC 8446 section 4.2.10
+     *
+     * For PSKs provisioned via NewSessionTicket, a server MUST validate that
+     * the ticket age for the selected PSK identity (computed by subtracting
+     * ticket_age_add from PskIdentity.obfuscated_ticket_age modulo 2^32) is
+     * within a small tolerance of the time since the ticket was issued.
+     *
+     * NOTE: When `now == session->start`, `age_diff_in_ms` may be negative
+     *       as the age units are different on the server (s) and in the
+     *       client (ms) side. Add a -1000 ms tolerance window to take this
+     *       into account.
+     */
+    age_diff_in_ms = age_in_s * 1000;
+    age_diff_in_ms -= (obfuscated_ticket_age - session->ticket_age_add);
+    if (age_diff_in_ms <= -1000 ||
+        age_diff_in_ms > MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE) {
+        MBEDTLS_SSL_DEBUG_MSG(
+            3, ("Ticket age outside tolerance window ( diff=%d )",
+                (int) age_diff_in_ms));
+        goto exit;
+    }
+
+    ret = 0;
+
+#endif /* MBEDTLS_HAVE_TIME */
+
+exit:
+    if (ret != 0) {
+        mbedtls_ssl_session_free(session);
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= check_identity_match_ticket"));
+    return ret;
+}
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_offered_psks_check_identity_match(
+    mbedtls_ssl_context *ssl,
+    const unsigned char *identity,
+    size_t identity_len,
+    uint32_t obfuscated_ticket_age,
+    int *psk_type,
+    mbedtls_ssl_session *session)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    ((void) session);
+    ((void) obfuscated_ticket_age);
+    *psk_type = MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL;
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "identity", identity, identity_len);
+    ssl->handshake->resume = 0;
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    if (ssl_tls13_offered_psks_check_identity_match_ticket(
+            ssl, identity, identity_len, obfuscated_ticket_age,
+            session) == SSL_TLS1_3_OFFERED_PSK_MATCH) {
+        ssl->handshake->resume = 1;
+        *psk_type = MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION;
+        ret = mbedtls_ssl_set_hs_psk(ssl,
+                                     session->resumption_key,
+                                     session->resumption_key_len);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret);
+            return ret;
+        }
+
+        MBEDTLS_SSL_DEBUG_BUF(4, "Ticket-resumed PSK:",
+                              session->resumption_key,
+                              session->resumption_key_len);
+        MBEDTLS_SSL_DEBUG_MSG(4, ("ticket: obfuscated_ticket_age: %u",
+                                  (unsigned) obfuscated_ticket_age));
+        return SSL_TLS1_3_OFFERED_PSK_MATCH;
+    }
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+    /* Check identity with external configured function */
+    if (ssl->conf->f_psk != NULL) {
+        if (ssl->conf->f_psk(
+                ssl->conf->p_psk, ssl, identity, identity_len) == 0) {
+            return SSL_TLS1_3_OFFERED_PSK_MATCH;
+        }
+        return SSL_TLS1_3_OFFERED_PSK_NOT_MATCH;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(5, "identity", identity, identity_len);
+    /* Check identity with pre-configured psk */
+    if (ssl->conf->psk_identity != NULL &&
+        identity_len == ssl->conf->psk_identity_len &&
+        mbedtls_ct_memcmp(ssl->conf->psk_identity,
+                          identity, identity_len) == 0) {
+        ret = mbedtls_ssl_set_hs_psk(ssl, ssl->conf->psk, ssl->conf->psk_len);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret);
+            return ret;
+        }
+        return SSL_TLS1_3_OFFERED_PSK_MATCH;
+    }
+
+    return SSL_TLS1_3_OFFERED_PSK_NOT_MATCH;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_offered_psks_check_binder_match(mbedtls_ssl_context *ssl,
+                                                     const unsigned char *binder,
+                                                     size_t binder_len,
+                                                     int psk_type,
+                                                     psa_algorithm_t psk_hash_alg)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    unsigned char transcript[PSA_HASH_MAX_SIZE];
+    size_t transcript_len;
+    unsigned char *psk;
+    size_t psk_len;
+    unsigned char server_computed_binder[PSA_HASH_MAX_SIZE];
+
+    /* Get current state of handshake transcript. */
+    ret = mbedtls_ssl_get_handshake_transcript(
+        ssl, mbedtls_hash_info_md_from_psa(psk_hash_alg),
+        transcript, sizeof(transcript), &transcript_len);
+    if (ret != 0) {
+        return ret;
+    }
+
+    ret = mbedtls_ssl_tls13_export_handshake_psk(ssl, &psk, &psk_len);
+    if (ret != 0) {
+        return ret;
+    }
+
+    ret = mbedtls_ssl_tls13_create_psk_binder(ssl, psk_hash_alg,
+                                              psk, psk_len, psk_type,
+                                              transcript,
+                                              server_computed_binder);
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    mbedtls_free((void *) psk);
+#endif
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("PSK binder calculation failed."));
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "psk binder ( computed ): ",
+                          server_computed_binder, transcript_len);
+    MBEDTLS_SSL_DEBUG_BUF(3, "psk binder ( received ): ", binder, binder_len);
+
+    if (mbedtls_ct_memcmp(server_computed_binder, binder, binder_len) == 0) {
+        return SSL_TLS1_3_OFFERED_PSK_MATCH;
+    }
+
+    mbedtls_platform_zeroize(server_computed_binder,
+                             sizeof(server_computed_binder));
+    return SSL_TLS1_3_OFFERED_PSK_NOT_MATCH;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_select_ciphersuite_for_psk(
+    mbedtls_ssl_context *ssl,
+    const unsigned char *cipher_suites,
+    const unsigned char *cipher_suites_end,
+    uint16_t *selected_ciphersuite,
+    const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info)
+{
+    psa_algorithm_t psk_hash_alg = PSA_ALG_SHA_256;
+
+    *selected_ciphersuite = 0;
+    *selected_ciphersuite_info = NULL;
+
+    /* RFC 8446, page 55.
+     *
+     * For externally established PSKs, the Hash algorithm MUST be set when the
+     * PSK is established or default to SHA-256 if no such algorithm is defined.
+     *
+     */
+
+    /*
+     * Search for a matching ciphersuite
+     */
+    for (const unsigned char *p = cipher_suites;
+         p < cipher_suites_end; p += 2) {
+        uint16_t cipher_suite;
+        const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+
+        cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0);
+        ciphersuite_info = ssl_tls13_validate_peer_ciphersuite(ssl,
+                                                               cipher_suite);
+        if (ciphersuite_info == NULL) {
+            continue;
+        }
+
+        /* MAC of selected ciphersuite MUST be same with PSK binder if exist.
+         * Otherwise, client should reject.
+         */
+        if (psk_hash_alg == mbedtls_psa_translate_md(ciphersuite_info->mac)) {
+            *selected_ciphersuite = cipher_suite;
+            *selected_ciphersuite_info = ciphersuite_info;
+            return 0;
+        }
+    }
+    MBEDTLS_SSL_DEBUG_MSG(2, ("No matched ciphersuite"));
+    return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+}
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_select_ciphersuite_for_resumption(
+    mbedtls_ssl_context *ssl,
+    const unsigned char *cipher_suites,
+    const unsigned char *cipher_suites_end,
+    mbedtls_ssl_session *session,
+    uint16_t *selected_ciphersuite,
+    const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info)
+{
+
+    *selected_ciphersuite = 0;
+    *selected_ciphersuite_info = NULL;
+    for (const unsigned char *p = cipher_suites; p < cipher_suites_end; p += 2) {
+        uint16_t cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0);
+        const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+
+        if (cipher_suite != session->ciphersuite) {
+            continue;
+        }
+
+        ciphersuite_info = ssl_tls13_validate_peer_ciphersuite(ssl,
+                                                               cipher_suite);
+        if (ciphersuite_info == NULL) {
+            continue;
+        }
+
+        *selected_ciphersuite = cipher_suite;
+        *selected_ciphersuite_info = ciphersuite_info;
+
+        return 0;
+    }
+
+    return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_session_copy_ticket(mbedtls_ssl_session *dst,
+                                         const mbedtls_ssl_session *src)
+{
+    dst->ticket_age_add = src->ticket_age_add;
+    dst->ticket_flags = src->ticket_flags;
+    dst->resumption_key_len = src->resumption_key_len;
+    if (src->resumption_key_len == 0) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+    memcpy(dst->resumption_key, src->resumption_key, src->resumption_key_len);
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+/* Parser for pre_shared_key extension in client hello
+ *    struct {
+ *        opaque identity<1..2^16-1>;
+ *        uint32 obfuscated_ticket_age;
+ *    } PskIdentity;
+ *
+ *    opaque PskBinderEntry<32..255>;
+ *
+ *    struct {
+ *        PskIdentity identities<7..2^16-1>;
+ *        PskBinderEntry binders<33..2^16-1>;
+ *    } OfferedPsks;
+ *
+ *    struct {
+ *        select (Handshake.msg_type) {
+ *            case client_hello: OfferedPsks;
+ *            ....
+ *        };
+ *    } PreSharedKeyExtension;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_pre_shared_key_ext(mbedtls_ssl_context *ssl,
+                                              const unsigned char *pre_shared_key_ext,
+                                              const unsigned char *pre_shared_key_ext_end,
+                                              const unsigned char *ciphersuites,
+                                              const unsigned char *ciphersuites_end)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const unsigned char *identities = pre_shared_key_ext;
+    const unsigned char *p_identity_len;
+    size_t identities_len;
+    const unsigned char *identities_end;
+    const unsigned char *binders;
+    const unsigned char *p_binder_len;
+    size_t binders_len;
+    const unsigned char *binders_end;
+    int matched_identity = -1;
+    int identity_id = -1;
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "pre_shared_key extension",
+                          pre_shared_key_ext,
+                          pre_shared_key_ext_end - pre_shared_key_ext);
+
+    /* identities_len       2 bytes
+     * identities_data   >= 7 bytes
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(identities, pre_shared_key_ext_end, 7 + 2);
+    identities_len = MBEDTLS_GET_UINT16_BE(identities, 0);
+    p_identity_len = identities + 2;
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p_identity_len, pre_shared_key_ext_end,
+                                 identities_len);
+    identities_end = p_identity_len + identities_len;
+
+    /* binders_len     2  bytes
+     * binders      >= 33 bytes
+     */
+    binders = identities_end;
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(binders, pre_shared_key_ext_end, 33 + 2);
+    binders_len = MBEDTLS_GET_UINT16_BE(binders, 0);
+    p_binder_len = binders + 2;
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p_binder_len, pre_shared_key_ext_end, binders_len);
+    binders_end = p_binder_len + binders_len;
+
+    ret = ssl->handshake->update_checksum(ssl, pre_shared_key_ext,
+                                          identities_end - pre_shared_key_ext);
+    if (0 != ret) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret);
+        return ret;
+    }
+
+    while (p_identity_len < identities_end && p_binder_len < binders_end) {
+        const unsigned char *identity;
+        size_t identity_len;
+        uint32_t obfuscated_ticket_age;
+        const unsigned char *binder;
+        size_t binder_len;
+        int psk_type;
+        uint16_t cipher_suite;
+        const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+        mbedtls_ssl_session session;
+        mbedtls_ssl_session_init(&session);
+#endif
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p_identity_len, identities_end, 2 + 1 + 4);
+        identity_len = MBEDTLS_GET_UINT16_BE(p_identity_len, 0);
+        identity = p_identity_len + 2;
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(identity, identities_end, identity_len + 4);
+        obfuscated_ticket_age = MBEDTLS_GET_UINT32_BE(identity, identity_len);
+        p_identity_len += identity_len + 6;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p_binder_len, binders_end, 1 + 32);
+        binder_len = *p_binder_len;
+        binder = p_binder_len + 1;
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(binder, binders_end, binder_len);
+        p_binder_len += binder_len + 1;
+
+        identity_id++;
+        if (matched_identity != -1) {
+            continue;
+        }
+
+        ret = ssl_tls13_offered_psks_check_identity_match(
+            ssl, identity, identity_len, obfuscated_ticket_age,
+            &psk_type, &session);
+        if (ret != SSL_TLS1_3_OFFERED_PSK_MATCH) {
+            continue;
+        }
+
+        MBEDTLS_SSL_DEBUG_MSG(4, ("found matched identity"));
+        switch (psk_type) {
+            case MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL:
+                ret = ssl_tls13_select_ciphersuite_for_psk(
+                    ssl, ciphersuites, ciphersuites_end,
+                    &cipher_suite, &ciphersuite_info);
+                break;
+            case MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION:
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+                ret = ssl_tls13_select_ciphersuite_for_resumption(
+                    ssl, ciphersuites, ciphersuites_end, &session,
+                    &cipher_suite, &ciphersuite_info);
+                if (ret != 0) {
+                    mbedtls_ssl_session_free(&session);
+                }
+#else
+                ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+#endif
+                break;
+            default:
+                return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        }
+        if (ret != 0) {
+            /* See below, no cipher_suite available, abort handshake */
+            MBEDTLS_SSL_PEND_FATAL_ALERT(
+                MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR,
+                MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
+            MBEDTLS_SSL_DEBUG_RET(
+                2, "ssl_tls13_select_ciphersuite", ret);
+            return ret;
+        }
+
+        ret = ssl_tls13_offered_psks_check_binder_match(
+            ssl, binder, binder_len, psk_type,
+            mbedtls_psa_translate_md(ciphersuite_info->mac));
+        if (ret != SSL_TLS1_3_OFFERED_PSK_MATCH) {
+            /* For security reasons, the handshake should be aborted when we
+             * fail to validate a binder value. See RFC 8446 section 4.2.11.2
+             * and appendix E.6. */
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+            mbedtls_ssl_session_free(&session);
+#endif
+            MBEDTLS_SSL_DEBUG_MSG(3, ("Invalid binder."));
+            MBEDTLS_SSL_DEBUG_RET(1,
+                                  "ssl_tls13_offered_psks_check_binder_match", ret);
+            MBEDTLS_SSL_PEND_FATAL_ALERT(
+                MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR,
+                MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
+            return ret;
+        }
+
+        matched_identity = identity_id;
+
+        /* Update handshake parameters */
+        ssl->handshake->ciphersuite_info = ciphersuite_info;
+        ssl->session_negotiate->ciphersuite = cipher_suite;
+        MBEDTLS_SSL_DEBUG_MSG(2, ("overwrite ciphersuite: %04x - %s",
+                                  cipher_suite, ciphersuite_info->name));
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+        if (psk_type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) {
+            ret = ssl_tls13_session_copy_ticket(ssl->session_negotiate,
+                                                &session);
+            mbedtls_ssl_session_free(&session);
+            if (ret != 0) {
+                return ret;
+            }
+        }
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+    }
+
+    if (p_identity_len != identities_end || p_binder_len != binders_end) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("pre_shared_key extension decode error"));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
+                                     MBEDTLS_ERR_SSL_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /* Update the handshake transcript with the binder list. */
+    ret = ssl->handshake->update_checksum(ssl,
+                                          identities_end,
+                                          (size_t) (binders_end - identities_end));
+    if (0 != ret) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret);
+        return ret;
+    }
+    if (matched_identity == -1) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("No matched PSK or ticket."));
+        return MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;
+    }
+
+    ssl->handshake->selected_identity = (uint16_t) matched_identity;
+    MBEDTLS_SSL_DEBUG_MSG(3, ("Pre shared key found"));
+
+    return 0;
+}
+
+/*
+ * struct {
+ *   select ( Handshake.msg_type ) {
+ *      ....
+ *      case server_hello:
+ *          uint16 selected_identity;
+ *   }
+ * } PreSharedKeyExtension;
+ */
+static int ssl_tls13_write_server_pre_shared_key_ext(mbedtls_ssl_context *ssl,
+                                                     unsigned char *buf,
+                                                     unsigned char *end,
+                                                     size_t *olen)
+{
+    unsigned char *p = (unsigned char *) buf;
+
+    *olen = 0;
+
+    int not_using_psk = 0;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    not_using_psk = (mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque));
+#else
+    not_using_psk = (ssl->handshake->psk == NULL);
+#endif
+    if (not_using_psk) {
+        /* We shouldn't have called this extension writer unless we've
+         * chosen to use a PSK. */
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding pre_shared_key extension"));
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6);
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PRE_SHARED_KEY, p, 0);
+    MBEDTLS_PUT_UINT16_BE(2, p, 2);
+
+    MBEDTLS_PUT_UINT16_BE(ssl->handshake->selected_identity, p, 4);
+
+    *olen = 6;
+
+    MBEDTLS_SSL_DEBUG_MSG(4, ("sent selected_identity: %u",
+                              ssl->handshake->selected_identity));
+
+    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_PRE_SHARED_KEY);
+
+    return 0;
+}
+
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
+
+/* From RFC 8446:
+ *   struct {
+ *          ProtocolVersion versions<2..254>;
+ *   } SupportedVersions;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_supported_versions_ext(mbedtls_ssl_context *ssl,
+                                                  const unsigned char *buf,
+                                                  const unsigned char *end)
+{
+    const unsigned char *p = buf;
+    size_t versions_len;
+    const unsigned char *versions_end;
+    uint16_t tls_version;
+    int tls13_supported = 0;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1);
+    versions_len = p[0];
+    p += 1;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, versions_len);
+    versions_end = p + versions_len;
+    while (p < versions_end) {
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, versions_end, 2);
+        tls_version = mbedtls_ssl_read_version(p, ssl->conf->transport);
+        p += 2;
+
+        /* In this implementation we only support TLS 1.3 and DTLS 1.3. */
+        if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
+            tls13_supported = 1;
+            break;
+        }
+    }
+
+    if (!tls13_supported) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("TLS 1.3 is not supported by the client"));
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION,
+                                     MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION);
+        return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(1, ("Negotiated version. Supported is [%04x]",
+                              (unsigned int) tls_version));
+
+    return 0;
+}
+
+#if defined(MBEDTLS_ECDH_C)
+/*
+ *
+ * From RFC 8446:
+ *   enum {
+ *       ... (0xFFFF)
+ *   } NamedGroup;
+ *   struct {
+ *       NamedGroup named_group_list<2..2^16-1>;
+ *   } NamedGroupList;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_supported_groups_ext(mbedtls_ssl_context *ssl,
+                                                const unsigned char *buf,
+                                                const unsigned char *end)
+{
+    const unsigned char *p = buf;
+    size_t named_group_list_len;
+    const unsigned char *named_group_list_end;
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "supported_groups extension", p, end - buf);
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    named_group_list_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, named_group_list_len);
+    named_group_list_end = p + named_group_list_len;
+    ssl->handshake->hrr_selected_group = 0;
+
+    while (p < named_group_list_end) {
+        uint16_t named_group;
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, named_group_list_end, 2);
+        named_group = MBEDTLS_GET_UINT16_BE(p, 0);
+        p += 2;
+
+        MBEDTLS_SSL_DEBUG_MSG(2,
+                              ("got named group: %s(%04x)",
+                               mbedtls_ssl_named_group_to_str(named_group),
+                               named_group));
+
+        if (!mbedtls_ssl_named_group_is_offered(ssl, named_group) ||
+            !mbedtls_ssl_named_group_is_supported(named_group) ||
+            ssl->handshake->hrr_selected_group != 0) {
+            continue;
+        }
+
+        MBEDTLS_SSL_DEBUG_MSG(2,
+                              ("add named group %s(%04x) into received list.",
+                               mbedtls_ssl_named_group_to_str(named_group),
+                               named_group));
+
+        ssl->handshake->hrr_selected_group = named_group;
+    }
+
+    return 0;
+
+}
+#endif /* MBEDTLS_ECDH_C */
+
+#define SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH 1
+
+#if defined(MBEDTLS_ECDH_C)
+/*
+ *  ssl_tls13_parse_key_shares_ext() verifies whether the information in the
+ *  extension is correct and stores the first acceptable key share and its associated group.
+ *
+ *  Possible return values are:
+ *  - 0: Successful processing of the client provided key share extension.
+ *  - SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH: The key shares provided by the client
+ *    does not match a group supported by the server. A HelloRetryRequest will
+ *    be needed.
+ *  - A negative value for fatal errors.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_key_shares_ext(mbedtls_ssl_context *ssl,
+                                          const unsigned char *buf,
+                                          const unsigned char *end)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char const *p = buf;
+    unsigned char const *client_shares_end;
+    size_t client_shares_len;
+
+    /* From RFC 8446:
+     *
+     * struct {
+     *     KeyShareEntry client_shares<0..2^16-1>;
+     * } KeyShareClientHello;
+     *
+     */
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    client_shares_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, client_shares_len);
+
+    ssl->handshake->offered_group_id = 0;
+    client_shares_end = p + client_shares_len;
+
+    /* We try to find a suitable key share entry and copy it to the
+     * handshake context. Later, we have to find out whether we can do
+     * something with the provided key share or whether we have to
+     * dismiss it and send a HelloRetryRequest message.
+     */
+
+    while (p < client_shares_end) {
+        uint16_t group;
+        size_t key_exchange_len;
+        const unsigned char *key_exchange;
+
+        /*
+         * struct {
+         *    NamedGroup group;
+         *    opaque key_exchange<1..2^16-1>;
+         * } KeyShareEntry;
+         */
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, client_shares_end, 4);
+        group = MBEDTLS_GET_UINT16_BE(p, 0);
+        key_exchange_len = MBEDTLS_GET_UINT16_BE(p, 2);
+        p += 4;
+        key_exchange = p;
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, client_shares_end, key_exchange_len);
+        p += key_exchange_len;
+
+        /* Continue parsing even if we have already found a match,
+         * for input validation purposes.
+         */
+        if (!mbedtls_ssl_named_group_is_offered(ssl, group) ||
+            !mbedtls_ssl_named_group_is_supported(group) ||
+            ssl->handshake->offered_group_id != 0) {
+            continue;
+        }
+
+        /*
+         * For now, we only support ECDHE groups.
+         */
+        if (mbedtls_ssl_tls13_named_group_is_ecdhe(group)) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("ECDH group: %s (%04x)",
+                                      mbedtls_ssl_named_group_to_str(group),
+                                      group));
+            ret = mbedtls_ssl_tls13_read_public_ecdhe_share(
+                ssl, key_exchange - 2, key_exchange_len + 2);
+            if (ret != 0) {
+                return ret;
+            }
+
+        } else {
+            MBEDTLS_SSL_DEBUG_MSG(4, ("Unrecognized NamedGroup %u",
+                                      (unsigned) group));
+            continue;
+        }
+
+        ssl->handshake->offered_group_id = group;
+    }
+
+
+    if (ssl->handshake->offered_group_id == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("no matching key share"));
+        return SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH;
+    }
+    return 0;
+}
+#endif /* MBEDTLS_ECDH_C */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_client_hello_has_exts(mbedtls_ssl_context *ssl,
+                                           int exts_mask)
+{
+    int masked = ssl->handshake->received_extensions & exts_mask;
+    return masked == exts_mask;
+}
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_client_hello_has_exts_for_ephemeral_key_exchange(
+    mbedtls_ssl_context *ssl)
+{
+    return ssl_tls13_client_hello_has_exts(
+        ssl,
+        MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) |
+        MBEDTLS_SSL_EXT_MASK(KEY_SHARE)        |
+        MBEDTLS_SSL_EXT_MASK(SIG_ALG));
+}
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_client_hello_has_exts_for_psk_key_exchange(
+    mbedtls_ssl_context *ssl)
+{
+    return ssl_tls13_client_hello_has_exts(
+        ssl,
+        MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)          |
+        MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES));
+}
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED */
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange(
+    mbedtls_ssl_context *ssl)
+{
+    return ssl_tls13_client_hello_has_exts(
+        ssl,
+        MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS)        |
+        MBEDTLS_SSL_EXT_MASK(KEY_SHARE)               |
+        MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)          |
+        MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES));
+}
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_check_ephemeral_key_exchange(mbedtls_ssl_context *ssl)
+{
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+    return mbedtls_ssl_conf_tls13_ephemeral_enabled(ssl) &&
+           ssl_tls13_client_hello_has_exts_for_ephemeral_key_exchange(ssl);
+#else
+    ((void) ssl);
+    return 0;
+#endif
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_check_psk_key_exchange(mbedtls_ssl_context *ssl)
+{
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED)
+    return mbedtls_ssl_conf_tls13_psk_enabled(ssl) &&
+           mbedtls_ssl_tls13_psk_enabled(ssl) &&
+           ssl_tls13_client_hello_has_exts_for_psk_key_exchange(ssl);
+#else
+    ((void) ssl);
+    return 0;
+#endif
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_check_psk_ephemeral_key_exchange(mbedtls_ssl_context *ssl)
+{
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
+    return mbedtls_ssl_conf_tls13_psk_ephemeral_enabled(ssl) &&
+           mbedtls_ssl_tls13_psk_ephemeral_enabled(ssl) &&
+           ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange(ssl);
+#else
+    ((void) ssl);
+    return 0;
+#endif
+}
+
+static int ssl_tls13_determine_key_exchange_mode(mbedtls_ssl_context *ssl)
+{
+    /*
+     * Determine the key exchange algorithm to use.
+     * There are three types of key exchanges supported in TLS 1.3:
+     * - (EC)DH with ECDSA,
+     * - (EC)DH with PSK,
+     * - plain PSK.
+     *
+     * The PSK-based key exchanges may additionally be used with 0-RTT.
+     *
+     * Our built-in order of preference is
+     *  1 ) (EC)DHE-PSK Mode ( psk_ephemeral )
+     *  2 ) Certificate Mode ( ephemeral )
+     *  3 ) Plain PSK Mode ( psk )
+     */
+
+    ssl->handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE;
+
+    if (ssl_tls13_check_psk_ephemeral_key_exchange(ssl)) {
+        ssl->handshake->key_exchange_mode =
+            MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
+        MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk_ephemeral"));
+    } else
+    if (ssl_tls13_check_ephemeral_key_exchange(ssl)) {
+        ssl->handshake->key_exchange_mode =
+            MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL;
+        MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: ephemeral"));
+    } else
+    if (ssl_tls13_check_psk_key_exchange(ssl)) {
+        ssl->handshake->key_exchange_mode =
+            MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;
+        MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk"));
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(
+            1,
+            ("ClientHello message misses mandatory extensions."));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_MISSING_EXTENSION,
+                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+    return 0;
+
+}
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
+    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+static psa_algorithm_t ssl_tls13_iana_sig_alg_to_psa_alg(uint16_t sig_alg)
+{
+    switch (sig_alg) {
+        case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256:
+            return PSA_ALG_ECDSA(PSA_ALG_SHA_256);
+        case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384:
+            return PSA_ALG_ECDSA(PSA_ALG_SHA_384);
+        case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512:
+            return PSA_ALG_ECDSA(PSA_ALG_SHA_512);
+        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256:
+            return PSA_ALG_RSA_PSS(PSA_ALG_SHA_256);
+        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384:
+            return PSA_ALG_RSA_PSS(PSA_ALG_SHA_384);
+        case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512:
+            return PSA_ALG_RSA_PSS(PSA_ALG_SHA_512);
+        case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256:
+            return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256);
+        case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384:
+            return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_384);
+        case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512:
+            return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_512);
+        default:
+            return PSA_ALG_NONE;
+    }
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+/*
+ * Pick best ( private key, certificate chain ) pair based on the signature
+ * algorithms supported by the client.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_pick_key_cert(mbedtls_ssl_context *ssl)
+{
+    mbedtls_ssl_key_cert *key_cert, *key_cert_list;
+    const uint16_t *sig_alg = ssl->handshake->received_sig_algs;
+
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    if (ssl->handshake->sni_key_cert != NULL) {
+        key_cert_list = ssl->handshake->sni_key_cert;
+    } else
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+    key_cert_list = ssl->conf->key_cert;
+
+    if (key_cert_list == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("server has no certificate"));
+        return -1;
+    }
+
+    for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) {
+        if (!mbedtls_ssl_sig_alg_is_offered(ssl, *sig_alg)) {
+            continue;
+        }
+
+        if (!mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(*sig_alg)) {
+            continue;
+        }
+
+        for (key_cert = key_cert_list; key_cert != NULL;
+             key_cert = key_cert->next) {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+            psa_algorithm_t psa_alg = PSA_ALG_NONE;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+            MBEDTLS_SSL_DEBUG_CRT(3, "certificate (chain) candidate",
+                                  key_cert->cert);
+
+            /*
+             * This avoids sending the client a cert it'll reject based on
+             * keyUsage or other extensions.
+             */
+            if (mbedtls_x509_crt_check_key_usage(
+                    key_cert->cert, MBEDTLS_X509_KU_DIGITAL_SIGNATURE) != 0 ||
+                mbedtls_x509_crt_check_extended_key_usage(
+                    key_cert->cert, MBEDTLS_OID_SERVER_AUTH,
+                    MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH)) != 0) {
+                MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: "
+                                          "(extended) key usage extension"));
+                continue;
+            }
+
+            MBEDTLS_SSL_DEBUG_MSG(3,
+                                  ("ssl_tls13_pick_key_cert:"
+                                   "check signature algorithm %s [%04x]",
+                                   mbedtls_ssl_sig_alg_to_str(*sig_alg),
+                                   *sig_alg));
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+            psa_alg = ssl_tls13_iana_sig_alg_to_psa_alg(*sig_alg);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+            if (mbedtls_ssl_tls13_check_sig_alg_cert_key_match(
+                    *sig_alg, &key_cert->cert->pk)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+                && psa_alg != PSA_ALG_NONE &&
+                mbedtls_pk_can_do_ext(&key_cert->cert->pk, psa_alg,
+                                      PSA_KEY_USAGE_SIGN_HASH) == 1
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+                ) {
+                ssl->handshake->key_cert = key_cert;
+                MBEDTLS_SSL_DEBUG_MSG(3,
+                                      ("ssl_tls13_pick_key_cert:"
+                                       "selected signature algorithm"
+                                       " %s [%04x]",
+                                       mbedtls_ssl_sig_alg_to_str(*sig_alg),
+                                       *sig_alg));
+                MBEDTLS_SSL_DEBUG_CRT(
+                    3, "selected certificate (chain)",
+                    ssl->handshake->key_cert->cert);
+                return 0;
+            }
+        }
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("ssl_tls13_pick_key_cert:"
+                              "no suitable certificate found"));
+    return -1;
+}
+#endif /* MBEDTLS_X509_CRT_PARSE_C &&
+          MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+
+/*
+ *
+ * STATE HANDLING: ClientHello
+ *
+ * There are three possible classes of outcomes when parsing the ClientHello:
+ *
+ * 1) The ClientHello was well-formed and matched the server's configuration.
+ *
+ *    In this case, the server progresses to sending its ServerHello.
+ *
+ * 2) The ClientHello was well-formed but didn't match the server's
+ *    configuration.
+ *
+ *    For example, the client might not have offered a key share which
+ *    the server supports, or the server might require a cookie.
+ *
+ *    In this case, the server sends a HelloRetryRequest.
+ *
+ * 3) The ClientHello was ill-formed
+ *
+ *    In this case, we abort the handshake.
+ *
+ */
+
+/*
+ * Structure of this message:
+ *
+ * uint16 ProtocolVersion;
+ * opaque Random[32];
+ * uint8 CipherSuite[2];    // Cryptographic suite selector
+ *
+ * struct {
+ *      ProtocolVersion legacy_version = 0x0303;    // TLS v1.2
+ *      Random random;
+ *      opaque legacy_session_id<0..32>;
+ *      CipherSuite cipher_suites<2..2^16-2>;
+ *      opaque legacy_compression_methods<1..2^8-1>;
+ *      Extension extensions<8..2^16-1>;
+ * } ClientHello;
+ */
+
+#define SSL_CLIENT_HELLO_OK           0
+#define SSL_CLIENT_HELLO_HRR_REQUIRED 1
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
+                                        const unsigned char *buf,
+                                        const unsigned char *end)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const unsigned char *p = buf;
+    size_t legacy_session_id_len;
+    size_t cipher_suites_len;
+    const unsigned char *cipher_suites_end;
+    size_t extensions_len;
+    const unsigned char *extensions_end;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    int hrr_required = 0;
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    const unsigned char *cipher_suites;
+    const unsigned char *pre_shared_key_ext = NULL;
+    const unsigned char *pre_shared_key_ext_end = NULL;
+#endif
+
+    /*
+     * ClientHello layout:
+     *     0  .   1   protocol version
+     *     2  .  33   random bytes
+     *    34  .  34   session id length ( 1 byte )
+     *    35  . 34+x  session id
+     *    ..  .  ..   ciphersuite list length ( 2 bytes )
+     *    ..  .  ..   ciphersuite list
+     *    ..  .  ..   compression alg. list length ( 1 byte )
+     *    ..  .  ..   compression alg. list
+     *    ..  .  ..   extensions length ( 2 bytes, optional )
+     *    ..  .  ..   extensions ( optional )
+     */
+
+    /*
+     * Minimal length ( with everything empty and extensions omitted ) is
+     * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can
+     * read at least up to session id length without worrying.
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 38);
+
+    /* ...
+     * ProtocolVersion legacy_version = 0x0303; // TLS 1.2
+     * ...
+     * with ProtocolVersion defined as:
+     * uint16 ProtocolVersion;
+     */
+    if (mbedtls_ssl_read_version(p, ssl->conf->transport) !=
+        MBEDTLS_SSL_VERSION_TLS1_2) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Unsupported version of TLS."));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION,
+                                     MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION);
+        return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;
+    }
+    p += 2;
+
+    /*
+     * Only support TLS 1.3 currently, temporarily set the version.
+     */
+    ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+    /* Store minor version for later use with ticket serialization. */
+    ssl->session_negotiate->tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
+    ssl->session_negotiate->endpoint = ssl->conf->endpoint;
+#endif
+
+    /* ...
+     * Random random;
+     * ...
+     * with Random defined as:
+     * opaque Random[32];
+     */
+    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, random bytes",
+                          p, MBEDTLS_CLIENT_HELLO_RANDOM_LEN);
+
+    memcpy(&handshake->randbytes[0], p, MBEDTLS_CLIENT_HELLO_RANDOM_LEN);
+    p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN;
+
+    /* ...
+     * opaque legacy_session_id<0..32>;
+     * ...
+     */
+    legacy_session_id_len = p[0];
+    p++;
+
+    if (legacy_session_id_len > sizeof(ssl->session_negotiate->id)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    ssl->session_negotiate->id_len = legacy_session_id_len;
+    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, session id",
+                          p, legacy_session_id_len);
+    /*
+     * Check we have enough data for the legacy session identifier
+     * and the ciphersuite list length.
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_len + 2);
+
+    memcpy(&ssl->session_negotiate->id[0], p, legacy_session_id_len);
+    p += legacy_session_id_len;
+
+    cipher_suites_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+
+    /*
+     * The length of the ciphersuite list has to be even.
+     */
+    if (cipher_suites_len & 1) {
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
+                                     MBEDTLS_ERR_SSL_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
+
+    /* Check we have enough data for the ciphersuite list, the legacy
+     * compression methods and the length of the extensions.
+     *
+     * cipher_suites                cipher_suites_len bytes
+     * legacy_compression_methods                   2 bytes
+     * extensions_len                               2 bytes
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, cipher_suites_len + 2 + 2);
+
+    /* ...
+     * CipherSuite cipher_suites<2..2^16-2>;
+     * ...
+     * with CipherSuite defined as:
+     * uint8 CipherSuite[2];
+     */
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    cipher_suites = p;
+#endif
+    cipher_suites_end = p + cipher_suites_len;
+    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, ciphersuitelist",
+                          p, cipher_suites_len);
+
+    /*
+     * Search for a matching ciphersuite
+     */
+    for (; p < cipher_suites_end; p += 2) {
+        uint16_t cipher_suite;
+        const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+
+        /*
+         * "cipher_suite_end - p is even" is an invariant of the loop. As
+         * cipher_suites_end - p > 0, we have cipher_suites_end - p >= 2 and
+         * it is thus safe to read two bytes.
+         */
+        cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0);
+        ciphersuite_info = ssl_tls13_validate_peer_ciphersuite(
+            ssl, cipher_suite);
+        if (ciphersuite_info == NULL) {
+            continue;
+        }
+
+        ssl->session_negotiate->ciphersuite = cipher_suite;
+        handshake->ciphersuite_info = ciphersuite_info;
+        MBEDTLS_SSL_DEBUG_MSG(2, ("selected ciphersuite: %04x - %s",
+                                  cipher_suite,
+                                  ciphersuite_info->name));
+        break;
+    }
+
+    if (handshake->ciphersuite_info == NULL) {
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
+                                     MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+    p = cipher_suites_end;
+
+    /* ...
+     * opaque legacy_compression_methods<1..2^8-1>;
+     * ...
+     */
+    if (p[0] != 1 || p[1] != MBEDTLS_SSL_COMPRESS_NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad legacy compression method"));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+    p += 2;
+
+    /* ...
+     * Extension extensions<8..2^16-1>;
+     * ...
+     * with Extension defined as:
+     * struct {
+     *    ExtensionType extension_type;
+     *    opaque extension_data<0..2^16-1>;
+     * } Extension;
+     */
+    extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len);
+    extensions_end = p + extensions_len;
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "client hello extensions", p, extensions_len);
+
+    handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;
+
+    while (p < extensions_end) {
+        unsigned int extension_type;
+        size_t extension_data_len;
+        const unsigned char *extension_data_end;
+
+        /* RFC 8446, section 4.2.11
+         *
+         * The "pre_shared_key" extension MUST be the last extension in the
+         * ClientHello (this facilitates implementation as described below).
+         * Servers MUST check that it is the last extension and otherwise fail
+         * the handshake with an "illegal_parameter" alert.
+         */
+        if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)) {
+            MBEDTLS_SSL_DEBUG_MSG(
+                3, ("pre_shared_key is not last extension."));
+            MBEDTLS_SSL_PEND_FATAL_ALERT(
+                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+        }
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4);
+        extension_type = MBEDTLS_GET_UINT16_BE(p, 0);
+        extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);
+        p += 4;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len);
+        extension_data_end = p + extension_data_len;
+
+        ret = mbedtls_ssl_tls13_check_received_extension(
+            ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, extension_type,
+            MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH);
+        if (ret != 0) {
+            return ret;
+        }
+
+        switch (extension_type) {
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+            case MBEDTLS_TLS_EXT_SERVERNAME:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found ServerName extension"));
+                ret = mbedtls_ssl_parse_server_name_ext(ssl, p,
+                                                        extension_data_end);
+                if (ret != 0) {
+                    MBEDTLS_SSL_DEBUG_RET(
+                        1, "mbedtls_ssl_parse_servername_ext", ret);
+                    return ret;
+                }
+                break;
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+
+#if defined(MBEDTLS_ECDH_C)
+            case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found supported group extension"));
+
+                /* Supported Groups Extension
+                 *
+                 * When sent by the client, the "supported_groups" extension
+                 * indicates the named groups which the client supports,
+                 * ordered from most preferred to least preferred.
+                 */
+                ret = ssl_tls13_parse_supported_groups_ext(
+                    ssl, p, extension_data_end);
+                if (ret != 0) {
+                    MBEDTLS_SSL_DEBUG_RET(1,
+                                          "mbedtls_ssl_parse_supported_groups_ext", ret);
+                    return ret;
+                }
+
+                break;
+#endif /* MBEDTLS_ECDH_C */
+
+#if defined(MBEDTLS_ECDH_C)
+            case MBEDTLS_TLS_EXT_KEY_SHARE:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found key share extension"));
+
+                /*
+                 * Key Share Extension
+                 *
+                 * When sent by the client, the "key_share" extension
+                 * contains the endpoint's cryptographic parameters for
+                 * ECDHE/DHE key establishment methods.
+                 */
+                ret = ssl_tls13_parse_key_shares_ext(
+                    ssl, p, extension_data_end);
+                if (ret == SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH) {
+                    MBEDTLS_SSL_DEBUG_MSG(2, ("HRR needed "));
+                    hrr_required = 1;
+                }
+
+                if (ret < 0) {
+                    MBEDTLS_SSL_DEBUG_RET(
+                        1, "ssl_tls13_parse_key_shares_ext", ret);
+                    return ret;
+                }
+
+                break;
+#endif /* MBEDTLS_ECDH_C */
+
+            case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found supported versions extension"));
+
+                ret = ssl_tls13_parse_supported_versions_ext(
+                    ssl, p, extension_data_end);
+                if (ret != 0) {
+                    MBEDTLS_SSL_DEBUG_RET(1,
+                                          ("ssl_tls13_parse_supported_versions_ext"), ret);
+                    return ret;
+                }
+                break;
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+            case MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found psk key exchange modes extension"));
+
+                ret = ssl_tls13_parse_key_exchange_modes_ext(
+                    ssl, p, extension_data_end);
+                if (ret != 0) {
+                    MBEDTLS_SSL_DEBUG_RET(
+                        1, "ssl_tls13_parse_key_exchange_modes_ext", ret);
+                    return ret;
+                }
+
+                break;
+#endif
+
+            case MBEDTLS_TLS_EXT_PRE_SHARED_KEY:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found pre_shared_key extension"));
+                if ((handshake->received_extensions &
+                     MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES)) == 0) {
+                    MBEDTLS_SSL_PEND_FATAL_ALERT(
+                        MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                        MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+                    return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+                }
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+                /* Delay processing of the PSK identity once we have
+                 * found out which algorithms to use. We keep a pointer
+                 * to the buffer and the size for later processing.
+                 */
+                pre_shared_key_ext = p;
+                pre_shared_key_ext_end = extension_data_end;
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
+                break;
+
+#if defined(MBEDTLS_SSL_ALPN)
+            case MBEDTLS_TLS_EXT_ALPN:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension"));
+
+                ret = mbedtls_ssl_parse_alpn_ext(ssl, p, extension_data_end);
+                if (ret != 0) {
+                    MBEDTLS_SSL_DEBUG_RET(
+                        1, ("mbedtls_ssl_parse_alpn_ext"), ret);
+                    return ret;
+                }
+                break;
+#endif /* MBEDTLS_SSL_ALPN */
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+            case MBEDTLS_TLS_EXT_SIG_ALG:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found signature_algorithms extension"));
+
+                ret = mbedtls_ssl_parse_sig_alg_ext(
+                    ssl, p, extension_data_end);
+                if (ret != 0) {
+                    MBEDTLS_SSL_DEBUG_MSG(1,
+                                          (
+                                              "ssl_parse_supported_signature_algorithms_server_ext ( %d )",
+                                              ret));
+                    return ret;
+                }
+                break;
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+            case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found record_size_limit extension"));
+
+                ret = mbedtls_ssl_tls13_parse_record_size_limit_ext(ssl, p, extension_data_end);
+
+                /* TODO: Return unconditionally here until we handle the record size limit correctly.
+                 *            Once handled correctly, only return in case of errors. */
+                return ret;
+
+                break;
+#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
+
+            default:
+                MBEDTLS_SSL_PRINT_EXT(
+                    3, MBEDTLS_SSL_HS_CLIENT_HELLO,
+                    extension_type, "( ignored )");
+                break;
+        }
+
+        p += extension_data_len;
+    }
+
+    MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CLIENT_HELLO,
+                           handshake->received_extensions);
+
+    ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl,
+                                             MBEDTLS_SSL_HS_CLIENT_HELLO,
+                                             p - buf);
+    if (0 != ret) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_add_hs_hdr_to_checksum"), ret);
+        return ret;
+    }
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    /* Update checksum with either
+     * - The entire content of the CH message, if no PSK extension is present
+     * - The content up to but excluding the PSK extension, if present.
+     */
+    /* If we've settled on a PSK-based exchange, parse PSK identity ext */
+    if (mbedtls_ssl_tls13_some_psk_enabled(ssl) &&
+        mbedtls_ssl_conf_tls13_some_psk_enabled(ssl) &&
+        (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY))) {
+        ret = handshake->update_checksum(ssl, buf,
+                                         pre_shared_key_ext - buf);
+        if (0 != ret) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret);
+            return ret;
+        }
+        ret = ssl_tls13_parse_pre_shared_key_ext(ssl,
+                                                 pre_shared_key_ext,
+                                                 pre_shared_key_ext_end,
+                                                 cipher_suites,
+                                                 cipher_suites_end);
+        if (ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) {
+            handshake->received_extensions &= ~MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY);
+        } else if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(
+                1, "ssl_tls13_parse_pre_shared_key_ext", ret);
+            return ret;
+        }
+    } else
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
+    {
+        ret = handshake->update_checksum(ssl, buf, p - buf);
+        if (0 != ret) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret);
+            return ret;
+        }
+    }
+
+    ret = ssl_tls13_determine_key_exchange_mode(ssl);
+    if (ret < 0) {
+        return ret;
+    }
+
+    mbedtls_ssl_optimize_checksum(ssl, handshake->ciphersuite_info);
+
+    return hrr_required ? SSL_CLIENT_HELLO_HRR_REQUIRED : SSL_CLIENT_HELLO_OK;
+}
+
+/* Update the handshake state machine */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_postprocess_client_hello(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    /*
+     * Server certificate selection
+     */
+    if (ssl->conf->f_cert_cb && (ret = ssl->conf->f_cert_cb(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "f_cert_cb", ret);
+        return ret;
+    }
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    ssl->handshake->sni_name = NULL;
+    ssl->handshake->sni_name_len = 0;
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+
+    ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1,
+                              "mbedtls_ssl_tls1_3_key_schedule_stage_early", ret);
+        return ret;
+    }
+
+    return 0;
+
+}
+
+/*
+ * Main entry point from the state machine; orchestrates the otherfunctions.
+ */
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_process_client_hello(mbedtls_ssl_context *ssl)
+{
+
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *buf = NULL;
+    size_t buflen = 0;
+    int parse_client_hello_ret;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client hello"));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(
+                             ssl, MBEDTLS_SSL_HS_CLIENT_HELLO,
+                             &buf, &buflen));
+
+    MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_parse_client_hello(ssl, buf,
+                                                          buf + buflen));
+    parse_client_hello_ret = ret; /* Store return value of parse_client_hello,
+                                   * only SSL_CLIENT_HELLO_OK or
+                                   * SSL_CLIENT_HELLO_HRR_REQUIRED at this
+                                   * stage as negative error codes are handled
+                                   * by MBEDTLS_SSL_PROC_CHK_NEG. */
+
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_client_hello(ssl));
+
+    if (parse_client_hello_ret == SSL_CLIENT_HELLO_OK) {
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO);
+    } else {
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HELLO_RETRY_REQUEST);
+    }
+
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse client hello"));
+    return ret;
+}
+
+/*
+ * Handler for MBEDTLS_SSL_SERVER_HELLO
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_prepare_server_hello(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *server_randbytes =
+        ssl->handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN;
+    if (ssl->conf->f_rng == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided"));
+        return MBEDTLS_ERR_SSL_NO_RNG;
+    }
+
+    if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, server_randbytes,
+                                MBEDTLS_SERVER_HELLO_RANDOM_LEN)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "f_rng", ret);
+        return ret;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", server_randbytes,
+                          MBEDTLS_SERVER_HELLO_RANDOM_LEN);
+
+#if defined(MBEDTLS_HAVE_TIME)
+    ssl->session_negotiate->start = time(NULL);
+#endif /* MBEDTLS_HAVE_TIME */
+
+    return ret;
+}
+
+/*
+ * ssl_tls13_write_server_hello_supported_versions_ext ():
+ *
+ * struct {
+ *      ProtocolVersion selected_version;
+ * } SupportedVersions;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_server_hello_supported_versions_ext(
+    mbedtls_ssl_context *ssl,
+    unsigned char *buf,
+    unsigned char *end,
+    size_t *out_len)
+{
+    *out_len = 0;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, write selected version"));
+
+    /* Check if we have space to write the extension:
+     * - extension_type         (2 bytes)
+     * - extension_data_length  (2 bytes)
+     * - selected_version       (2 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6);
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, buf, 0);
+
+    MBEDTLS_PUT_UINT16_BE(2, buf, 2);
+
+    mbedtls_ssl_write_version(buf + 4,
+                              ssl->conf->transport,
+                              ssl->tls_version);
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("supported version: [%04x]",
+                              ssl->tls_version));
+
+    *out_len = 6;
+
+    mbedtls_ssl_tls13_set_hs_sent_ext_mask(
+        ssl, MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS);
+
+    return 0;
+}
+
+
+
+/* Generate and export a single key share. For hybrid KEMs, this can
+ * be called multiple times with the different components of the hybrid. */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_generate_and_write_key_share(mbedtls_ssl_context *ssl,
+                                                  uint16_t named_group,
+                                                  unsigned char *buf,
+                                                  unsigned char *end,
+                                                  size_t *out_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    *out_len = 0;
+
+#if defined(MBEDTLS_ECDH_C)
+    if (mbedtls_ssl_tls13_named_group_is_ecdhe(named_group)) {
+        ret = mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange(
+            ssl, named_group, buf, end, out_len);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(
+                1, "mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange",
+                ret);
+            return ret;
+        }
+    } else
+#endif /* MBEDTLS_ECDH_C */
+    if (0 /* Other kinds of KEMs */) {
+    } else {
+        ((void) ssl);
+        ((void) named_group);
+        ((void) buf);
+        ((void) end);
+        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    return ret;
+}
+
+/*
+ * ssl_tls13_write_key_share_ext
+ *
+ * Structure of key_share extension in ServerHello:
+ *
+ * struct {
+ *     NamedGroup group;
+ *     opaque key_exchange<1..2^16-1>;
+ * } KeyShareEntry;
+ * struct {
+ *     KeyShareEntry server_share;
+ * } KeyShareServerHello;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_key_share_ext(mbedtls_ssl_context *ssl,
+                                         unsigned char *buf,
+                                         unsigned char *end,
+                                         size_t *out_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *p = buf;
+    uint16_t group = ssl->handshake->offered_group_id;
+    unsigned char *server_share = buf + 4;
+    size_t key_exchange_length;
+
+    *out_len = 0;
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding key share extension"));
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("server hello, write selected_group: %s (%04x)",
+                              mbedtls_ssl_named_group_to_str(group),
+                              group));
+
+    /* Check if we have space for header and length fields:
+     * - extension_type         (2 bytes)
+     * - extension_data_length  (2 bytes)
+     * - group                  (2 bytes)
+     * - key_exchange_length    (2 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 8);
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, p, 0);
+    MBEDTLS_PUT_UINT16_BE(group, server_share, 0);
+    p += 8;
+
+    /* When we introduce PQC-ECDHE hybrids, we'll want to call this
+     * function multiple times. */
+    ret = ssl_tls13_generate_and_write_key_share(
+        ssl, group, server_share + 4, end, &key_exchange_length);
+    if (ret != 0) {
+        return ret;
+    }
+    p += key_exchange_length;
+
+    MBEDTLS_PUT_UINT16_BE(key_exchange_length, server_share + 2, 0);
+
+    MBEDTLS_PUT_UINT16_BE(p - server_share, buf, 2);
+
+    *out_len = p - buf;
+
+    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE);
+
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_hrr_key_share_ext(mbedtls_ssl_context *ssl,
+                                             unsigned char *buf,
+                                             unsigned char *end,
+                                             size_t *out_len)
+{
+    uint16_t selected_group = ssl->handshake->hrr_selected_group;
+    /* key_share Extension
+     *
+     *  struct {
+     *    select (Handshake.msg_type) {
+     *      ...
+     *      case hello_retry_request:
+     *          NamedGroup selected_group;
+     *      ...
+     *    };
+     * } KeyShare;
+     */
+
+    *out_len = 0;
+
+    /*
+     * For a pure PSK key exchange, there is no group to agree upon. The purpose
+     * of the HRR is then to transmit a cookie to force the client to demonstrate
+     * reachability at their apparent network address (primarily useful for DTLS).
+     */
+    if (!mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) {
+        return 0;
+    }
+
+    /* We should only send the key_share extension if the client's initial
+     * key share was not acceptable. */
+    if (ssl->handshake->offered_group_id != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(4, ("Skip key_share extension in HRR"));
+        return 0;
+    }
+
+    if (selected_group == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("no matching named group found"));
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+    /* Check if we have enough space:
+     * - extension_type         (2 bytes)
+     * - extension_data_length  (2 bytes)
+     * - selected_group         (2 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6);
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, buf, 0);
+    MBEDTLS_PUT_UINT16_BE(2, buf, 2);
+    MBEDTLS_PUT_UINT16_BE(selected_group, buf, 4);
+
+    MBEDTLS_SSL_DEBUG_MSG(3,
+                          ("HRR selected_group: %s (%x)",
+                           mbedtls_ssl_named_group_to_str(selected_group),
+                           selected_group));
+
+    *out_len = 6;
+
+    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE);
+
+    return 0;
+}
+
+/*
+ * Structure of ServerHello message:
+ *
+ *     struct {
+ *        ProtocolVersion legacy_version = 0x0303;    // TLS v1.2
+ *        Random random;
+ *        opaque legacy_session_id_echo<0..32>;
+ *        CipherSuite cipher_suite;
+ *        uint8 legacy_compression_method = 0;
+ *        Extension extensions<6..2^16-1>;
+ *    } ServerHello;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_server_hello_body(mbedtls_ssl_context *ssl,
+                                             unsigned char *buf,
+                                             unsigned char *end,
+                                             size_t *out_len,
+                                             int is_hrr)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *p = buf;
+    unsigned char *p_extensions_len;
+    size_t output_len;
+
+    *out_len = 0;
+    ssl->handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE;
+
+    /* ...
+     * ProtocolVersion legacy_version = 0x0303; // TLS 1.2
+     * ...
+     * with ProtocolVersion defined as:
+     * uint16 ProtocolVersion;
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);
+    MBEDTLS_PUT_UINT16_BE(0x0303, p, 0);
+    p += 2;
+
+    /* ...
+     * Random random;
+     * ...
+     * with Random defined as:
+     * opaque Random[MBEDTLS_SERVER_HELLO_RANDOM_LEN];
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN);
+    if (is_hrr) {
+        memcpy(p, mbedtls_ssl_tls13_hello_retry_request_magic,
+               MBEDTLS_SERVER_HELLO_RANDOM_LEN);
+    } else {
+        memcpy(p, &ssl->handshake->randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN],
+               MBEDTLS_SERVER_HELLO_RANDOM_LEN);
+    }
+    MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes",
+                          p, MBEDTLS_SERVER_HELLO_RANDOM_LEN);
+    p += MBEDTLS_SERVER_HELLO_RANDOM_LEN;
+
+    /* ...
+     * opaque legacy_session_id_echo<0..32>;
+     * ...
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1 + ssl->session_negotiate->id_len);
+    *p++ = (unsigned char) ssl->session_negotiate->id_len;
+    if (ssl->session_negotiate->id_len > 0) {
+        memcpy(p, &ssl->session_negotiate->id[0],
+               ssl->session_negotiate->id_len);
+        p += ssl->session_negotiate->id_len;
+
+        MBEDTLS_SSL_DEBUG_BUF(3, "session id", ssl->session_negotiate->id,
+                              ssl->session_negotiate->id_len);
+    }
+
+    /* ...
+     * CipherSuite cipher_suite;
+     * ...
+     * with CipherSuite defined as:
+     * uint8 CipherSuite[2];
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);
+    MBEDTLS_PUT_UINT16_BE(ssl->session_negotiate->ciphersuite, p, 0);
+    p += 2;
+    MBEDTLS_SSL_DEBUG_MSG(3,
+                          ("server hello, chosen ciphersuite: %s ( id=%d )",
+                           mbedtls_ssl_get_ciphersuite_name(
+                               ssl->session_negotiate->ciphersuite),
+                           ssl->session_negotiate->ciphersuite));
+
+    /* ...
+     * uint8 legacy_compression_method = 0;
+     * ...
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1);
+    *p++ = MBEDTLS_SSL_COMPRESS_NULL;
+
+    /* ...
+     * Extension extensions<6..2^16-1>;
+     * ...
+     * struct {
+     *      ExtensionType extension_type; (2 bytes)
+     *      opaque extension_data<0..2^16-1>;
+     * } Extension;
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);
+    p_extensions_len = p;
+    p += 2;
+
+    if ((ret = ssl_tls13_write_server_hello_supported_versions_ext(
+             ssl, p, end, &output_len)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(
+            1, "ssl_tls13_write_server_hello_supported_versions_ext", ret);
+        return ret;
+    }
+    p += output_len;
+
+    if (mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) {
+        if (is_hrr) {
+            ret = ssl_tls13_write_hrr_key_share_ext(ssl, p, end, &output_len);
+        } else {
+            ret = ssl_tls13_write_key_share_ext(ssl, p, end, &output_len);
+        }
+        if (ret != 0) {
+            return ret;
+        }
+        p += output_len;
+    }
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    if (!is_hrr && mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) {
+        ret = ssl_tls13_write_server_pre_shared_key_ext(ssl, p, end, &output_len);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_write_server_pre_shared_key_ext",
+                                  ret);
+            return ret;
+        }
+        p += output_len;
+    }
+#endif
+
+    MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0);
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "server hello extensions",
+                          p_extensions_len, p - p_extensions_len);
+
+    *out_len = p - buf;
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "server hello", buf, *out_len);
+
+    MBEDTLS_SSL_PRINT_EXTS(
+        3, is_hrr ? MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST :
+        MBEDTLS_SSL_HS_SERVER_HELLO,
+        ssl->handshake->sent_extensions);
+
+    return ret;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_finalize_server_hello(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    ret = mbedtls_ssl_tls13_compute_handshake_transform(ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1,
+                              "mbedtls_ssl_tls13_compute_handshake_transform",
+                              ret);
+        return ret;
+    }
+
+    return ret;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_server_hello(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *buf;
+    size_t buf_len, msg_len;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write server hello"));
+
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_server_hello(ssl));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl,
+                                                         MBEDTLS_SSL_HS_SERVER_HELLO, &buf,
+                                                         &buf_len));
+
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_server_hello_body(ssl, buf,
+                                                           buf + buf_len,
+                                                           &msg_len,
+                                                           0));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                             ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, msg_len));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
+                             ssl, buf_len, msg_len));
+
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_finalize_server_hello(ssl));
+
+#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+    /* The server sends a dummy change_cipher_spec record immediately
+     * after its first handshake message. This may either be after
+     * a ServerHello or a HelloRetryRequest.
+     */
+    mbedtls_ssl_handshake_set_state(
+        ssl, MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO);
+#else
+    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS);
+#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
+
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server hello"));
+    return ret;
+}
+
+
+/*
+ * Handler for MBEDTLS_SSL_HELLO_RETRY_REQUEST
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_prepare_hello_retry_request(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    if (ssl->handshake->hello_retry_request_count > 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Too many HRRs"));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
+                                     MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+    /*
+     * Create stateless transcript hash for HRR
+     */
+    MBEDTLS_SSL_DEBUG_MSG(4, ("Reset transcript for HRR"));
+    ret = mbedtls_ssl_reset_transcript_for_hrr(ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_reset_transcript_for_hrr", ret);
+        return ret;
+    }
+    mbedtls_ssl_session_reset_msg_layer(ssl, 0);
+
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_hello_retry_request(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *buf;
+    size_t buf_len, msg_len;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write hello retry request"));
+
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_hello_retry_request(ssl));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(
+                             ssl, MBEDTLS_SSL_HS_SERVER_HELLO,
+                             &buf, &buf_len));
+
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_server_hello_body(ssl, buf,
+                                                           buf + buf_len,
+                                                           &msg_len,
+                                                           1));
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                             ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, msg_len));
+
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl, buf_len,
+                                                          msg_len));
+
+    ssl->handshake->hello_retry_request_count++;
+
+#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+    /* The server sends a dummy change_cipher_spec record immediately
+     * after its first handshake message. This may either be after
+     * a ServerHello or a HelloRetryRequest.
+     */
+    mbedtls_ssl_handshake_set_state(
+        ssl, MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST);
+#else
+    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);
+#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
+
+cleanup:
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write hello retry request"));
+    return ret;
+}
+
+/*
+ * Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS
+ */
+
+/*
+ * struct {
+ *    Extension extensions<0..2 ^ 16 - 1>;
+ * } EncryptedExtensions;
+ *
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_encrypted_extensions_body(mbedtls_ssl_context *ssl,
+                                                     unsigned char *buf,
+                                                     unsigned char *end,
+                                                     size_t *out_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *p = buf;
+    size_t extensions_len = 0;
+    unsigned char *p_extensions_len;
+    size_t output_len;
+
+    *out_len = 0;
+
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);
+    p_extensions_len = p;
+    p += 2;
+
+    ((void) ssl);
+    ((void) ret);
+    ((void) output_len);
+
+#if defined(MBEDTLS_SSL_ALPN)
+    ret = mbedtls_ssl_write_alpn_ext(ssl, p, end, &output_len);
+    if (ret != 0) {
+        return ret;
+    }
+    p += output_len;
+#endif /* MBEDTLS_SSL_ALPN */
+
+    extensions_len = (p - p_extensions_len) - 2;
+    MBEDTLS_PUT_UINT16_BE(extensions_len, p_extensions_len, 0);
+
+    *out_len = p - buf;
+
+    MBEDTLS_SSL_DEBUG_BUF(4, "encrypted extensions", buf, *out_len);
+
+    MBEDTLS_SSL_PRINT_EXTS(
+        3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, ssl->handshake->sent_extensions);
+
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_encrypted_extensions(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *buf;
+    size_t buf_len, msg_len;
+
+    mbedtls_ssl_set_outbound_transform(ssl,
+                                       ssl->handshake->transform_handshake);
+    MBEDTLS_SSL_DEBUG_MSG(
+        3, ("switching to handshake transform for outbound data"));
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write encrypted extensions"));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl,
+                                                         MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, &buf,
+                                                         &buf_len));
+
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_encrypted_extensions_body(
+                             ssl, buf, buf + buf_len, &msg_len));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                             ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, buf, msg_len));
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
+                             ssl, buf_len, msg_len));
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+    if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) {
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED);
+    } else {
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST);
+    }
+#else
+    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED);
+#endif
+
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write encrypted extensions"));
+    return ret;
+}
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+#define SSL_CERTIFICATE_REQUEST_SEND_REQUEST 0
+#define SSL_CERTIFICATE_REQUEST_SKIP         1
+/* Coordination:
+ * Check whether a CertificateRequest message should be written.
+ * Returns a negative code on failure, or
+ * - SSL_CERTIFICATE_REQUEST_SEND_REQUEST
+ * - SSL_CERTIFICATE_REQUEST_SKIP
+ * indicating if the writing of the CertificateRequest
+ * should be skipped or not.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_certificate_request_coordinate(mbedtls_ssl_context *ssl)
+{
+    int authmode;
+
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    if (ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET) {
+        authmode = ssl->handshake->sni_authmode;
+    } else
+#endif
+    authmode = ssl->conf->authmode;
+
+    if (authmode == MBEDTLS_SSL_VERIFY_NONE) {
+        ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY;
+        return SSL_CERTIFICATE_REQUEST_SKIP;
+    }
+
+    ssl->handshake->certificate_request_sent = 1;
+
+    return SSL_CERTIFICATE_REQUEST_SEND_REQUEST;
+}
+
+/*
+ * struct {
+ *   opaque certificate_request_context<0..2^8-1>;
+ *   Extension extensions<2..2^16-1>;
+ * } CertificateRequest;
+ *
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_certificate_request_body(mbedtls_ssl_context *ssl,
+                                                    unsigned char *buf,
+                                                    const unsigned char *end,
+                                                    size_t *out_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *p = buf;
+    size_t output_len = 0;
+    unsigned char *p_extensions_len;
+
+    *out_len = 0;
+
+    /* Check if we have enough space:
+     * - certificate_request_context (1 byte)
+     * - extensions length           (2 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 3);
+
+    /*
+     * Write certificate_request_context
+     */
+    /*
+     * We use a zero length context for the normal handshake
+     * messages. For post-authentication handshake messages
+     * this request context would be set to a non-zero value.
+     */
+    *p++ = 0x0;
+
+    /*
+     * Write extensions
+     */
+    /* The extensions must contain the signature_algorithms. */
+    p_extensions_len = p;
+    p += 2;
+    ret = mbedtls_ssl_write_sig_alg_ext(ssl, p, end, &output_len);
+    if (ret != 0) {
+        return ret;
+    }
+
+    p += output_len;
+    MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0);
+
+    *out_len = p - buf;
+
+    MBEDTLS_SSL_PRINT_EXTS(
+        3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, ssl->handshake->sent_extensions);
+
+    return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_certificate_request(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate request"));
+
+    MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_certificate_request_coordinate(ssl));
+
+    if (ret == SSL_CERTIFICATE_REQUEST_SEND_REQUEST) {
+        unsigned char *buf;
+        size_t buf_len, msg_len;
+
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl,
+                                                             MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,
+                                                             &buf, &buf_len));
+
+        MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_request_body(
+                                 ssl, buf, buf + buf_len, &msg_len));
+
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                                 ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, buf, msg_len));
+
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
+                                 ssl, buf_len, msg_len));
+    } else if (ret == SSL_CERTIFICATE_REQUEST_SKIP) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate request"));
+        ret = 0;
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        goto cleanup;
+    }
+
+    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CERTIFICATE);
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate request"));
+    return ret;
+}
+
+/*
+ * Handler for MBEDTLS_SSL_SERVER_CERTIFICATE
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_server_certificate(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    if ((ssl_tls13_pick_key_cert(ssl) != 0) ||
+        mbedtls_ssl_own_cert(ssl) == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("No certificate available."));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
+                                     MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+    ret = mbedtls_ssl_tls13_write_certificate(ssl);
+    if (ret != 0) {
+        return ret;
+    }
+    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_VERIFY);
+    return 0;
+}
+
+/*
+ * Handler for MBEDTLS_SSL_CERTIFICATE_VERIFY
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl)
+{
+    int ret = mbedtls_ssl_tls13_write_certificate_verify(ssl);
+    if (ret != 0) {
+        return ret;
+    }
+    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED);
+    return 0;
+}
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+
+/*
+ * Handler for MBEDTLS_SSL_SERVER_FINISHED
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_server_finished(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    ret = mbedtls_ssl_tls13_write_finished_message(ssl);
+    if (ret != 0) {
+        return ret;
+    }
+
+    ret = mbedtls_ssl_tls13_compute_application_transform(ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_PEND_FATAL_ALERT(
+            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
+            MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
+        return ret;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to handshake keys for inbound traffic"));
+    mbedtls_ssl_set_inbound_transform(ssl, ssl->handshake->transform_handshake);
+
+    if (ssl->handshake->certificate_request_sent) {
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate"));
+        MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate verify"));
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED);
+    }
+
+    return 0;
+}
+
+/*
+ * Handler for MBEDTLS_SSL_CLIENT_FINISHED
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_process_client_finished(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    ret = mbedtls_ssl_tls13_process_finished_message(ssl);
+    if (ret != 0) {
+        return ret;
+    }
+
+    ret = mbedtls_ssl_tls13_compute_resumption_master_secret(ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1,
+                              "mbedtls_ssl_tls13_compute_resumption_master_secret", ret);
+    }
+
+    mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP);
+    return 0;
+}
+
+/*
+ * Handler for MBEDTLS_SSL_HANDSHAKE_WRAPUP
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl)
+{
+    MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done"));
+
+    mbedtls_ssl_tls13_handshake_wrapup(ssl);
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \
+    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+/* TODO: Remove the check of SOME_PSK_ENABLED since SESSION_TICKETS requires
+ *       SOME_PSK_ENABLED to be enabled. Here is just to make CI happy. It is
+ *       expected to be resolved with issue#6395.
+ */
+    /* Sent NewSessionTicket message only when client supports PSK */
+    if (mbedtls_ssl_tls13_some_psk_enabled(ssl)) {
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET);
+    } else
+#endif
+    {
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER);
+    }
+    return 0;
+}
+
+/*
+ * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET
+ */
+#define SSL_NEW_SESSION_TICKET_SKIP  0
+#define SSL_NEW_SESSION_TICKET_WRITE 1
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_new_session_ticket_coordinate(mbedtls_ssl_context *ssl)
+{
+    /* Check whether the use of session tickets is enabled */
+    if (ssl->conf->f_ticket_write == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("NewSessionTicket: disabled,"
+                                  " callback is not set"));
+        return SSL_NEW_SESSION_TICKET_SKIP;
+    }
+    if (ssl->conf->new_session_tickets_count == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("NewSessionTicket: disabled,"
+                                  " configured count is zero"));
+        return SSL_NEW_SESSION_TICKET_SKIP;
+    }
+
+    if (ssl->handshake->new_session_tickets_count == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("NewSessionTicket: all tickets have "
+                                  "been sent."));
+        return SSL_NEW_SESSION_TICKET_SKIP;
+    }
+
+    return SSL_NEW_SESSION_TICKET_WRITE;
+}
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_prepare_new_session_ticket(mbedtls_ssl_context *ssl,
+                                                unsigned char *ticket_nonce,
+                                                size_t ticket_nonce_size)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ssl_session *session = ssl->session;
+    mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+    psa_algorithm_t psa_hash_alg;
+    int hash_length;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> prepare NewSessionTicket msg"));
+
+#if defined(MBEDTLS_HAVE_TIME)
+    session->start = mbedtls_time(NULL);
+#endif
+
+    /* Set ticket_flags depends on the advertised psk key exchange mode */
+    mbedtls_ssl_session_clear_ticket_flags(
+        session, MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    mbedtls_ssl_session_set_ticket_flags(
+        session, ssl->handshake->tls13_kex_modes);
+#endif
+    MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags);
+
+    /* Generate ticket_age_add */
+    if ((ret = ssl->conf->f_rng(ssl->conf->p_rng,
+                                (unsigned char *) &session->ticket_age_add,
+                                sizeof(session->ticket_age_add)) != 0)) {
+        MBEDTLS_SSL_DEBUG_RET(1, "generate_ticket_age_add", ret);
+        return ret;
+    }
+    MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_age_add: %u",
+                              (unsigned int) session->ticket_age_add));
+
+    /* Generate ticket_nonce */
+    ret = ssl->conf->f_rng(ssl->conf->p_rng, ticket_nonce, ticket_nonce_size);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "generate_ticket_nonce", ret);
+        return ret;
+    }
+    MBEDTLS_SSL_DEBUG_BUF(3, "ticket_nonce:",
+                          ticket_nonce, ticket_nonce_size);
+
+    ciphersuite_info =
+        (mbedtls_ssl_ciphersuite_t *) ssl->handshake->ciphersuite_info;
+    psa_hash_alg = mbedtls_psa_translate_md(ciphersuite_info->mac);
+    hash_length = PSA_HASH_LENGTH(psa_hash_alg);
+    if (hash_length == -1 ||
+        (size_t) hash_length > sizeof(session->resumption_key)) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    /* In this code the psk key length equals the length of the hash */
+    session->resumption_key_len = hash_length;
+    session->ciphersuite = ciphersuite_info->id;
+
+    /* Compute resumption key
+     *
+     *  HKDF-Expand-Label( resumption_master_secret,
+     *                    "resumption", ticket_nonce, Hash.length )
+     */
+    ret = mbedtls_ssl_tls13_hkdf_expand_label(
+        psa_hash_alg,
+        session->app_secrets.resumption_master_secret,
+        hash_length,
+        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(resumption),
+        ticket_nonce,
+        ticket_nonce_size,
+        session->resumption_key,
+        hash_length);
+
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(2,
+                              "Creating the ticket-resumed PSK failed",
+                              ret);
+        return ret;
+    }
+    MBEDTLS_SSL_DEBUG_BUF(3, "Ticket-resumed PSK",
+                          session->resumption_key,
+                          session->resumption_key_len);
+
+    MBEDTLS_SSL_DEBUG_BUF(3, "resumption_master_secret",
+                          session->app_secrets.resumption_master_secret,
+                          hash_length);
+
+    return 0;
+}
+
+/* This function creates a NewSessionTicket message in the following format:
+ *
+ * struct {
+ *    uint32 ticket_lifetime;
+ *    uint32 ticket_age_add;
+ *    opaque ticket_nonce<0..255>;
+ *    opaque ticket<1..2^16-1>;
+ *    Extension extensions<0..2^16-2>;
+ * } NewSessionTicket;
+ *
+ * The ticket inside the NewSessionTicket message is an encrypted container
+ * carrying the necessary information so that the server is later able to
+ * re-start the communication.
+ *
+ * The following fields are placed inside the ticket by the
+ * f_ticket_write() function:
+ *
+ *  - creation time (start)
+ *  - flags (flags)
+ *  - age add (ticket_age_add)
+ *  - key (key)
+ *  - key length (key_len)
+ *  - ciphersuite (ciphersuite)
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_write_new_session_ticket_body(mbedtls_ssl_context *ssl,
+                                                   unsigned char *buf,
+                                                   unsigned char *end,
+                                                   size_t *out_len,
+                                                   unsigned char *ticket_nonce,
+                                                   size_t ticket_nonce_size)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *p = buf;
+    mbedtls_ssl_session *session = ssl->session;
+    size_t ticket_len;
+    uint32_t ticket_lifetime;
+
+    *out_len = 0;
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write NewSessionTicket msg"));
+
+    /*
+     *    ticket_lifetime   4 bytes
+     *    ticket_age_add    4 bytes
+     *    ticket_nonce      1 + ticket_nonce_size bytes
+     *    ticket            >=2 bytes
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4 + 4 + 1 + ticket_nonce_size + 2);
+
+    /* Generate ticket and ticket_lifetime */
+    ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket,
+                                    session,
+                                    p + 9 + ticket_nonce_size + 2,
+                                    end,
+                                    &ticket_len,
+                                    &ticket_lifetime);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "write_ticket", ret);
+        return ret;
+    }
+    /* RFC 8446 4.6.1
+     *  ticket_lifetime:  Indicates the lifetime in seconds as a 32-bit
+     *      unsigned integer in network byte order from the time of ticket
+     *      issuance.  Servers MUST NOT use any value greater than
+     *      604800 seconds (7 days).  The value of zero indicates that the
+     *      ticket should be discarded immediately.  Clients MUST NOT cache
+     *      tickets for longer than 7 days, regardless of the ticket_lifetime,
+     *      and MAY delete tickets earlier based on local policy.  A server
+     *      MAY treat a ticket as valid for a shorter period of time than what
+     *      is stated in the ticket_lifetime.
+     */
+    if (ticket_lifetime > 604800) {
+        ticket_lifetime = 604800;
+    }
+    MBEDTLS_PUT_UINT32_BE(ticket_lifetime, p, 0);
+    MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_lifetime: %u",
+                              (unsigned int) ticket_lifetime));
+
+    /* Write ticket_age_add */
+    MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 4);
+    MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_age_add: %u",
+                              (unsigned int) session->ticket_age_add));
+
+    /* Write ticket_nonce */
+    p[8] = (unsigned char) ticket_nonce_size;
+    if (ticket_nonce_size > 0) {
+        memcpy(p + 9, ticket_nonce, ticket_nonce_size);
+    }
+    p += 9 + ticket_nonce_size;
+
+    /* Write ticket */
+    MBEDTLS_PUT_UINT16_BE(ticket_len, p, 0);
+    p += 2;
+    MBEDTLS_SSL_DEBUG_BUF(4, "ticket", p, ticket_len);
+    p += ticket_len;
+
+    /* Ticket Extensions
+     *
+     * Note: We currently don't have any extensions.
+     * Set length to zero.
+     */
+    ssl->handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE;
+
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);
+    MBEDTLS_PUT_UINT16_BE(0, p, 0);
+    p += 2;
+
+    *out_len = p - buf;
+    MBEDTLS_SSL_DEBUG_BUF(4, "ticket", buf, *out_len);
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write new session ticket"));
+
+    MBEDTLS_SSL_PRINT_EXTS(
+        3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, ssl->handshake->sent_extensions);
+
+    return 0;
+}
+
+/*
+ * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET
+ */
+static int ssl_tls13_write_new_session_ticket(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_write_new_session_ticket_coordinate(ssl));
+
+    if (ret == SSL_NEW_SESSION_TICKET_WRITE) {
+        unsigned char ticket_nonce[MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH];
+        unsigned char *buf;
+        size_t buf_len, msg_len;
+
+        MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_new_session_ticket(
+                                 ssl, ticket_nonce, sizeof(ticket_nonce)));
+
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl,
+                                                             MBEDTLS_SSL_HS_NEW_SESSION_TICKET,
+                                                             &buf, &buf_len));
+
+        MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_new_session_ticket_body(
+                                 ssl, buf, buf + buf_len, &msg_len,
+                                 ticket_nonce, sizeof(ticket_nonce)));
+
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
+                                 ssl, buf_len, msg_len));
+
+        /* Limit session tickets count to one when resumption connection.
+         *
+         * See document of mbedtls_ssl_conf_new_session_tickets.
+         */
+        if (ssl->handshake->resume == 1) {
+            ssl->handshake->new_session_tickets_count = 0;
+        } else {
+            ssl->handshake->new_session_tickets_count--;
+        }
+
+        mbedtls_ssl_handshake_set_state(
+            ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH);
+    } else {
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER);
+    }
+
+cleanup:
+
+    return ret;
+}
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+/*
+ * TLS 1.3 State Machine -- server side
+ */
+int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if (ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("tls13 server state: %s(%d)",
+                              mbedtls_ssl_states_str(ssl->state),
+                              ssl->state));
+
+    switch (ssl->state) {
+        /* start state */
+        case MBEDTLS_SSL_HELLO_REQUEST:
+            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);
+            ret = 0;
+            break;
+
+        case MBEDTLS_SSL_CLIENT_HELLO:
+            ret = ssl_tls13_process_client_hello(ssl);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_process_client_hello", ret);
+            }
+            break;
+
+        case MBEDTLS_SSL_HELLO_RETRY_REQUEST:
+            ret = ssl_tls13_write_hello_retry_request(ssl);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_write_hello_retry_request", ret);
+                return ret;
+            }
+            break;
+
+        case MBEDTLS_SSL_SERVER_HELLO:
+            ret = ssl_tls13_write_server_hello(ssl);
+            break;
+
+        case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS:
+            ret = ssl_tls13_write_encrypted_extensions(ssl);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_write_encrypted_extensions", ret);
+                return ret;
+            }
+            break;
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+        case MBEDTLS_SSL_CERTIFICATE_REQUEST:
+            ret = ssl_tls13_write_certificate_request(ssl);
+            break;
+
+        case MBEDTLS_SSL_SERVER_CERTIFICATE:
+            ret = ssl_tls13_write_server_certificate(ssl);
+            break;
+
+        case MBEDTLS_SSL_CERTIFICATE_VERIFY:
+            ret = ssl_tls13_write_certificate_verify(ssl);
+            break;
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+
+            /*
+             * Injection of dummy-CCS's for middlebox compatibility
+             */
+#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+        case MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST:
+            ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
+            if (ret == 0) {
+                mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);
+            }
+            break;
+
+        case MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO:
+            ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
+            if (ret == 0) {
+                mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS);
+            }
+            break;
+#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
+
+        case MBEDTLS_SSL_SERVER_FINISHED:
+            ret = ssl_tls13_write_server_finished(ssl);
+            break;
+
+        case MBEDTLS_SSL_CLIENT_FINISHED:
+            ret = ssl_tls13_process_client_finished(ssl);
+            break;
+
+        case MBEDTLS_SSL_HANDSHAKE_WRAPUP:
+            ret = ssl_tls13_handshake_wrapup(ssl);
+            break;
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+        case MBEDTLS_SSL_CLIENT_CERTIFICATE:
+            ret = mbedtls_ssl_tls13_process_certificate(ssl);
+            if (ret == 0) {
+                if (ssl->session_negotiate->peer_cert != NULL) {
+                    mbedtls_ssl_handshake_set_state(
+                        ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY);
+                } else {
+                    MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate verify"));
+                    mbedtls_ssl_handshake_set_state(
+                        ssl, MBEDTLS_SSL_CLIENT_FINISHED);
+                }
+            }
+            break;
+
+        case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY:
+            ret = mbedtls_ssl_tls13_process_certificate_verify(ssl);
+            if (ret == 0) {
+                mbedtls_ssl_handshake_set_state(
+                    ssl, MBEDTLS_SSL_CLIENT_FINISHED);
+            }
+            break;
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+        case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET:
+            ret = ssl_tls13_write_new_session_ticket(ssl);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1,
+                                      "ssl_tls13_write_new_session_ticket ",
+                                      ret);
+            }
+            break;
+        case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH:
+            /* This state is necessary to do the flush of the New Session
+             * Ticket message written in MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET
+             * as part of ssl_prepare_handshake_step.
+             */
+            ret = 0;
+
+            if (ssl->handshake->new_session_tickets_count == 0) {
+                mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER);
+            } else {
+                mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET);
+            }
+            break;
+
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+        default:
+            MBEDTLS_SSL_DEBUG_MSG(1, ("invalid state %d", ssl->state));
+            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    }
+
+    return ret;
+}
+
+#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_TLS1_3 */
diff --git a/lib/libmbedtls/mbedtls/library/threading.c b/lib/libmbedtls/mbedtls/library/threading.c
index 5e0aaa4..130c696 100644
--- a/lib/libmbedtls/mbedtls/library/threading.c
+++ b/lib/libmbedtls/mbedtls/library/threading.c
@@ -19,7 +19,7 @@
 
 /*
  * Ensure gmtime_r is available even with -std=c99; must be defined before
- * config.h, which pulls in glibc's features.h. Harmless on other platforms.
+ * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms.
  */
 #if !defined(_POSIX_C_SOURCE)
 #define _POSIX_C_SOURCE 200112L
@@ -40,9 +40,9 @@
 #endif /* !_WIN32 && (unix || __unix || __unix__ ||
         * (__APPLE__ && __MACH__)) */
 
-#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) ||     \
-       ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) &&                     \
-         _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) )
+#if !((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) ||     \
+    (defined(_POSIX_THREAD_SAFE_FUNCTIONS) &&                     \
+    _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L))
 /*
  * This is a convenience shorthand macro to avoid checking the long
  * preprocessor conditions above. Ideally, we could expose this macro in
@@ -51,21 +51,22 @@
  * we keep it private by only defining it in this file
  */
 
-#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) )
+#if !(defined(_WIN32) && !defined(EFIX64) && !defined(EFI32))
 #define THREADING_USE_GMTIME
 #endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */
 
-#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) ||     \
-             ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) &&                     \
+#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \
+             ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \
                 _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */
 
 #endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */
 
 #if defined(MBEDTLS_THREADING_PTHREAD)
-static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex )
+static void threading_mutex_init_pthread(mbedtls_threading_mutex_t *mutex)
 {
-    if( mutex == NULL )
+    if (mutex == NULL) {
         return;
+    }
 
     /* A nonzero value of is_valid indicates a successfully initialized
      * mutex. This is a workaround for not being able to return an error
@@ -73,44 +74,49 @@
      * if is_valid is nonzero. The Mbed TLS unit test code uses this field
      * to distinguish more states of the mutex; see
      * tests/src/threading_helpers for details. */
-    mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0;
+    mutex->is_valid = pthread_mutex_init(&mutex->mutex, NULL) == 0;
 }
 
-static void threading_mutex_free_pthread( mbedtls_threading_mutex_t *mutex )
+static void threading_mutex_free_pthread(mbedtls_threading_mutex_t *mutex)
 {
-    if( mutex == NULL || !mutex->is_valid )
+    if (mutex == NULL || !mutex->is_valid) {
         return;
+    }
 
-    (void) pthread_mutex_destroy( &mutex->mutex );
+    (void) pthread_mutex_destroy(&mutex->mutex);
     mutex->is_valid = 0;
 }
 
-static int threading_mutex_lock_pthread( mbedtls_threading_mutex_t *mutex )
+static int threading_mutex_lock_pthread(mbedtls_threading_mutex_t *mutex)
 {
-    if( mutex == NULL || ! mutex->is_valid )
-        return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA );
+    if (mutex == NULL || !mutex->is_valid) {
+        return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA;
+    }
 
-    if( pthread_mutex_lock( &mutex->mutex ) != 0 )
-        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+    if (pthread_mutex_lock(&mutex->mutex) != 0) {
+        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
+    }
 
-    return( 0 );
+    return 0;
 }
 
-static int threading_mutex_unlock_pthread( mbedtls_threading_mutex_t *mutex )
+static int threading_mutex_unlock_pthread(mbedtls_threading_mutex_t *mutex)
 {
-    if( mutex == NULL || ! mutex->is_valid )
-        return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA );
+    if (mutex == NULL || !mutex->is_valid) {
+        return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA;
+    }
 
-    if( pthread_mutex_unlock( &mutex->mutex ) != 0 )
-        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+    if (pthread_mutex_unlock(&mutex->mutex) != 0) {
+        return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
+    }
 
-    return( 0 );
+    return 0;
 }
 
-void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_init_pthread;
-void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_free_pthread;
-int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_lock_pthread;
-int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_unlock_pthread;
+void (*mbedtls_mutex_init)(mbedtls_threading_mutex_t *) = threading_mutex_init_pthread;
+void (*mbedtls_mutex_free)(mbedtls_threading_mutex_t *) = threading_mutex_free_pthread;
+int (*mbedtls_mutex_lock)(mbedtls_threading_mutex_t *) = threading_mutex_lock_pthread;
+int (*mbedtls_mutex_unlock)(mbedtls_threading_mutex_t *) = threading_mutex_unlock_pthread;
 
 /*
  * With pthreads we can statically initialize mutexes
@@ -120,29 +126,29 @@
 #endif /* MBEDTLS_THREADING_PTHREAD */
 
 #if defined(MBEDTLS_THREADING_ALT)
-static int threading_mutex_fail( mbedtls_threading_mutex_t *mutex )
+static int threading_mutex_fail(mbedtls_threading_mutex_t *mutex)
 {
-    ((void) mutex );
-    return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA );
+    ((void) mutex);
+    return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA;
 }
-static void threading_mutex_dummy( mbedtls_threading_mutex_t *mutex )
+static void threading_mutex_dummy(mbedtls_threading_mutex_t *mutex)
 {
-    ((void) mutex );
+    ((void) mutex);
     return;
 }
 
-void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy;
-void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy;
-int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail;
-int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail;
+void (*mbedtls_mutex_init)(mbedtls_threading_mutex_t *) = threading_mutex_dummy;
+void (*mbedtls_mutex_free)(mbedtls_threading_mutex_t *) = threading_mutex_dummy;
+int (*mbedtls_mutex_lock)(mbedtls_threading_mutex_t *) = threading_mutex_fail;
+int (*mbedtls_mutex_unlock)(mbedtls_threading_mutex_t *) = threading_mutex_fail;
 
 /*
  * Set functions pointers and initialize global mutexes
  */
-void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ),
-                       void (*mutex_free)( mbedtls_threading_mutex_t * ),
-                       int (*mutex_lock)( mbedtls_threading_mutex_t * ),
-                       int (*mutex_unlock)( mbedtls_threading_mutex_t * ) )
+void mbedtls_threading_set_alt(void (*mutex_init)(mbedtls_threading_mutex_t *),
+                               void (*mutex_free)(mbedtls_threading_mutex_t *),
+                               int (*mutex_lock)(mbedtls_threading_mutex_t *),
+                               int (*mutex_unlock)(mbedtls_threading_mutex_t *))
 {
     mbedtls_mutex_init = mutex_init;
     mbedtls_mutex_free = mutex_free;
@@ -150,23 +156,23 @@
     mbedtls_mutex_unlock = mutex_unlock;
 
 #if defined(MBEDTLS_FS_IO)
-    mbedtls_mutex_init( &mbedtls_threading_readdir_mutex );
+    mbedtls_mutex_init(&mbedtls_threading_readdir_mutex);
 #endif
 #if defined(THREADING_USE_GMTIME)
-    mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex );
+    mbedtls_mutex_init(&mbedtls_threading_gmtime_mutex);
 #endif
 }
 
 /*
  * Free global mutexes
  */
-void mbedtls_threading_free_alt( void )
+void mbedtls_threading_free_alt(void)
 {
 #if defined(MBEDTLS_FS_IO)
-    mbedtls_mutex_free( &mbedtls_threading_readdir_mutex );
+    mbedtls_mutex_free(&mbedtls_threading_readdir_mutex);
 #endif
 #if defined(THREADING_USE_GMTIME)
-    mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex );
+    mbedtls_mutex_free(&mbedtls_threading_gmtime_mutex);
 #endif
 }
 #endif /* MBEDTLS_THREADING_ALT */
diff --git a/lib/libmbedtls/mbedtls/library/timing.c b/lib/libmbedtls/mbedtls/library/timing.c
index 57bc9bc..6852033 100644
--- a/lib/libmbedtls/mbedtls/library/timing.c
+++ b/lib/libmbedtls/mbedtls/library/timing.c
@@ -19,13 +19,6 @@
 
 #include "common.h"
 
-#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf     printf
-#endif
-
 #if defined(MBEDTLS_TIMING_C)
 
 #include "mbedtls/timing.h"
@@ -35,11 +28,7 @@
 #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
     !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
     !defined(__HAIKU__) && !defined(__midipix__)
-#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h"
-#endif
-
-#ifndef asm
-#define asm __asm
+#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in mbedtls_config.h"
 #endif
 
 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
@@ -47,8 +36,7 @@
 #include <windows.h>
 #include <process.h>
 
-struct _hr_time
-{
+struct _hr_time {
     LARGE_INTEGER start;
 };
 
@@ -61,268 +49,66 @@
  * platform matches the ifdefs above, it will be used. */
 #include <time.h>
 #include <sys/time.h>
-struct _hr_time
-{
+struct _hr_time {
     struct timeval start;
 };
 #endif /* _WIN32 && !EFIX64 && !EFI32 */
 
-#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) &&  \
-    ( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__)
-
-#define HAVE_HARDCLOCK
-
-unsigned long mbedtls_timing_hardclock( void )
-{
-    unsigned long tsc;
-    __asm   rdtsc
-    __asm   mov  [tsc], eax
-    return( tsc );
-}
-#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
-          ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */
-
-/* some versions of mingw-64 have 32-bit longs even on x84_64 */
-#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) &&  \
-    defined(__GNUC__) && ( defined(__i386__) || (                       \
-    ( defined(__amd64__) || defined( __x86_64__) ) && __SIZEOF_LONG__ == 4 ) )
-
-#define HAVE_HARDCLOCK
-
-unsigned long mbedtls_timing_hardclock( void )
-{
-    unsigned long lo, hi;
-    asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) );
-    return( lo );
-}
-#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
-          __GNUC__ && __i386__ */
-
-#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) &&  \
-    defined(__GNUC__) && ( defined(__amd64__) || defined(__x86_64__) )
-
-#define HAVE_HARDCLOCK
-
-unsigned long mbedtls_timing_hardclock( void )
-{
-    unsigned long lo, hi;
-    asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) );
-    return( lo | ( hi << 32 ) );
-}
-#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
-          __GNUC__ && ( __amd64__ || __x86_64__ ) */
-
-#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) &&  \
-    defined(__GNUC__) && ( defined(__powerpc__) || defined(__ppc__) )
-
-#define HAVE_HARDCLOCK
-
-unsigned long mbedtls_timing_hardclock( void )
-{
-    unsigned long tbl, tbu0, tbu1;
-
-    do
-    {
-        asm volatile( "mftbu %0" : "=r" (tbu0) );
-        asm volatile( "mftb  %0" : "=r" (tbl ) );
-        asm volatile( "mftbu %0" : "=r" (tbu1) );
-    }
-    while( tbu0 != tbu1 );
-
-    return( tbl );
-}
-#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
-          __GNUC__ && ( __powerpc__ || __ppc__ ) */
-
-#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) &&  \
-    defined(__GNUC__) && defined(__sparc64__)
-
-#if defined(__OpenBSD__)
-#warning OpenBSD does not allow access to tick register using software version instead
-#else
-#define HAVE_HARDCLOCK
-
-unsigned long mbedtls_timing_hardclock( void )
-{
-    unsigned long tick;
-    asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) );
-    return( tick );
-}
-#endif /* __OpenBSD__ */
-#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
-          __GNUC__ && __sparc64__ */
-
-#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) &&  \
-    defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__)
-
-#define HAVE_HARDCLOCK
-
-unsigned long mbedtls_timing_hardclock( void )
-{
-    unsigned long tick;
-    asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" );
-    asm volatile( "mov   %%g1, %0" : "=r" (tick) );
-    return( tick );
-}
-#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
-          __GNUC__ && __sparc__ && !__sparc64__ */
-
-#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) &&      \
-    defined(__GNUC__) && defined(__alpha__)
-
-#define HAVE_HARDCLOCK
-
-unsigned long mbedtls_timing_hardclock( void )
-{
-    unsigned long cc;
-    asm volatile( "rpcc %0" : "=r" (cc) );
-    return( cc & 0xFFFFFFFF );
-}
-#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
-          __GNUC__ && __alpha__ */
-
-#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) &&      \
-    defined(__GNUC__) && defined(__ia64__)
-
-#define HAVE_HARDCLOCK
-
-unsigned long mbedtls_timing_hardclock( void )
-{
-    unsigned long itc;
-    asm volatile( "mov %0 = ar.itc" : "=r" (itc) );
-    return( itc );
-}
-#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
-          __GNUC__ && __ia64__ */
-
-#if !defined(HAVE_HARDCLOCK) && defined(_MSC_VER) && \
-    !defined(EFIX64) && !defined(EFI32)
-
-#define HAVE_HARDCLOCK
-
-unsigned long mbedtls_timing_hardclock( void )
-{
-    LARGE_INTEGER offset;
-
-    QueryPerformanceCounter( &offset );
-
-    return( (unsigned long)( offset.QuadPart ) );
-}
-#endif /* !HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */
-
-#if !defined(HAVE_HARDCLOCK)
-
-#define HAVE_HARDCLOCK
-
-static int hardclock_init = 0;
-static struct timeval tv_init;
-
-unsigned long mbedtls_timing_hardclock( void )
-{
-    struct timeval tv_cur;
-
-    if( hardclock_init == 0 )
-    {
-        gettimeofday( &tv_init, NULL );
-        hardclock_init = 1;
-    }
-
-    gettimeofday( &tv_cur, NULL );
-    return( ( tv_cur.tv_sec  - tv_init.tv_sec  ) * 1000000
-          + ( tv_cur.tv_usec - tv_init.tv_usec ) );
-}
-#endif /* !HAVE_HARDCLOCK */
-
-volatile int mbedtls_timing_alarmed = 0;
-
+/**
+ * \brief          Return the elapsed time in milliseconds
+ *
+ * \warning        May change without notice
+ *
+ * \param val      points to a timer structure
+ * \param reset    If 0, query the elapsed time. Otherwise (re)start the timer.
+ *
+ * \return         Elapsed time since the previous reset in ms. When
+ *                 restarting, this is always 0.
+ *
+ * \note           To initialize a timer, call this function with reset=1.
+ *
+ *                 Determining the elapsed time and resetting the timer is not
+ *                 atomic on all platforms, so after the sequence
+ *                 `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 =
+ *                 get_timer(0) }` the value time1+time2 is only approximately
+ *                 the delay since the first reset.
+ */
 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
 
-unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset )
+unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset)
 {
     struct _hr_time *t = (struct _hr_time *) val;
 
-    if( reset )
-    {
-        QueryPerformanceCounter( &t->start );
-        return( 0 );
-    }
-    else
-    {
+    if (reset) {
+        QueryPerformanceCounter(&t->start);
+        return 0;
+    } else {
         unsigned long delta;
         LARGE_INTEGER now, hfreq;
-        QueryPerformanceCounter(  &now );
-        QueryPerformanceFrequency( &hfreq );
-        delta = (unsigned long)( ( now.QuadPart - t->start.QuadPart ) * 1000ul
-                                 / hfreq.QuadPart );
-        return( delta );
+        QueryPerformanceCounter(&now);
+        QueryPerformanceFrequency(&hfreq);
+        delta = (unsigned long) ((now.QuadPart - t->start.QuadPart) * 1000ul
+                                 / hfreq.QuadPart);
+        return delta;
     }
 }
 
-/* It's OK to use a global because alarm() is supposed to be global anyway */
-static DWORD alarmMs;
-
-static void TimerProc( void *TimerContext )
-{
-    (void) TimerContext;
-    Sleep( alarmMs );
-    mbedtls_timing_alarmed = 1;
-    /* _endthread will be called implicitly on return
-     * That ensures execution of thread funcition's epilogue */
-}
-
-void mbedtls_set_alarm( int seconds )
-{
-    if( seconds == 0 )
-    {
-        /* No need to create a thread for this simple case.
-         * Also, this shorcut is more reliable at least on MinGW32 */
-        mbedtls_timing_alarmed = 1;
-        return;
-    }
-
-    mbedtls_timing_alarmed = 0;
-    alarmMs = seconds * 1000;
-    (void) _beginthread( TimerProc, 0, NULL );
-}
-
 #else /* _WIN32 && !EFIX64 && !EFI32 */
 
-unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset )
+unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset)
 {
     struct _hr_time *t = (struct _hr_time *) val;
 
-    if( reset )
-    {
-        gettimeofday( &t->start, NULL );
-        return( 0 );
-    }
-    else
-    {
+    if (reset) {
+        gettimeofday(&t->start, NULL);
+        return 0;
+    } else {
         unsigned long delta;
         struct timeval now;
-        gettimeofday( &now, NULL );
-        delta = ( now.tv_sec  - t->start.tv_sec  ) * 1000ul
-              + ( now.tv_usec - t->start.tv_usec ) / 1000;
-        return( delta );
-    }
-}
-
-static void sighandler( int signum )
-{
-    mbedtls_timing_alarmed = 1;
-    signal( signum, sighandler );
-}
-
-void mbedtls_set_alarm( int seconds )
-{
-    mbedtls_timing_alarmed = 0;
-    signal( SIGALRM, sighandler );
-    alarm( seconds );
-    if( seconds == 0 )
-    {
-        /* alarm(0) cancelled any previous pending alarm, but the
-           handler won't fire, so raise the flag straight away. */
-        mbedtls_timing_alarmed = 1;
+        gettimeofday(&now, NULL);
+        delta = (now.tv_sec  - t->start.tv_sec) * 1000ul
+                + (now.tv_usec - t->start.tv_usec) / 1000;
+        return delta;
     }
 }
 
@@ -331,199 +117,50 @@
 /*
  * Set delays to watch
  */
-void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms )
+void mbedtls_timing_set_delay(void *data, uint32_t int_ms, uint32_t fin_ms)
 {
     mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data;
 
     ctx->int_ms = int_ms;
     ctx->fin_ms = fin_ms;
 
-    if( fin_ms != 0 )
-        (void) mbedtls_timing_get_timer( &ctx->timer, 1 );
+    if (fin_ms != 0) {
+        (void) mbedtls_timing_get_timer(&ctx->timer, 1);
+    }
 }
 
 /*
  * Get number of delays expired
  */
-int mbedtls_timing_get_delay( void *data )
+int mbedtls_timing_get_delay(void *data)
 {
     mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data;
     unsigned long elapsed_ms;
 
-    if( ctx->fin_ms == 0 )
-        return( -1 );
+    if (ctx->fin_ms == 0) {
+        return -1;
+    }
 
-    elapsed_ms = mbedtls_timing_get_timer( &ctx->timer, 0 );
+    elapsed_ms = mbedtls_timing_get_timer(&ctx->timer, 0);
 
-    if( elapsed_ms >= ctx->fin_ms )
-        return( 2 );
+    if (elapsed_ms >= ctx->fin_ms) {
+        return 2;
+    }
 
-    if( elapsed_ms >= ctx->int_ms )
-        return( 1 );
+    if (elapsed_ms >= ctx->int_ms) {
+        return 1;
+    }
 
-    return( 0 );
+    return 0;
 }
 
-
-#if defined(MBEDTLS_SELF_TEST)
-
 /*
- * Busy-waits for the given number of milliseconds.
- * Used for testing mbedtls_timing_hardclock.
+ * Get the final delay.
  */
-static void busy_msleep( unsigned long msec )
+uint32_t mbedtls_timing_get_final_delay(
+    const mbedtls_timing_delay_context *data)
 {
-    struct mbedtls_timing_hr_time hires;
-    unsigned long i = 0; /* for busy-waiting */
-    volatile unsigned long j; /* to prevent optimisation */
-
-    (void) mbedtls_timing_get_timer( &hires, 1 );
-
-    while( mbedtls_timing_get_timer( &hires, 0 ) < msec )
-        i++;
-
-    j = i;
-    (void) j;
+    return data->fin_ms;
 }
-
-#define FAIL    do                                                      \
-    {                                                                   \
-        if( verbose != 0 )                                              \
-        {                                                               \
-            mbedtls_printf( "failed at line %d\n", __LINE__ );          \
-            mbedtls_printf( " cycles=%lu ratio=%lu millisecs=%lu secs=%lu hardfail=%d a=%lu b=%lu\n", \
-                            cycles, ratio, millisecs, secs, hardfail,   \
-                            (unsigned long) a, (unsigned long) b );     \
-            mbedtls_printf( " elapsed(hires)=%lu elapsed(ctx)=%lu status(ctx)=%d\n", \
-                            mbedtls_timing_get_timer( &hires, 0 ),      \
-                            mbedtls_timing_get_timer( &ctx.timer, 0 ),  \
-                            mbedtls_timing_get_delay( &ctx ) );         \
-        }                                                               \
-        return( 1 );                                                    \
-    } while( 0 )
-
-/*
- * Checkup routine
- *
- * Warning: this is work in progress, some tests may not be reliable enough
- * yet! False positives may happen.
- */
-int mbedtls_timing_self_test( int verbose )
-{
-    unsigned long cycles = 0, ratio = 0;
-    unsigned long millisecs = 0, secs = 0;
-    int hardfail = 0;
-    struct mbedtls_timing_hr_time hires;
-    uint32_t a = 0, b = 0;
-    mbedtls_timing_delay_context ctx;
-
-    if( verbose != 0 )
-        mbedtls_printf( "  TIMING tests note: will take some time!\n" );
-
-    if( verbose != 0 )
-        mbedtls_printf( "  TIMING test #1 (set_alarm / get_timer): " );
-
-    {
-        secs = 1;
-
-        (void) mbedtls_timing_get_timer( &hires, 1 );
-
-        mbedtls_set_alarm( (int) secs );
-        while( !mbedtls_timing_alarmed )
-            ;
-
-        millisecs = mbedtls_timing_get_timer( &hires, 0 );
-
-        /* For some reason on Windows it looks like alarm has an extra delay
-         * (maybe related to creating a new thread). Allow some room here. */
-        if( millisecs < 800 * secs || millisecs > 1200 * secs + 300 )
-            FAIL;
-    }
-
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
-
-    if( verbose != 0 )
-        mbedtls_printf( "  TIMING test #2 (set/get_delay        ): " );
-
-    {
-        a = 800;
-        b = 400;
-        mbedtls_timing_set_delay( &ctx, a, a + b );          /* T = 0 */
-
-        busy_msleep( a - a / 4 );                      /* T = a - a/4 */
-        if( mbedtls_timing_get_delay( &ctx ) != 0 )
-            FAIL;
-
-        busy_msleep( a / 4 + b / 4 );                  /* T = a + b/4 */
-        if( mbedtls_timing_get_delay( &ctx ) != 1 )
-            FAIL;
-
-        busy_msleep( b );                          /* T = a + b + b/4 */
-        if( mbedtls_timing_get_delay( &ctx ) != 2 )
-            FAIL;
-    }
-
-    mbedtls_timing_set_delay( &ctx, 0, 0 );
-    busy_msleep( 200 );
-    if( mbedtls_timing_get_delay( &ctx ) != -1 )
-        FAIL;
-
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
-
-    if( verbose != 0 )
-        mbedtls_printf( "  TIMING test #3 (hardclock / get_timer): " );
-
-    /*
-     * Allow one failure for possible counter wrapping.
-     * On a 4Ghz 32-bit machine the cycle counter wraps about once per second;
-     * since the whole test is about 10ms, it shouldn't happen twice in a row.
-     */
-
-hard_test:
-    if( hardfail > 1 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed (ignored)\n" );
-
-        goto hard_test_done;
-    }
-
-    /* Get a reference ratio cycles/ms */
-    millisecs = 1;
-    cycles = mbedtls_timing_hardclock();
-    busy_msleep( millisecs );
-    cycles = mbedtls_timing_hardclock() - cycles;
-    ratio = cycles / millisecs;
-
-    /* Check that the ratio is mostly constant */
-    for( millisecs = 2; millisecs <= 4; millisecs++ )
-    {
-        cycles = mbedtls_timing_hardclock();
-        busy_msleep( millisecs );
-        cycles = mbedtls_timing_hardclock() - cycles;
-
-        /* Allow variation up to 20% */
-        if( cycles / millisecs < ratio - ratio / 5 ||
-            cycles / millisecs > ratio + ratio / 5 )
-        {
-            hardfail++;
-            goto hard_test;
-        }
-    }
-
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n" );
-
-hard_test_done:
-
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
-
-    return( 0 );
-}
-
-#endif /* MBEDTLS_SELF_TEST */
 #endif /* !MBEDTLS_TIMING_ALT */
 #endif /* MBEDTLS_TIMING_C */
diff --git a/lib/libmbedtls/mbedtls/library/version.c b/lib/libmbedtls/mbedtls/library/version.c
index 32a0d7d..4f78c9c 100644
--- a/lib/libmbedtls/mbedtls/library/version.c
+++ b/lib/libmbedtls/mbedtls/library/version.c
@@ -24,21 +24,21 @@
 #include "mbedtls/version.h"
 #include <string.h>
 
-unsigned int mbedtls_version_get_number( void )
+unsigned int mbedtls_version_get_number(void)
 {
-    return( MBEDTLS_VERSION_NUMBER );
+    return MBEDTLS_VERSION_NUMBER;
 }
 
-void mbedtls_version_get_string( char *string )
+void mbedtls_version_get_string(char *string)
 {
-    memcpy( string, MBEDTLS_VERSION_STRING,
-            sizeof( MBEDTLS_VERSION_STRING ) );
+    memcpy(string, MBEDTLS_VERSION_STRING,
+           sizeof(MBEDTLS_VERSION_STRING));
 }
 
-void mbedtls_version_get_string_full( char *string )
+void mbedtls_version_get_string_full(char *string)
 {
-    memcpy( string, MBEDTLS_VERSION_STRING_FULL,
-            sizeof( MBEDTLS_VERSION_STRING_FULL ) );
+    memcpy(string, MBEDTLS_VERSION_STRING_FULL,
+           sizeof(MBEDTLS_VERSION_STRING_FULL));
 }
 
 #endif /* MBEDTLS_VERSION_C */
diff --git a/lib/libmbedtls/mbedtls/library/version_features.c b/lib/libmbedtls/mbedtls/library/version_features.c
index 40c9520..0a6ff22 100644
--- a/lib/libmbedtls/mbedtls/library/version_features.c
+++ b/lib/libmbedtls/mbedtls/library/version_features.c
@@ -27,7 +27,7 @@
 
 static const char * const features[] = {
 #if defined(MBEDTLS_VERSION_FEATURES)
-#if defined(MBEDTLS_HAVE_ASM)
+    #if defined(MBEDTLS_HAVE_ASM)
     "MBEDTLS_HAVE_ASM",
 #endif /* MBEDTLS_HAVE_ASM */
 #if defined(MBEDTLS_NO_UDBL_DIVISION)
@@ -51,6 +51,9 @@
 #if defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS)
     "MBEDTLS_PLATFORM_NO_STD_FUNCTIONS",
 #endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */
+#if defined(MBEDTLS_PLATFORM_SETBUF_ALT)
+    "MBEDTLS_PLATFORM_SETBUF_ALT",
+#endif /* MBEDTLS_PLATFORM_SETBUF_ALT */
 #if defined(MBEDTLS_PLATFORM_EXIT_ALT)
     "MBEDTLS_PLATFORM_EXIT_ALT",
 #endif /* MBEDTLS_PLATFORM_EXIT_ALT */
@@ -81,27 +84,15 @@
 #if defined(MBEDTLS_DEPRECATED_REMOVED)
     "MBEDTLS_DEPRECATED_REMOVED",
 #endif /* MBEDTLS_DEPRECATED_REMOVED */
-#if defined(MBEDTLS_CHECK_PARAMS)
-    "MBEDTLS_CHECK_PARAMS",
-#endif /* MBEDTLS_CHECK_PARAMS */
-#if defined(MBEDTLS_CHECK_PARAMS_ASSERT)
-    "MBEDTLS_CHECK_PARAMS_ASSERT",
-#endif /* MBEDTLS_CHECK_PARAMS_ASSERT */
 #if defined(MBEDTLS_TIMING_ALT)
     "MBEDTLS_TIMING_ALT",
 #endif /* MBEDTLS_TIMING_ALT */
 #if defined(MBEDTLS_AES_ALT)
     "MBEDTLS_AES_ALT",
 #endif /* MBEDTLS_AES_ALT */
-#if defined(MBEDTLS_ARC4_ALT)
-    "MBEDTLS_ARC4_ALT",
-#endif /* MBEDTLS_ARC4_ALT */
 #if defined(MBEDTLS_ARIA_ALT)
     "MBEDTLS_ARIA_ALT",
 #endif /* MBEDTLS_ARIA_ALT */
-#if defined(MBEDTLS_BLOWFISH_ALT)
-    "MBEDTLS_BLOWFISH_ALT",
-#endif /* MBEDTLS_BLOWFISH_ALT */
 #if defined(MBEDTLS_CAMELLIA_ALT)
     "MBEDTLS_CAMELLIA_ALT",
 #endif /* MBEDTLS_CAMELLIA_ALT */
@@ -132,12 +123,6 @@
 #if defined(MBEDTLS_NIST_KW_ALT)
     "MBEDTLS_NIST_KW_ALT",
 #endif /* MBEDTLS_NIST_KW_ALT */
-#if defined(MBEDTLS_MD2_ALT)
-    "MBEDTLS_MD2_ALT",
-#endif /* MBEDTLS_MD2_ALT */
-#if defined(MBEDTLS_MD4_ALT)
-    "MBEDTLS_MD4_ALT",
-#endif /* MBEDTLS_MD4_ALT */
 #if defined(MBEDTLS_MD5_ALT)
     "MBEDTLS_MD5_ALT",
 #endif /* MBEDTLS_MD5_ALT */
@@ -159,18 +144,9 @@
 #if defined(MBEDTLS_SHA512_ALT)
     "MBEDTLS_SHA512_ALT",
 #endif /* MBEDTLS_SHA512_ALT */
-#if defined(MBEDTLS_XTEA_ALT)
-    "MBEDTLS_XTEA_ALT",
-#endif /* MBEDTLS_XTEA_ALT */
 #if defined(MBEDTLS_ECP_ALT)
     "MBEDTLS_ECP_ALT",
 #endif /* MBEDTLS_ECP_ALT */
-#if defined(MBEDTLS_MD2_PROCESS_ALT)
-    "MBEDTLS_MD2_PROCESS_ALT",
-#endif /* MBEDTLS_MD2_PROCESS_ALT */
-#if defined(MBEDTLS_MD4_PROCESS_ALT)
-    "MBEDTLS_MD4_PROCESS_ALT",
-#endif /* MBEDTLS_MD4_PROCESS_ALT */
 #if defined(MBEDTLS_MD5_PROCESS_ALT)
     "MBEDTLS_MD5_PROCESS_ALT",
 #endif /* MBEDTLS_MD5_PROCESS_ALT */
@@ -252,9 +228,6 @@
 #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
     "MBEDTLS_ECP_NORMALIZE_MXZ_ALT",
 #endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
-#if defined(MBEDTLS_TEST_NULL_ENTROPY)
-    "MBEDTLS_TEST_NULL_ENTROPY",
-#endif /* MBEDTLS_TEST_NULL_ENTROPY */
 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
     "MBEDTLS_ENTROPY_HARDWARE_ALT",
 #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */
@@ -303,15 +276,6 @@
 #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
     "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY",
 #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
-#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES)
-    "MBEDTLS_ENABLE_WEAK_CIPHERSUITES",
-#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */
-#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES)
-    "MBEDTLS_REMOVE_ARC4_CIPHERSUITES",
-#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */
-#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES)
-    "MBEDTLS_REMOVE_3DES_CIPHERSUITES",
-#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */
 #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
     "MBEDTLS_ECP_DP_SECP192R1_ENABLED",
 #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
@@ -354,15 +318,9 @@
 #if defined(MBEDTLS_ECP_NIST_OPTIM)
     "MBEDTLS_ECP_NIST_OPTIM",
 #endif /* MBEDTLS_ECP_NIST_OPTIM */
-#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
-    "MBEDTLS_ECP_NO_INTERNAL_RNG",
-#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
 #if defined(MBEDTLS_ECP_RESTARTABLE)
     "MBEDTLS_ECP_RESTARTABLE",
 #endif /* MBEDTLS_ECP_RESTARTABLE */
-#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
-    "MBEDTLS_ECDH_LEGACY_CONTEXT",
-#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
     "MBEDTLS_ECDSA_DETERMINISTIC",
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
@@ -471,18 +429,15 @@
 #if defined(MBEDTLS_SHA512_SMALLER)
     "MBEDTLS_SHA512_SMALLER",
 #endif /* MBEDTLS_SHA512_SMALLER */
-#if defined(MBEDTLS_SHA512_NO_SHA384)
-    "MBEDTLS_SHA512_NO_SHA384",
-#endif /* MBEDTLS_SHA512_NO_SHA384 */
 #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)
     "MBEDTLS_SSL_ALL_ALERT_MESSAGES",
 #endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */
-#if defined(MBEDTLS_SSL_RECORD_CHECKING)
-    "MBEDTLS_SSL_RECORD_CHECKING",
-#endif /* MBEDTLS_SSL_RECORD_CHECKING */
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
     "MBEDTLS_SSL_DTLS_CONNECTION_ID",
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT)
+    "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT",
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT */
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
     "MBEDTLS_SSL_ASYNC_PRIVATE",
 #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
@@ -498,45 +453,42 @@
 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
     "MBEDTLS_SSL_EXTENDED_MASTER_SECRET",
 #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
-#if defined(MBEDTLS_SSL_FALLBACK_SCSV)
-    "MBEDTLS_SSL_FALLBACK_SCSV",
-#endif /* MBEDTLS_SSL_FALLBACK_SCSV */
 #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
     "MBEDTLS_SSL_KEEP_PEER_CERTIFICATE",
 #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
-    "MBEDTLS_SSL_HW_RECORD_ACCEL",
-#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
-#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
-    "MBEDTLS_SSL_CBC_RECORD_SPLITTING",
-#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
     "MBEDTLS_SSL_RENEGOTIATION",
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
-#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
-    "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO",
-#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */
-#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE)
-    "MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE",
-#endif /* MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE */
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
     "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH",
 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-    "MBEDTLS_SSL_PROTO_SSL3",
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1)
-    "MBEDTLS_SSL_PROTO_TLS1",
-#endif /* MBEDTLS_SSL_PROTO_TLS1 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_1)
-    "MBEDTLS_SSL_PROTO_TLS1_1",
-#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+    "MBEDTLS_SSL_RECORD_SIZE_LIMIT",
+#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
     "MBEDTLS_SSL_PROTO_TLS1_2",
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
-    "MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL",
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    "MBEDTLS_SSL_PROTO_TLS1_3",
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+    "MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE",
+#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED)
+    "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED",
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED */
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+    "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED",
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
+    "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED",
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED */
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    "MBEDTLS_SSL_EARLY_DATA",
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+#if defined(MBEDTLS_SSL_MAX_EARLY_DATA_SIZE)
+    "MBEDTLS_SSL_MAX_EARLY_DATA_SIZE",
+#endif /* MBEDTLS_SSL_MAX_EARLY_DATA_SIZE */
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     "MBEDTLS_SSL_PROTO_DTLS",
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
@@ -555,24 +507,12 @@
 #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE)
     "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE",
 #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */
-#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
-    "MBEDTLS_SSL_DTLS_BADMAC_LIMIT",
-#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
     "MBEDTLS_SSL_SESSION_TICKETS",
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
-    "MBEDTLS_SSL_EXPORT_KEYS",
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
     "MBEDTLS_SSL_SERVER_NAME_INDICATION",
 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
-    "MBEDTLS_SSL_TRUNCATED_HMAC",
-#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
-#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT)
-    "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT",
-#endif /* MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT */
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
     "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH",
 #endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */
@@ -600,36 +540,24 @@
 #if defined(MBEDTLS_VERSION_FEATURES)
     "MBEDTLS_VERSION_FEATURES",
 #endif /* MBEDTLS_VERSION_FEATURES */
-#if defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3)
-    "MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3",
-#endif /* MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 */
-#if defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
-    "MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION",
-#endif /* MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */
 #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
     "MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK",
 #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
-#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
-    "MBEDTLS_X509_CHECK_KEY_USAGE",
-#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */
-#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
-    "MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE",
-#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */
+#if defined(MBEDTLS_X509_REMOVE_INFO)
+    "MBEDTLS_X509_REMOVE_INFO",
+#endif /* MBEDTLS_X509_REMOVE_INFO */
 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
     "MBEDTLS_X509_RSASSA_PSS_SUPPORT",
 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-    "MBEDTLS_ZLIB_SUPPORT",
-#endif /* MBEDTLS_ZLIB_SUPPORT */
 #if defined(MBEDTLS_AESNI_C)
     "MBEDTLS_AESNI_C",
 #endif /* MBEDTLS_AESNI_C */
+#if defined(MBEDTLS_AESCE_C)
+    "MBEDTLS_AESCE_C",
+#endif /* MBEDTLS_AESCE_C */
 #if defined(MBEDTLS_AES_C)
     "MBEDTLS_AES_C",
 #endif /* MBEDTLS_AES_C */
-#if defined(MBEDTLS_ARC4_C)
-    "MBEDTLS_ARC4_C",
-#endif /* MBEDTLS_ARC4_C */
 #if defined(MBEDTLS_ASN1_PARSE_C)
     "MBEDTLS_ASN1_PARSE_C",
 #endif /* MBEDTLS_ASN1_PARSE_C */
@@ -642,9 +570,6 @@
 #if defined(MBEDTLS_BIGNUM_C)
     "MBEDTLS_BIGNUM_C",
 #endif /* MBEDTLS_BIGNUM_C */
-#if defined(MBEDTLS_BLOWFISH_C)
-    "MBEDTLS_BLOWFISH_C",
-#endif /* MBEDTLS_BLOWFISH_C */
 #if defined(MBEDTLS_CAMELLIA_C)
     "MBEDTLS_CAMELLIA_C",
 #endif /* MBEDTLS_CAMELLIA_C */
@@ -654,9 +579,6 @@
 #if defined(MBEDTLS_CCM_C)
     "MBEDTLS_CCM_C",
 #endif /* MBEDTLS_CCM_C */
-#if defined(MBEDTLS_CERTS_C)
-    "MBEDTLS_CERTS_C",
-#endif /* MBEDTLS_CERTS_C */
 #if defined(MBEDTLS_CHACHA20_C)
     "MBEDTLS_CHACHA20_C",
 #endif /* MBEDTLS_CHACHA20_C */
@@ -702,27 +624,24 @@
 #if defined(MBEDTLS_GCM_C)
     "MBEDTLS_GCM_C",
 #endif /* MBEDTLS_GCM_C */
-#if defined(MBEDTLS_HAVEGE_C)
-    "MBEDTLS_HAVEGE_C",
-#endif /* MBEDTLS_HAVEGE_C */
 #if defined(MBEDTLS_HKDF_C)
     "MBEDTLS_HKDF_C",
 #endif /* MBEDTLS_HKDF_C */
 #if defined(MBEDTLS_HMAC_DRBG_C)
     "MBEDTLS_HMAC_DRBG_C",
 #endif /* MBEDTLS_HMAC_DRBG_C */
+#if defined(MBEDTLS_LMS_C)
+    "MBEDTLS_LMS_C",
+#endif /* MBEDTLS_LMS_C */
+#if defined(MBEDTLS_LMS_PRIVATE)
+    "MBEDTLS_LMS_PRIVATE",
+#endif /* MBEDTLS_LMS_PRIVATE */
 #if defined(MBEDTLS_NIST_KW_C)
     "MBEDTLS_NIST_KW_C",
 #endif /* MBEDTLS_NIST_KW_C */
 #if defined(MBEDTLS_MD_C)
     "MBEDTLS_MD_C",
 #endif /* MBEDTLS_MD_C */
-#if defined(MBEDTLS_MD2_C)
-    "MBEDTLS_MD2_C",
-#endif /* MBEDTLS_MD2_C */
-#if defined(MBEDTLS_MD4_C)
-    "MBEDTLS_MD4_C",
-#endif /* MBEDTLS_MD4_C */
 #if defined(MBEDTLS_MD5_C)
     "MBEDTLS_MD5_C",
 #endif /* MBEDTLS_MD5_C */
@@ -756,9 +675,9 @@
 #if defined(MBEDTLS_PKCS5_C)
     "MBEDTLS_PKCS5_C",
 #endif /* MBEDTLS_PKCS5_C */
-#if defined(MBEDTLS_PKCS11_C)
-    "MBEDTLS_PKCS11_C",
-#endif /* MBEDTLS_PKCS11_C */
+#if defined(MBEDTLS_PKCS7_C)
+    "MBEDTLS_PKCS7_C",
+#endif /* MBEDTLS_PKCS7_C */
 #if defined(MBEDTLS_PKCS12_C)
     "MBEDTLS_PKCS12_C",
 #endif /* MBEDTLS_PKCS12_C */
@@ -789,12 +708,30 @@
 #if defined(MBEDTLS_SHA1_C)
     "MBEDTLS_SHA1_C",
 #endif /* MBEDTLS_SHA1_C */
+#if defined(MBEDTLS_SHA224_C)
+    "MBEDTLS_SHA224_C",
+#endif /* MBEDTLS_SHA224_C */
 #if defined(MBEDTLS_SHA256_C)
     "MBEDTLS_SHA256_C",
 #endif /* MBEDTLS_SHA256_C */
+#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
+    "MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT",
+#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT */
+#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
+    "MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY",
+#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */
+#if defined(MBEDTLS_SHA384_C)
+    "MBEDTLS_SHA384_C",
+#endif /* MBEDTLS_SHA384_C */
 #if defined(MBEDTLS_SHA512_C)
     "MBEDTLS_SHA512_C",
 #endif /* MBEDTLS_SHA512_C */
+#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
+    "MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT",
+#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */
+#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
+    "MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY",
+#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
 #if defined(MBEDTLS_SSL_CACHE_C)
     "MBEDTLS_SSL_CACHE_C",
 #endif /* MBEDTLS_SSL_CACHE_C */
@@ -843,30 +780,29 @@
 #if defined(MBEDTLS_X509_CSR_WRITE_C)
     "MBEDTLS_X509_CSR_WRITE_C",
 #endif /* MBEDTLS_X509_CSR_WRITE_C */
-#if defined(MBEDTLS_XTEA_C)
-    "MBEDTLS_XTEA_C",
-#endif /* MBEDTLS_XTEA_C */
 #endif /* MBEDTLS_VERSION_FEATURES */
     NULL
 };
 
-int mbedtls_version_check_feature( const char *feature )
+int mbedtls_version_check_feature(const char *feature)
 {
     const char * const *idx = features;
 
-    if( *idx == NULL )
-        return( -2 );
+    if (*idx == NULL) {
+        return -2;
+    }
 
-    if( feature == NULL )
-        return( -1 );
+    if (feature == NULL) {
+        return -1;
+    }
 
-    while( *idx != NULL )
-    {
-        if( !strcmp( *idx, feature ) )
-            return( 0 );
+    while (*idx != NULL) {
+        if (!strcmp(*idx, feature)) {
+            return 0;
+        }
         idx++;
     }
-    return( -1 );
+    return -1;
 }
 
 #endif /* MBEDTLS_VERSION_C */
diff --git a/lib/libmbedtls/mbedtls/library/x509.c b/lib/libmbedtls/mbedtls/library/x509.c
index 3997ebd..fc13b92 100644
--- a/lib/libmbedtls/mbedtls/library/x509.c
+++ b/lib/libmbedtls/mbedtls/library/x509.c
@@ -43,16 +43,7 @@
 #include "mbedtls/pem.h"
 #endif
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#define mbedtls_free      free
-#define mbedtls_calloc    calloc
-#define mbedtls_printf    printf
-#define mbedtls_snprintf  snprintf
-#endif
 
 #if defined(MBEDTLS_HAVE_TIME)
 #include "mbedtls/platform_time.h"
@@ -62,42 +53,47 @@
 #include <time.h>
 #endif
 
-#define CHECK(code) if( ( ret = ( code ) ) != 0 ){ return( ret ); }
+#include "mbedtls/legacy_or_psa.h"
+
+#define CHECK(code) if ((ret = (code)) != 0) { return ret; }
 #define CHECK_RANGE(min, max, val)                      \
     do                                                  \
     {                                                   \
-        if( ( val ) < ( min ) || ( val ) > ( max ) )    \
+        if ((val) < (min) || (val) > (max))    \
         {                                               \
-            return( ret );                              \
+            return ret;                              \
         }                                               \
-    } while( 0 )
+    } while (0)
 
 /*
  *  CertificateSerialNumber  ::=  INTEGER
  */
-int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end,
-                     mbedtls_x509_buf *serial )
+int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end,
+                            mbedtls_x509_buf *serial)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( ( end - *p ) < 1 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SERIAL,
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA ) );
+    if ((end - *p) < 1) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL,
+                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
+    }
 
-    if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) &&
-        **p !=   MBEDTLS_ASN1_INTEGER )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SERIAL,
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
+    if (**p != (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2) &&
+        **p !=   MBEDTLS_ASN1_INTEGER) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL,
+                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
+    }
 
     serial->tag = *(*p)++;
 
-    if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SERIAL, ret ) );
+    if ((ret = mbedtls_asn1_get_len(p, end, &serial->len)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, ret);
+    }
 
     serial->p = *p;
     *p += serial->len;
 
-    return( 0 );
+    return 0;
 }
 
 /* Get an algorithm identifier without parameters (eg for signatures)
@@ -106,29 +102,72 @@
  *       algorithm               OBJECT IDENTIFIER,
  *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
  */
-int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end,
-                       mbedtls_x509_buf *alg )
+int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end,
+                              mbedtls_x509_buf *alg)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
+    if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Parse an algorithm identifier with (optional) parameters
  */
-int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end,
-                  mbedtls_x509_buf *alg, mbedtls_x509_buf *params )
+int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end,
+                         mbedtls_x509_buf *alg, mbedtls_x509_buf *params)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
+    if ((ret = mbedtls_asn1_get_alg(p, end, alg, params)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
+    }
 
-    return( 0 );
+    return 0;
+}
+
+/*
+ * Convert md type to string
+ */
+static inline const char *md_type_to_string(mbedtls_md_type_t md_alg)
+{
+    switch (md_alg) {
+#if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA)
+        case MBEDTLS_MD_MD5:
+            return "MD5";
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA)
+        case MBEDTLS_MD_SHA1:
+            return "SHA1";
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA)
+        case MBEDTLS_MD_SHA224:
+            return "SHA224";
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA)
+        case MBEDTLS_MD_SHA256:
+            return "SHA256";
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA)
+        case MBEDTLS_MD_SHA384:
+            return "SHA384";
+#endif
+#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA)
+        case MBEDTLS_MD_SHA512:
+            return "SHA512";
+#endif
+#if defined(MBEDTLS_HAS_ALG_RIPEMD160_VIA_MD_OR_PSA)
+        case MBEDTLS_MD_RIPEMD160:
+            return "RIPEMD160";
+#endif
+        case MBEDTLS_MD_NONE:
+            return NULL;
+        default:
+            return NULL;
+    }
 }
 
 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
@@ -141,7 +180,7 @@
  *
  * For HashAlgorithm, parameters MUST be NULL or absent.
  */
-static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg )
+static int x509_get_hash_alg(const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *p;
@@ -150,42 +189,49 @@
     size_t len;
 
     /* Make sure we got a SEQUENCE and setup bounds */
-    if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
+    if (alg->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
+                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
+    }
 
     p = alg->p;
     end = p + alg->len;
 
-    if( p >= end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA ) );
+    if (p >= end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
+                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
+    }
 
     /* Parse md_oid */
     md_oid.tag = *p;
 
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &md_oid.len, MBEDTLS_ASN1_OID)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
+    }
 
     md_oid.p = p;
     p += md_oid.len;
 
     /* Get md_alg from md_oid */
-    if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
+    if ((ret = mbedtls_oid_get_md_alg(&md_oid, md_alg)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
+    }
 
     /* Make sure params is absent of NULL */
-    if( p == end )
-        return( 0 );
+    if (p == end) {
+        return 0;
+    }
 
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_NULL)) != 0 || len != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
+    }
 
-    if( p != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -198,11 +244,11 @@
  *
  * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value
  * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other
- * option. Enfore this at parsing time.
+ * option. Enforce this at parsing time.
  */
-int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params,
-                                mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
-                                int *salt_len )
+int mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params,
+                                       mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
+                                       int *salt_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *p;
@@ -216,121 +262,139 @@
     *salt_len = 20;
 
     /* Make sure params is a SEQUENCE and setup bounds */
-    if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
+    if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
+                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
+    }
 
     p = (unsigned char *) params->p;
     end = p + params->len;
 
-    if( p == end )
-        return( 0 );
+    if (p == end) {
+        return 0;
+    }
 
     /*
      * HashAlgorithm
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 )
-    {
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
+                                    0)) == 0) {
         end2 = p + len;
 
         /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
-        if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 )
-            return( ret );
+        if ((ret = mbedtls_x509_get_alg_null(&p, end2, &alg_id)) != 0) {
+            return ret;
+        }
 
-        if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
+        if ((ret = mbedtls_oid_get_md_alg(&alg_id, md_alg)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
+        }
 
-        if( p != end2 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+        if (p != end2) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
+                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+        }
+    } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
     }
-    else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
 
-    if( p == end )
-        return( 0 );
+    if (p == end) {
+        return 0;
+    }
 
     /*
      * MaskGenAlgorithm
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 )
-    {
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
+                                    1)) == 0) {
         end2 = p + len;
 
         /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
-        if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 )
-            return( ret );
+        if ((ret = mbedtls_x509_get_alg(&p, end2, &alg_id, &alg_params)) != 0) {
+            return ret;
+        }
 
         /* Only MFG1 is recognised for now */
-        if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE,
-                    MBEDTLS_ERR_OID_NOT_FOUND ) );
+        if (MBEDTLS_OID_CMP(MBEDTLS_OID_MGF1, &alg_id) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE,
+                                     MBEDTLS_ERR_OID_NOT_FOUND);
+        }
 
         /* Parse HashAlgorithm */
-        if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 )
-            return( ret );
+        if ((ret = x509_get_hash_alg(&alg_params, mgf_md)) != 0) {
+            return ret;
+        }
 
-        if( p != end2 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+        if (p != end2) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
+                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+        }
+    } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
     }
-    else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
 
-    if( p == end )
-        return( 0 );
+    if (p == end) {
+        return 0;
+    }
 
     /*
      * salt_len
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 )
-    {
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
+                                    2)) == 0) {
         end2 = p + len;
 
-        if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
+        if ((ret = mbedtls_asn1_get_int(&p, end2, salt_len)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
+        }
 
-        if( p != end2 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+        if (p != end2) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
+                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+        }
+    } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
     }
-    else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
 
-    if( p == end )
-        return( 0 );
+    if (p == end) {
+        return 0;
+    }
 
     /*
      * trailer_field (if present, must be 1)
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 )
-    {
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
+                                    3)) == 0) {
         int trailer_field;
 
         end2 = p + len;
 
-        if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
+        if ((ret = mbedtls_asn1_get_int(&p, end2, &trailer_field)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
+        }
 
-        if( p != end2 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+        if (p != end2) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
+                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+        }
 
-        if( trailer_field != 1 )
-            return( MBEDTLS_ERR_X509_INVALID_ALG );
+        if (trailer_field != 1) {
+            return MBEDTLS_ERR_X509_INVALID_ALG;
+        }
+    } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
     }
-    else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) );
 
-    if( p != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
 
@@ -343,63 +407,68 @@
  *
  *  AttributeValue ::= ANY DEFINED BY AttributeType
  */
-static int x509_get_attr_type_value( unsigned char **p,
-                                     const unsigned char *end,
-                                     mbedtls_x509_name *cur )
+static int x509_get_attr_type_value(unsigned char **p,
+                                    const unsigned char *end,
+                                    mbedtls_x509_name *cur)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
     mbedtls_x509_buf *oid;
     mbedtls_x509_buf *val;
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
+    }
 
     end = *p + len;
 
-    if( ( end - *p ) < 1 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME,
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA ) );
+    if ((end - *p) < 1) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
+                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
+    }
 
     oid = &cur->oid;
     oid->tag = **p;
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &oid->len, MBEDTLS_ASN1_OID)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
+    }
 
     oid->p = *p;
     *p += oid->len;
 
-    if( ( end - *p ) < 1 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME,
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA ) );
+    if ((end - *p) < 1) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
+                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
+    }
 
-    if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING      &&
+    if (**p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING      &&
         **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING &&
         **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING &&
-        **p != MBEDTLS_ASN1_BIT_STRING )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME,
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
+        **p != MBEDTLS_ASN1_BIT_STRING) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
+                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
+    }
 
     val = &cur->val;
     val->tag = *(*p)++;
 
-    if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) );
+    if ((ret = mbedtls_asn1_get_len(p, end, &val->len)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
+    }
 
     val->p = *p;
     *p += val->len;
 
-    if( *p != end )
-    {
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (*p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
     }
 
     cur->next = NULL;
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -424,41 +493,51 @@
  * For the general case we still use a flat list, but we mark elements of the
  * same set so that they are "merged" together in the functions that consume
  * this list, eg mbedtls_x509_dn_gets().
+ *
+ * On success, this function may allocate a linked list starting at cur->next
+ * that must later be free'd by the caller using mbedtls_free(). In error
+ * cases, this function frees all allocated memory internally and the caller
+ * has no freeing responsibilities.
  */
-int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
-                   mbedtls_x509_name *cur )
+int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end,
+                          mbedtls_x509_name *cur)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t set_len;
     const unsigned char *end_set;
+    mbedtls_x509_name *head = cur;
 
     /* don't use recursion, we'd risk stack overflow if not optimized */
-    while( 1 )
-    {
+    while (1) {
         /*
          * parse SET
          */
-        if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len,
-                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) );
+        if ((ret = mbedtls_asn1_get_tag(p, end, &set_len,
+                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) {
+            ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
+            goto error;
+        }
 
         end_set  = *p + set_len;
 
-        while( 1 )
-        {
-            if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 )
-                return( ret );
+        while (1) {
+            if ((ret = x509_get_attr_type_value(p, end_set, cur)) != 0) {
+                goto error;
+            }
 
-            if( *p == end_set )
+            if (*p == end_set) {
                 break;
+            }
 
             /* Mark this item as being no the only one in a set */
             cur->next_merged = 1;
 
-            cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
+            cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name));
 
-            if( cur->next == NULL )
-                return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+            if (cur->next == NULL) {
+                ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
+                goto error;
+            }
 
             cur = cur->next;
         }
@@ -466,46 +545,55 @@
         /*
          * continue until end of SEQUENCE is reached
          */
-        if( *p == end )
-            return( 0 );
+        if (*p == end) {
+            return 0;
+        }
 
-        cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
+        cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name));
 
-        if( cur->next == NULL )
-            return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+        if (cur->next == NULL) {
+            ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
+            goto error;
+        }
 
         cur = cur->next;
     }
+
+error:
+    /* Skip the first element as we did not allocate it */
+    mbedtls_asn1_free_named_data_list_shallow(head->next);
+    head->next = NULL;
+
+    return ret;
 }
 
-static int x509_parse_int( unsigned char **p, size_t n, int *res )
+static int x509_parse_int(unsigned char **p, size_t n, int *res)
 {
     *res = 0;
 
-    for( ; n > 0; --n )
-    {
-        if( ( **p < '0') || ( **p > '9' ) )
-            return ( MBEDTLS_ERR_X509_INVALID_DATE );
+    for (; n > 0; --n) {
+        if ((**p < '0') || (**p > '9')) {
+            return MBEDTLS_ERR_X509_INVALID_DATE;
+        }
 
         *res *= 10;
-        *res += ( *(*p)++ - '0' );
+        *res += (*(*p)++ - '0');
     }
 
-    return( 0 );
+    return 0;
 }
 
-static int x509_date_is_valid(const mbedtls_x509_time *t )
+static int x509_date_is_valid(const mbedtls_x509_time *t)
 {
     int ret = MBEDTLS_ERR_X509_INVALID_DATE;
     int month_len;
 
-    CHECK_RANGE( 0, 9999, t->year );
-    CHECK_RANGE( 0, 23,   t->hour );
-    CHECK_RANGE( 0, 59,   t->min  );
-    CHECK_RANGE( 0, 59,   t->sec  );
+    CHECK_RANGE(0, 9999, t->year);
+    CHECK_RANGE(0, 23,   t->hour);
+    CHECK_RANGE(0, 59,   t->min);
+    CHECK_RANGE(0, 59,   t->sec);
 
-    switch( t->mon )
-    {
+    switch (t->mon) {
         case 1: case 3: case 5: case 7: case 8: case 10: case 12:
             month_len = 31;
             break;
@@ -513,69 +601,69 @@
             month_len = 30;
             break;
         case 2:
-            if( ( !( t->year % 4 ) && t->year % 100 ) ||
-                !( t->year % 400 ) )
+            if ((!(t->year % 4) && t->year % 100) ||
+                !(t->year % 400)) {
                 month_len = 29;
-            else
+            } else {
                 month_len = 28;
+            }
             break;
         default:
-            return( ret );
+            return ret;
     }
-    CHECK_RANGE( 1, month_len, t->day );
+    CHECK_RANGE(1, month_len, t->day);
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4)
  * field.
  */
-static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen,
-                            mbedtls_x509_time *tm )
+static int x509_parse_time(unsigned char **p, size_t len, size_t yearlen,
+                           mbedtls_x509_time *tm)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     /*
      * Minimum length is 10 or 12 depending on yearlen
      */
-    if ( len < yearlen + 8 )
-        return ( MBEDTLS_ERR_X509_INVALID_DATE );
+    if (len < yearlen + 8) {
+        return MBEDTLS_ERR_X509_INVALID_DATE;
+    }
     len -= yearlen + 8;
 
     /*
      * Parse year, month, day, hour, minute
      */
-    CHECK( x509_parse_int( p, yearlen, &tm->year ) );
-    if ( 2 == yearlen )
-    {
-        if ( tm->year < 50 )
+    CHECK(x509_parse_int(p, yearlen, &tm->year));
+    if (2 == yearlen) {
+        if (tm->year < 50) {
             tm->year += 100;
+        }
 
         tm->year += 1900;
     }
 
-    CHECK( x509_parse_int( p, 2, &tm->mon ) );
-    CHECK( x509_parse_int( p, 2, &tm->day ) );
-    CHECK( x509_parse_int( p, 2, &tm->hour ) );
-    CHECK( x509_parse_int( p, 2, &tm->min ) );
+    CHECK(x509_parse_int(p, 2, &tm->mon));
+    CHECK(x509_parse_int(p, 2, &tm->day));
+    CHECK(x509_parse_int(p, 2, &tm->hour));
+    CHECK(x509_parse_int(p, 2, &tm->min));
 
     /*
      * Parse seconds if present
      */
-    if ( len >= 2 )
-    {
-        CHECK( x509_parse_int( p, 2, &tm->sec ) );
+    if (len >= 2) {
+        CHECK(x509_parse_int(p, 2, &tm->sec));
         len -= 2;
+    } else {
+        return MBEDTLS_ERR_X509_INVALID_DATE;
     }
-    else
-        return ( MBEDTLS_ERR_X509_INVALID_DATE );
 
     /*
      * Parse trailing 'Z' if present
      */
-    if ( 1 == len && 'Z' == **p )
-    {
+    if (1 == len && 'Z' == **p) {
         (*p)++;
         len--;
     }
@@ -583,12 +671,13 @@
     /*
      * We should have parsed all characters at this point
      */
-    if ( 0 != len )
-        return ( MBEDTLS_ERR_X509_INVALID_DATE );
+    if (0 != len) {
+        return MBEDTLS_ERR_X509_INVALID_DATE;
+    }
 
-    CHECK( x509_date_is_valid( tm ) );
+    CHECK(x509_date_is_valid(tm));
 
-    return ( 0 );
+    return 0;
 }
 
 /*
@@ -596,50 +685,55 @@
  *       utcTime        UTCTime,
  *       generalTime    GeneralizedTime }
  */
-int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end,
-                           mbedtls_x509_time *tm )
+int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end,
+                          mbedtls_x509_time *tm)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len, year_len;
     unsigned char tag;
 
-    if( ( end - *p ) < 1 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE,
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA ) );
+    if ((end - *p) < 1) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,
+                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
+    }
 
     tag = **p;
 
-    if( tag == MBEDTLS_ASN1_UTC_TIME )
+    if (tag == MBEDTLS_ASN1_UTC_TIME) {
         year_len = 2;
-    else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME )
+    } else if (tag == MBEDTLS_ASN1_GENERALIZED_TIME) {
         year_len = 4;
-    else
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE,
-                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
+    } else {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,
+                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
+    }
 
     (*p)++;
-    ret = mbedtls_asn1_get_len( p, end, &len );
+    ret = mbedtls_asn1_get_len(p, end, &len);
 
-    if( ret != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, ret ) );
+    if (ret != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret);
+    }
 
-    return x509_parse_time( p, len, year_len, tm );
+    return x509_parse_time(p, len, year_len, tm);
 }
 
-int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig )
+int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
     int tag_type;
 
-    if( ( end - *p ) < 1 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SIGNATURE,
-                MBEDTLS_ERR_ASN1_OUT_OF_DATA ) );
+    if ((end - *p) < 1) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE,
+                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
+    }
 
     tag_type = **p;
 
-    if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SIGNATURE, ret ) );
+    if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE, ret);
+    }
 
     sig->tag = tag_type;
     sig->len = len;
@@ -647,63 +741,64 @@
 
     *p += len;
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Get signature algorithm from alg OID and optional parameters
  */
-int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
-                      mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
-                      void **sig_opts )
+int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
+                             mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
+                             void **sig_opts)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( *sig_opts != NULL )
-        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+    if (*sig_opts != NULL) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
 
-    if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG, ret ) );
+    if ((ret = mbedtls_oid_get_sig_alg(sig_oid, md_alg, pk_alg)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG, ret);
+    }
 
 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
-    if( *pk_alg == MBEDTLS_PK_RSASSA_PSS )
-    {
+    if (*pk_alg == MBEDTLS_PK_RSASSA_PSS) {
         mbedtls_pk_rsassa_pss_options *pss_opts;
 
-        pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) );
-        if( pss_opts == NULL )
-            return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+        pss_opts = mbedtls_calloc(1, sizeof(mbedtls_pk_rsassa_pss_options));
+        if (pss_opts == NULL) {
+            return MBEDTLS_ERR_X509_ALLOC_FAILED;
+        }
 
-        ret = mbedtls_x509_get_rsassa_pss_params( sig_params,
-                                          md_alg,
-                                          &pss_opts->mgf1_hash_id,
-                                          &pss_opts->expected_salt_len );
-        if( ret != 0 )
-        {
-            mbedtls_free( pss_opts );
-            return( ret );
+        ret = mbedtls_x509_get_rsassa_pss_params(sig_params,
+                                                 md_alg,
+                                                 &pss_opts->mgf1_hash_id,
+                                                 &pss_opts->expected_salt_len);
+        if (ret != 0) {
+            mbedtls_free(pss_opts);
+            return ret;
         }
 
         *sig_opts = (void *) pss_opts;
-    }
-    else
+    } else
 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
     {
         /* Make sure parameters are absent or NULL */
-        if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) ||
-              sig_params->len != 0 )
-        return( MBEDTLS_ERR_X509_INVALID_ALG );
+        if ((sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0) ||
+            sig_params->len != 0) {
+            return MBEDTLS_ERR_X509_INVALID_ALG;
+        }
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * X.509 Extensions (No parsing of extensions, pointer should
  * be either manually updated or extensions should be parsed!)
  */
-int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end,
-                          mbedtls_x509_buf *ext, int tag )
+int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end,
+                         mbedtls_x509_buf *ext, int tag)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
@@ -711,10 +806,11 @@
     /* Extension structure use EXPLICIT tagging. That is, the actual
      * `Extensions` structure is wrapped by a tag-length pair using
      * the respective context-specific tag. */
-    ret = mbedtls_asn1_get_tag( p, end, &ext->len,
-              MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag );
-    if( ret != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
+    ret = mbedtls_asn1_get_tag(p, end, &ext->len,
+                               MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag);
+    if (ret != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+    }
 
     ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag;
     ext->p   = *p;
@@ -723,22 +819,24 @@
     /*
      * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
      */
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+    }
 
-    if( end != *p + len )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (end != *p + len) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Store the name in printable form into buf; no more
  * than size characters will be written
  */
-int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn )
+int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i, j, n;
@@ -747,67 +845,67 @@
     const char *short_name = NULL;
     char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p;
 
-    memset( s, 0, sizeof( s ) );
+    memset(s, 0, sizeof(s));
 
     name = dn;
     p = buf;
     n = size;
 
-    while( name != NULL )
-    {
-        if( !name->oid.p )
-        {
+    while (name != NULL) {
+        if (!name->oid.p) {
             name = name->next;
             continue;
         }
 
-        if( name != dn )
-        {
-            ret = mbedtls_snprintf( p, n, merge ? " + " : ", " );
+        if (name != dn) {
+            ret = mbedtls_snprintf(p, n, merge ? " + " : ", ");
             MBEDTLS_X509_SAFE_SNPRINTF;
         }
 
-        ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name );
+        ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name);
 
-        if( ret == 0 )
-            ret = mbedtls_snprintf( p, n, "%s=", short_name );
-        else
-            ret = mbedtls_snprintf( p, n, "\?\?=" );
+        if (ret == 0) {
+            ret = mbedtls_snprintf(p, n, "%s=", short_name);
+        } else {
+            ret = mbedtls_snprintf(p, n, "\?\?=");
+        }
         MBEDTLS_X509_SAFE_SNPRINTF;
 
-        for( i = 0, j = 0; i < name->val.len; i++, j++ )
-        {
-            if( j >= sizeof( s ) - 1 )
-                return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+        for (i = 0, j = 0; i < name->val.len; i++, j++) {
+            if (j >= sizeof(s) - 1) {
+                return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
+            }
 
             c = name->val.p[i];
             // Special characters requiring escaping, RFC 1779
-            if( c && strchr( ",=+<>#;\"\\", c ) )
-            {
-                if( j + 1 >= sizeof( s ) - 1 )
-                    return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+            if (c && strchr(",=+<>#;\"\\", c)) {
+                if (j + 1 >= sizeof(s) - 1) {
+                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
+                }
                 s[j++] = '\\';
             }
-            if( c < 32 || c >= 127 )
-                 s[j] = '?';
-            else s[j] = c;
+            if (c < 32 || c >= 127) {
+                s[j] = '?';
+            } else {
+                s[j] = c;
+            }
         }
         s[j] = '\0';
-        ret = mbedtls_snprintf( p, n, "%s", s );
+        ret = mbedtls_snprintf(p, n, "%s", s);
         MBEDTLS_X509_SAFE_SNPRINTF;
 
         merge = name->next_merged;
         name = name->next;
     }
 
-    return( (int) ( size - n ) );
+    return (int) (size - n);
 }
 
 /*
  * Store the serial in printable form into buf; no more
  * than size characters will be written
  */
-int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial )
+int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t i, n, nr;
@@ -816,62 +914,61 @@
     p = buf;
     n = size;
 
-    nr = ( serial->len <= 32 )
+    nr = (serial->len <= 32)
         ? serial->len  : 28;
 
-    for( i = 0; i < nr; i++ )
-    {
-        if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
+    for (i = 0; i < nr; i++) {
+        if (i == 0 && nr > 1 && serial->p[i] == 0x0) {
             continue;
+        }
 
-        ret = mbedtls_snprintf( p, n, "%02X%s",
-                serial->p[i], ( i < nr - 1 ) ? ":" : "" );
+        ret = mbedtls_snprintf(p, n, "%02X%s",
+                               serial->p[i], (i < nr - 1) ? ":" : "");
         MBEDTLS_X509_SAFE_SNPRINTF;
     }
 
-    if( nr != serial->len )
-    {
-        ret = mbedtls_snprintf( p, n, "...." );
+    if (nr != serial->len) {
+        ret = mbedtls_snprintf(p, n, "....");
         MBEDTLS_X509_SAFE_SNPRINTF;
     }
 
-    return( (int) ( size - n ) );
+    return (int) (size - n);
 }
 
+#if !defined(MBEDTLS_X509_REMOVE_INFO)
 /*
  * Helper for writing signature algorithms
  */
-int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
-                       mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
-                       const void *sig_opts )
+int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
+                              mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
+                              const void *sig_opts)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     char *p = buf;
     size_t n = size;
     const char *desc = NULL;
 
-    ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc );
-    if( ret != 0 )
-        ret = mbedtls_snprintf( p, n, "???"  );
-    else
-        ret = mbedtls_snprintf( p, n, "%s", desc );
+    ret = mbedtls_oid_get_sig_alg_desc(sig_oid, &desc);
+    if (ret != 0) {
+        ret = mbedtls_snprintf(p, n, "???");
+    } else {
+        ret = mbedtls_snprintf(p, n, "%s", desc);
+    }
     MBEDTLS_X509_SAFE_SNPRINTF;
 
 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
-    if( pk_alg == MBEDTLS_PK_RSASSA_PSS )
-    {
+    if (pk_alg == MBEDTLS_PK_RSASSA_PSS) {
         const mbedtls_pk_rsassa_pss_options *pss_opts;
-        const mbedtls_md_info_t *md_info, *mgf_md_info;
 
         pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts;
 
-        md_info = mbedtls_md_info_from_type( md_alg );
-        mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id );
+        const char *name = md_type_to_string(md_alg);
+        const char *mgf_name = md_type_to_string(pss_opts->mgf1_hash_id);
 
-        ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)",
-                              md_info ? mbedtls_md_get_name( md_info ) : "???",
-                              mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???",
-                              (unsigned int) pss_opts->expected_salt_len );
+        ret = mbedtls_snprintf(p, n, " (%s, MGF1-%s, 0x%02X)",
+                               name ? name : "???",
+                               mgf_name ? mgf_name : "???",
+                               (unsigned int) pss_opts->expected_salt_len);
         MBEDTLS_X509_SAFE_SNPRINTF;
     }
 #else
@@ -880,22 +977,23 @@
     ((void) sig_opts);
 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
 
-    return( (int)( size - n ) );
+    return (int) (size - n);
 }
+#endif /* MBEDTLS_X509_REMOVE_INFO */
 
 /*
  * Helper for writing "RSA key size", "EC key size", etc
  */
-int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name )
+int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name)
 {
     char *p = buf;
     size_t n = buf_size;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    ret = mbedtls_snprintf( p, n, "%s key size", name );
+    ret = mbedtls_snprintf(p, n, "%s key size", name);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    return( 0 );
+    return 0;
 }
 
 #if defined(MBEDTLS_HAVE_TIME_DATE)
@@ -903,19 +1001,18 @@
  * Set the time structure to the current time.
  * Return 0 on success, non-zero on failure.
  */
-static int x509_get_current_time( mbedtls_x509_time *now )
+static int x509_get_current_time(mbedtls_x509_time *now)
 {
     struct tm *lt, tm_buf;
     mbedtls_time_t tt;
     int ret = 0;
 
-    tt = mbedtls_time( NULL );
-    lt = mbedtls_platform_gmtime_r( &tt, &tm_buf );
+    tt = mbedtls_time(NULL);
+    lt = mbedtls_platform_gmtime_r(&tt, &tm_buf);
 
-    if( lt == NULL )
+    if (lt == NULL) {
         ret = -1;
-    else
-    {
+    } else {
         now->year = lt->tm_year + 1900;
         now->mon  = lt->tm_mon  + 1;
         now->day  = lt->tm_mday;
@@ -924,151 +1021,621 @@
         now->sec  = lt->tm_sec;
     }
 
-    return( ret );
+    return ret;
 }
 
 /*
  * Return 0 if before <= after, 1 otherwise
  */
-static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after )
+static int x509_check_time(const mbedtls_x509_time *before, const mbedtls_x509_time *after)
 {
-    if( before->year  > after->year )
-        return( 1 );
+    if (before->year  > after->year) {
+        return 1;
+    }
 
-    if( before->year == after->year &&
-        before->mon   > after->mon )
-        return( 1 );
+    if (before->year == after->year &&
+        before->mon   > after->mon) {
+        return 1;
+    }
 
-    if( before->year == after->year &&
+    if (before->year == after->year &&
         before->mon  == after->mon  &&
-        before->day   > after->day )
-        return( 1 );
+        before->day   > after->day) {
+        return 1;
+    }
 
-    if( before->year == after->year &&
+    if (before->year == after->year &&
         before->mon  == after->mon  &&
         before->day  == after->day  &&
-        before->hour  > after->hour )
-        return( 1 );
+        before->hour  > after->hour) {
+        return 1;
+    }
 
-    if( before->year == after->year &&
+    if (before->year == after->year &&
         before->mon  == after->mon  &&
         before->day  == after->day  &&
         before->hour == after->hour &&
-        before->min   > after->min  )
-        return( 1 );
+        before->min   > after->min) {
+        return 1;
+    }
 
-    if( before->year == after->year &&
+    if (before->year == after->year &&
         before->mon  == after->mon  &&
         before->day  == after->day  &&
         before->hour == after->hour &&
         before->min  == after->min  &&
-        before->sec   > after->sec  )
-        return( 1 );
+        before->sec   > after->sec) {
+        return 1;
+    }
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_x509_time_is_past( const mbedtls_x509_time *to )
+int mbedtls_x509_time_is_past(const mbedtls_x509_time *to)
 {
     mbedtls_x509_time now;
 
-    if( x509_get_current_time( &now ) != 0 )
-        return( 1 );
+    if (x509_get_current_time(&now) != 0) {
+        return 1;
+    }
 
-    return( x509_check_time( &now, to ) );
+    return x509_check_time(&now, to);
 }
 
-int mbedtls_x509_time_is_future( const mbedtls_x509_time *from )
+int mbedtls_x509_time_is_future(const mbedtls_x509_time *from)
 {
     mbedtls_x509_time now;
 
-    if( x509_get_current_time( &now ) != 0 )
-        return( 1 );
+    if (x509_get_current_time(&now) != 0) {
+        return 1;
+    }
 
-    return( x509_check_time( from, &now ) );
+    return x509_check_time(from, &now);
 }
 
 #else  /* MBEDTLS_HAVE_TIME_DATE */
 
-int mbedtls_x509_time_is_past( const mbedtls_x509_time *to )
+int mbedtls_x509_time_is_past(const mbedtls_x509_time *to)
 {
     ((void) to);
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_x509_time_is_future( const mbedtls_x509_time *from )
+int mbedtls_x509_time_is_future(const mbedtls_x509_time *from)
 {
     ((void) from);
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_HAVE_TIME_DATE */
 
-#if defined(MBEDTLS_SELF_TEST)
-
-#include "mbedtls/x509_crt.h"
-#include "mbedtls/certs.h"
-
+/* Common functions for parsing CRT and CSR. */
+#if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(MBEDTLS_X509_CSR_PARSE_C)
 /*
- * Checkup routine
+ * OtherName ::= SEQUENCE {
+ *      type-id    OBJECT IDENTIFIER,
+ *      value      [0] EXPLICIT ANY DEFINED BY type-id }
+ *
+ * HardwareModuleName ::= SEQUENCE {
+ *                           hwType OBJECT IDENTIFIER,
+ *                           hwSerialNum OCTET STRING }
+ *
+ * NOTE: we currently only parse and use otherName of type HwModuleName,
+ * as defined in RFC 4108.
  */
-int mbedtls_x509_self_test( int verbose )
+static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name,
+                               mbedtls_x509_san_other_name *other_name)
 {
     int ret = 0;
-#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C)
-    uint32_t flags;
-    mbedtls_x509_crt cacert;
-    mbedtls_x509_crt clicert;
+    size_t len;
+    unsigned char *p = subject_alt_name->p;
+    const unsigned char *end = p + subject_alt_name->len;
+    mbedtls_x509_buf cur_oid;
 
-    if( verbose != 0 )
-        mbedtls_printf( "  X.509 certificate load: " );
-
-    mbedtls_x509_crt_init( &cacert );
-    mbedtls_x509_crt_init( &clicert );
-
-    ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt,
-                           mbedtls_test_cli_crt_len );
-    if( ret != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
-
-        goto cleanup;
+    if ((subject_alt_name->tag &
+         (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) !=
+        (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME)) {
+        /*
+         * The given subject alternative name is not of type "othername".
+         */
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
     }
 
-    ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt,
-                          mbedtls_test_ca_crt_len );
-    if( ret != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
-
-        goto cleanup;
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_OID)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n  X.509 signature verify: ");
+    cur_oid.tag = MBEDTLS_ASN1_OID;
+    cur_oid.p = p;
+    cur_oid.len = len;
 
-    ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
-    if( ret != 0 )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "failed\n" );
-
-        goto cleanup;
+    /*
+     * Only HwModuleName is currently supported.
+     */
+    if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid) != 0) {
+        return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
     }
 
-    if( verbose != 0 )
-        mbedtls_printf( "passed\n\n");
+    p += len;
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=
+        0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+    }
 
-cleanup:
-    mbedtls_x509_crt_free( &cacert  );
-    mbedtls_x509_crt_free( &clicert );
-#else
-    ((void) verbose);
-#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA256_C */
-    return( ret );
+    if (end != p + len) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+    }
+
+    if (end != p + len) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+    }
+
+    other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID;
+    other_name->value.hardware_module_name.oid.p = p;
+    other_name->value.hardware_module_name.oid.len = len;
+
+    p += len;
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_OCTET_STRING)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+    }
+
+    other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;
+    other_name->value.hardware_module_name.val.p = p;
+    other_name->value.hardware_module_name.val.len = len;
+    p += len;
+    if (p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+    return 0;
 }
 
-#endif /* MBEDTLS_SELF_TEST */
+/*
+ * SubjectAltName ::= GeneralNames
+ *
+ * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+ *
+ * GeneralName ::= CHOICE {
+ *      otherName                       [0]     OtherName,
+ *      rfc822Name                      [1]     IA5String,
+ *      dNSName                         [2]     IA5String,
+ *      x400Address                     [3]     ORAddress,
+ *      directoryName                   [4]     Name,
+ *      ediPartyName                    [5]     EDIPartyName,
+ *      uniformResourceIdentifier       [6]     IA5String,
+ *      iPAddress                       [7]     OCTET STRING,
+ *      registeredID                    [8]     OBJECT IDENTIFIER }
+ *
+ * OtherName ::= SEQUENCE {
+ *      type-id    OBJECT IDENTIFIER,
+ *      value      [0] EXPLICIT ANY DEFINED BY type-id }
+ *
+ * EDIPartyName ::= SEQUENCE {
+ *      nameAssigner            [0]     DirectoryString OPTIONAL,
+ *      partyName               [1]     DirectoryString }
+ *
+ * We list all types, but use the following GeneralName types from RFC 5280:
+ * "dnsName", "uniformResourceIdentifier" and "hardware_module_name"
+ * of type "otherName", as defined in RFC 4108.
+ */
+int mbedtls_x509_get_subject_alt_name(unsigned char **p,
+                                      const unsigned char *end,
+                                      mbedtls_x509_sequence *subject_alt_name)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t len, tag_len;
+    mbedtls_asn1_sequence *cur = subject_alt_name;
 
+    /* Get main sequence tag */
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+    }
+
+    if (*p + len != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+
+    while (*p < end) {
+        mbedtls_x509_subject_alternative_name dummy_san_buf;
+        mbedtls_x509_buf tmp_san_buf;
+        memset(&dummy_san_buf, 0, sizeof(dummy_san_buf));
+
+        tmp_san_buf.tag = **p;
+        (*p)++;
+
+        if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
+
+        tmp_san_buf.p = *p;
+        tmp_san_buf.len = tag_len;
+
+        if ((tmp_san_buf.tag & MBEDTLS_ASN1_TAG_CLASS_MASK) !=
+            MBEDTLS_ASN1_CONTEXT_SPECIFIC) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                     MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
+        }
+
+        /*
+         * Check that the SAN is structured correctly.
+         */
+        ret = mbedtls_x509_parse_subject_alt_name(&tmp_san_buf, &dummy_san_buf);
+        /*
+         * In case the extension is malformed, return an error,
+         * and clear the allocated sequences.
+         */
+        if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
+            mbedtls_asn1_sequence_free(subject_alt_name->next);
+            subject_alt_name->next = NULL;
+            return ret;
+        }
+
+        /* Allocate and assign next pointer */
+        if (cur->buf.p != NULL) {
+            if (cur->next != NULL) {
+                return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
+            }
+
+            cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
+
+            if (cur->next == NULL) {
+                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                         MBEDTLS_ERR_ASN1_ALLOC_FAILED);
+            }
+
+            cur = cur->next;
+        }
+
+        cur->buf = tmp_san_buf;
+        *p += tmp_san_buf.len;
+    }
+
+    /* Set final sequence entry's next pointer to NULL */
+    cur->next = NULL;
+
+    if (*p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+
+    return 0;
+}
+
+int mbedtls_x509_get_ns_cert_type(unsigned char **p,
+                                  const unsigned char *end,
+                                  unsigned char *ns_cert_type)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_x509_bitstring bs = { 0, 0, NULL };
+
+    if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+    }
+
+    /* A bitstring with no flags set is still technically valid, as it will mean
+       that the certificate has no designated purpose at the time of creation. */
+    if (bs.len == 0) {
+        *ns_cert_type = 0;
+        return 0;
+    }
+
+    if (bs.len != 1) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_INVALID_LENGTH);
+    }
+
+    /* Get actual bitstring */
+    *ns_cert_type = *bs.p;
+    return 0;
+}
+
+int mbedtls_x509_get_key_usage(unsigned char **p,
+                               const unsigned char *end,
+                               unsigned int *key_usage)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t i;
+    mbedtls_x509_bitstring bs = { 0, 0, NULL };
+
+    if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+    }
+
+    /* A bitstring with no flags set is still technically valid, as it will mean
+       that the certificate has no designated purpose at the time of creation. */
+    if (bs.len == 0) {
+        *key_usage = 0;
+        return 0;
+    }
+
+    /* Get actual bitstring */
+    *key_usage = 0;
+    for (i = 0; i < bs.len && i < sizeof(unsigned int); i++) {
+        *key_usage |= (unsigned int) bs.p[i] << (8*i);
+    }
+
+    return 0;
+}
+
+int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
+                                        mbedtls_x509_subject_alternative_name *san)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    switch (san_buf->tag &
+            (MBEDTLS_ASN1_TAG_CLASS_MASK |
+             MBEDTLS_ASN1_TAG_VALUE_MASK)) {
+        /*
+         * otherName
+         */
+        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME):
+        {
+            mbedtls_x509_san_other_name other_name;
+
+            ret = x509_get_other_name(san_buf, &other_name);
+            if (ret != 0) {
+                return ret;
+            }
+
+            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
+            san->type = MBEDTLS_X509_SAN_OTHER_NAME;
+            memcpy(&san->san.other_name,
+                   &other_name, sizeof(other_name));
+
+        }
+        break;
+        /*
+         * uniformResourceIdentifier
+         */
+        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER):
+        {
+            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
+            san->type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER;
+
+            memcpy(&san->san.unstructured_name,
+                   san_buf, sizeof(*san_buf));
+
+        }
+        break;
+        /*
+         * dNSName
+         */
+        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME):
+        {
+            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
+            san->type = MBEDTLS_X509_SAN_DNS_NAME;
+
+            memcpy(&san->san.unstructured_name,
+                   san_buf, sizeof(*san_buf));
+        }
+        break;
+
+        /*
+         * RFC822 Name
+         */
+        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_RFC822_NAME):
+        {
+            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
+            san->type = MBEDTLS_X509_SAN_RFC822_NAME;
+            memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf));
+        }
+        break;
+
+        /*
+         * Type not supported
+         */
+        default:
+            return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
+    }
+    return 0;
+}
+
+#if !defined(MBEDTLS_X509_REMOVE_INFO)
+int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,
+                                       const mbedtls_x509_sequence
+                                       *subject_alt_name,
+                                       const char *prefix)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t i;
+    size_t n = *size;
+    char *p = *buf;
+    const mbedtls_x509_sequence *cur = subject_alt_name;
+    mbedtls_x509_subject_alternative_name san;
+    int parse_ret;
+
+    while (cur != NULL) {
+        memset(&san, 0, sizeof(san));
+        parse_ret = mbedtls_x509_parse_subject_alt_name(&cur->buf, &san);
+        if (parse_ret != 0) {
+            if (parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
+                ret = mbedtls_snprintf(p, n, "\n%s    <unsupported>", prefix);
+                MBEDTLS_X509_SAFE_SNPRINTF;
+            } else {
+                ret = mbedtls_snprintf(p, n, "\n%s    <malformed>", prefix);
+                MBEDTLS_X509_SAFE_SNPRINTF;
+            }
+            cur = cur->next;
+            continue;
+        }
+
+        switch (san.type) {
+            /*
+             * otherName
+             */
+            case MBEDTLS_X509_SAN_OTHER_NAME:
+            {
+                mbedtls_x509_san_other_name *other_name = &san.san.other_name;
+
+                ret = mbedtls_snprintf(p, n, "\n%s    otherName :", prefix);
+                MBEDTLS_X509_SAFE_SNPRINTF;
+
+                if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME,
+                                    &other_name->value.hardware_module_name.oid) != 0) {
+                    ret = mbedtls_snprintf(p, n, "\n%s        hardware module name :", prefix);
+                    MBEDTLS_X509_SAFE_SNPRINTF;
+                    ret =
+                        mbedtls_snprintf(p, n, "\n%s            hardware type          : ", prefix);
+                    MBEDTLS_X509_SAFE_SNPRINTF;
+
+                    ret = mbedtls_oid_get_numeric_string(p,
+                                                         n,
+                                                         &other_name->value.hardware_module_name.oid);
+                    MBEDTLS_X509_SAFE_SNPRINTF;
+
+                    ret =
+                        mbedtls_snprintf(p, n, "\n%s            hardware serial number : ", prefix);
+                    MBEDTLS_X509_SAFE_SNPRINTF;
+
+                    for (i = 0; i < other_name->value.hardware_module_name.val.len; i++) {
+                        ret = mbedtls_snprintf(p,
+                                               n,
+                                               "%02X",
+                                               other_name->value.hardware_module_name.val.p[i]);
+                        MBEDTLS_X509_SAFE_SNPRINTF;
+                    }
+                }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
+            }
+            break;
+            /*
+             * uniformResourceIdentifier
+             */
+            case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
+            {
+                ret = mbedtls_snprintf(p, n, "\n%s    uniformResourceIdentifier : ", prefix);
+                MBEDTLS_X509_SAFE_SNPRINTF;
+                if (san.san.unstructured_name.len >= n) {
+                    *p = '\0';
+                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
+                }
+
+                memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len);
+                p += san.san.unstructured_name.len;
+                n -= san.san.unstructured_name.len;
+            }
+            break;
+            /*
+             * dNSName
+             * RFC822 Name
+             */
+            case MBEDTLS_X509_SAN_DNS_NAME:
+            case MBEDTLS_X509_SAN_RFC822_NAME:
+            {
+                const char *dns_name = "dNSName";
+                const char *rfc822_name = "rfc822Name";
+
+                ret = mbedtls_snprintf(p, n,
+                                       "\n%s    %s : ",
+                                       prefix,
+                                       san.type ==
+                                       MBEDTLS_X509_SAN_DNS_NAME ? dns_name : rfc822_name);
+                MBEDTLS_X509_SAFE_SNPRINTF;
+                if (san.san.unstructured_name.len >= n) {
+                    *p = '\0';
+                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
+                }
+
+                memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len);
+                p += san.san.unstructured_name.len;
+                n -= san.san.unstructured_name.len;
+            }
+            break;
+
+            /*
+             * Type not supported, skip item.
+             */
+            default:
+                ret = mbedtls_snprintf(p, n, "\n%s    <unsupported>", prefix);
+                MBEDTLS_X509_SAFE_SNPRINTF;
+                break;
+        }
+
+        cur = cur->next;
+    }
+
+    *p = '\0';
+
+    *size = n;
+    *buf = p;
+
+    return 0;
+}
+
+#define PRINT_ITEM(i)                           \
+    {                                           \
+        ret = mbedtls_snprintf(p, n, "%s" i, sep);    \
+        MBEDTLS_X509_SAFE_SNPRINTF;                        \
+        sep = ", ";                             \
+    }
+
+#define CERT_TYPE(type, name)                    \
+    if (ns_cert_type & (type))                 \
+    PRINT_ITEM(name);
+
+int mbedtls_x509_info_cert_type(char **buf, size_t *size,
+                                unsigned char ns_cert_type)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t n = *size;
+    char *p = *buf;
+    const char *sep = "";
+
+    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT,         "SSL Client");
+    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER,         "SSL Server");
+    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL,              "Email");
+    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING,     "Object Signing");
+    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_RESERVED,           "Reserved");
+    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CA,             "SSL CA");
+    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA,           "Email CA");
+    CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA,  "Object Signing CA");
+
+    *size = n;
+    *buf = p;
+
+    return 0;
+}
+
+#define KEY_USAGE(code, name)    \
+    if (key_usage & (code))    \
+    PRINT_ITEM(name);
+
+int mbedtls_x509_info_key_usage(char **buf, size_t *size,
+                                unsigned int key_usage)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t n = *size;
+    char *p = *buf;
+    const char *sep = "";
+
+    KEY_USAGE(MBEDTLS_X509_KU_DIGITAL_SIGNATURE,    "Digital Signature");
+    KEY_USAGE(MBEDTLS_X509_KU_NON_REPUDIATION,      "Non Repudiation");
+    KEY_USAGE(MBEDTLS_X509_KU_KEY_ENCIPHERMENT,     "Key Encipherment");
+    KEY_USAGE(MBEDTLS_X509_KU_DATA_ENCIPHERMENT,    "Data Encipherment");
+    KEY_USAGE(MBEDTLS_X509_KU_KEY_AGREEMENT,        "Key Agreement");
+    KEY_USAGE(MBEDTLS_X509_KU_KEY_CERT_SIGN,        "Key Cert Sign");
+    KEY_USAGE(MBEDTLS_X509_KU_CRL_SIGN,             "CRL Sign");
+    KEY_USAGE(MBEDTLS_X509_KU_ENCIPHER_ONLY,        "Encipher Only");
+    KEY_USAGE(MBEDTLS_X509_KU_DECIPHER_ONLY,        "Decipher Only");
+
+    *size = n;
+    *buf = p;
+
+    return 0;
+}
+#endif /* MBEDTLS_X509_REMOVE_INFO */
+#endif /* MBEDTLS_X509_CRT_PARSE_C || MBEDTLS_X509_CSR_PARSE_C */
 #endif /* MBEDTLS_X509_USE_C */
diff --git a/lib/libmbedtls/mbedtls/library/x509_create.c b/lib/libmbedtls/mbedtls/library/x509_create.c
index 056bbaa..50db956 100644
--- a/lib/libmbedtls/mbedtls/library/x509_create.c
+++ b/lib/libmbedtls/mbedtls/library/x509_create.c
@@ -31,115 +31,115 @@
 /* Structure linking OIDs for X.509 DN AttributeTypes to their
  * string representations and default string encodings used by Mbed TLS. */
 typedef struct {
-   const char *name; /* String representation of AttributeType, e.g.
-                      * "CN" or "emailAddress". */
-   size_t name_len;  /* Length of 'name', without trailing 0 byte. */
-   const char *oid;  /* String representation of OID of AttributeType,
+    const char *name; /* String representation of AttributeType, e.g.
+                       * "CN" or "emailAddress". */
+    size_t name_len; /* Length of 'name', without trailing 0 byte. */
+    const char *oid; /* String representation of OID of AttributeType,
                       * as per RFC 5280, Appendix A.1. */
-   int default_tag;  /* The default character encoding used for the
+    int default_tag; /* The default character encoding used for the
                       * given attribute type, e.g.
                       * MBEDTLS_ASN1_UTF8_STRING for UTF-8. */
 } x509_attr_descriptor_t;
 
-#define ADD_STRLEN( s )     s, sizeof( s ) - 1
+#define ADD_STRLEN(s)     s, sizeof(s) - 1
 
 /* X.509 DN attributes from RFC 5280, Appendix A.1. */
 static const x509_attr_descriptor_t x509_attrs[] =
 {
-    { ADD_STRLEN( "CN" ),
+    { ADD_STRLEN("CN"),
       MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "commonName" ),
+    { ADD_STRLEN("commonName"),
       MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "C" ),
+    { ADD_STRLEN("C"),
       MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING },
-    { ADD_STRLEN( "countryName" ),
+    { ADD_STRLEN("countryName"),
       MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING },
-    { ADD_STRLEN( "O" ),
+    { ADD_STRLEN("O"),
       MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "organizationName" ),
+    { ADD_STRLEN("organizationName"),
       MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "L" ),
+    { ADD_STRLEN("L"),
       MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "locality" ),
+    { ADD_STRLEN("locality"),
       MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "R" ),
+    { ADD_STRLEN("R"),
       MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING },
-    { ADD_STRLEN( "OU" ),
+    { ADD_STRLEN("OU"),
       MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "organizationalUnitName" ),
+    { ADD_STRLEN("organizationalUnitName"),
       MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "ST" ),
+    { ADD_STRLEN("ST"),
       MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "stateOrProvinceName" ),
+    { ADD_STRLEN("stateOrProvinceName"),
       MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "emailAddress" ),
+    { ADD_STRLEN("emailAddress"),
       MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING },
-    { ADD_STRLEN( "serialNumber" ),
+    { ADD_STRLEN("serialNumber"),
       MBEDTLS_OID_AT_SERIAL_NUMBER, MBEDTLS_ASN1_PRINTABLE_STRING },
-    { ADD_STRLEN( "postalAddress" ),
+    { ADD_STRLEN("postalAddress"),
       MBEDTLS_OID_AT_POSTAL_ADDRESS, MBEDTLS_ASN1_PRINTABLE_STRING },
-    { ADD_STRLEN( "postalCode" ),
+    { ADD_STRLEN("postalCode"),
       MBEDTLS_OID_AT_POSTAL_CODE, MBEDTLS_ASN1_PRINTABLE_STRING },
-    { ADD_STRLEN( "dnQualifier" ),
+    { ADD_STRLEN("dnQualifier"),
       MBEDTLS_OID_AT_DN_QUALIFIER, MBEDTLS_ASN1_PRINTABLE_STRING },
-    { ADD_STRLEN( "title" ),
+    { ADD_STRLEN("title"),
       MBEDTLS_OID_AT_TITLE, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "surName" ),
+    { ADD_STRLEN("surName"),
       MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "SN" ),
+    { ADD_STRLEN("SN"),
       MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "givenName" ),
+    { ADD_STRLEN("givenName"),
       MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "GN" ),
+    { ADD_STRLEN("GN"),
       MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "initials" ),
+    { ADD_STRLEN("initials"),
       MBEDTLS_OID_AT_INITIALS, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "pseudonym" ),
+    { ADD_STRLEN("pseudonym"),
       MBEDTLS_OID_AT_PSEUDONYM, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "generationQualifier" ),
+    { ADD_STRLEN("generationQualifier"),
       MBEDTLS_OID_AT_GENERATION_QUALIFIER, MBEDTLS_ASN1_UTF8_STRING },
-    { ADD_STRLEN( "domainComponent" ),
+    { ADD_STRLEN("domainComponent"),
       MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING },
-    { ADD_STRLEN( "DC" ),
+    { ADD_STRLEN("DC"),
       MBEDTLS_OID_DOMAIN_COMPONENT,   MBEDTLS_ASN1_IA5_STRING },
     { NULL, 0, NULL, MBEDTLS_ASN1_NULL }
 };
 
-static const x509_attr_descriptor_t *x509_attr_descr_from_name( const char *name, size_t name_len )
+static const x509_attr_descriptor_t *x509_attr_descr_from_name(const char *name, size_t name_len)
 {
     const x509_attr_descriptor_t *cur;
 
-    for( cur = x509_attrs; cur->name != NULL; cur++ )
-        if( cur->name_len == name_len &&
-            strncmp( cur->name, name, name_len ) == 0 )
+    for (cur = x509_attrs; cur->name != NULL; cur++) {
+        if (cur->name_len == name_len &&
+            strncmp(cur->name, name, name_len) == 0) {
             break;
+        }
+    }
 
-    if ( cur->name == NULL )
-        return( NULL );
+    if (cur->name == NULL) {
+        return NULL;
+    }
 
-    return( cur );
+    return cur;
 }
 
-int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name )
+int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name)
 {
     int ret = 0;
     const char *s = name, *c = s;
-    const char *end = s + strlen( s );
+    const char *end = s + strlen(s);
     const char *oid = NULL;
-    const x509_attr_descriptor_t* attr_descr = NULL;
+    const x509_attr_descriptor_t *attr_descr = NULL;
     int in_tag = 1;
     char data[MBEDTLS_X509_MAX_DN_NAME_SIZE];
     char *d = data;
 
     /* Clear existing chain if present */
-    mbedtls_asn1_free_named_data_list( head );
+    mbedtls_asn1_free_named_data_list(head);
 
-    while( c <= end )
-    {
-        if( in_tag && *c == '=' )
-        {
-            if( ( attr_descr = x509_attr_descr_from_name( s, c - s ) ) == NULL )
-            {
+    while (c <= end) {
+        if (in_tag && *c == '=') {
+            if ((attr_descr = x509_attr_descr_from_name(s, c - s)) == NULL) {
                 ret = MBEDTLS_ERR_X509_UNKNOWN_OID;
                 goto exit;
             }
@@ -150,45 +150,39 @@
             d = data;
         }
 
-        if( !in_tag && *c == '\\' && c != end )
-        {
+        if (!in_tag && *c == '\\' && c != end) {
             c++;
 
             /* Check for valid escaped characters */
-            if( c == end || *c != ',' )
-            {
+            if (c == end || *c != ',') {
                 ret = MBEDTLS_ERR_X509_INVALID_NAME;
                 goto exit;
             }
-        }
-        else if( !in_tag && ( *c == ',' || c == end ) )
-        {
-            mbedtls_asn1_named_data* cur =
-                mbedtls_asn1_store_named_data( head, oid, strlen( oid ),
-                                               (unsigned char *) data,
-                                               d - data );
+        } else if (!in_tag && (*c == ',' || c == end)) {
+            mbedtls_asn1_named_data *cur =
+                mbedtls_asn1_store_named_data(head, oid, strlen(oid),
+                                              (unsigned char *) data,
+                                              d - data);
 
-            if(cur == NULL )
-            {
-                return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+            if (cur == NULL) {
+                return MBEDTLS_ERR_X509_ALLOC_FAILED;
             }
 
             // set tagType
             cur->val.tag = attr_descr->default_tag;
 
-            while( c < end && *(c + 1) == ' ' )
+            while (c < end && *(c + 1) == ' ') {
                 c++;
+            }
 
             s = c + 1;
             in_tag = 1;
         }
 
-        if( !in_tag && s != c + 1 )
-        {
+        if (!in_tag && s != c + 1) {
             *(d++) = *c;
 
-            if( d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE )
-            {
+            if (d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE) {
                 ret = MBEDTLS_ERR_X509_INVALID_NAME;
                 goto exit;
             }
@@ -199,27 +193,26 @@
 
 exit:
 
-    return( ret );
+    return ret;
 }
 
 /* The first byte of the value in the mbedtls_asn1_named_data structure is reserved
  * to store the critical boolean for us
  */
-int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len,
-                        int critical, const unsigned char *val, size_t val_len )
+int mbedtls_x509_set_extension(mbedtls_asn1_named_data **head, const char *oid, size_t oid_len,
+                               int critical, const unsigned char *val, size_t val_len)
 {
     mbedtls_asn1_named_data *cur;
 
-    if( ( cur = mbedtls_asn1_store_named_data( head, oid, oid_len,
-                                       NULL, val_len + 1 ) ) == NULL )
-    {
-        return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+    if ((cur = mbedtls_asn1_store_named_data(head, oid, oid_len,
+                                             NULL, val_len + 1)) == NULL) {
+        return MBEDTLS_ERR_X509_ALLOC_FAILED;
     }
 
     cur->val.p[0] = critical;
-    memcpy( cur->val.p + 1, val, val_len );
+    memcpy(cur->val.p + 1, val, val_len);
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -234,115 +227,117 @@
  *
  *  AttributeValue ::= ANY DEFINED BY AttributeType
  */
-static int x509_write_name( unsigned char **p, unsigned char *start, mbedtls_asn1_named_data* cur_name)
+static int x509_write_name(unsigned char **p,
+                           unsigned char *start,
+                           mbedtls_asn1_named_data *cur_name)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
-    const char *oid             = (const char*)cur_name->oid.p;
+    const char *oid             = (const char *) cur_name->oid.p;
     size_t oid_len              = cur_name->oid.len;
     const unsigned char *name   = cur_name->val.p;
     size_t name_len             = cur_name->val.len;
 
     // Write correct string tag and value
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tagged_string( p, start,
-                                                       cur_name->val.tag,
-                                                       (const char *) name,
-                                                       name_len ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tagged_string(p, start,
+                                                               cur_name->val.tag,
+                                                               (const char *) name,
+                                                               name_len));
     // Write OID
     //
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid,
-                                                       oid_len ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid,
+                                                     oid_len));
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
-                                                    MBEDTLS_ASN1_CONSTRUCTED |
-                                                    MBEDTLS_ASN1_SEQUENCE ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
+                                                     MBEDTLS_ASN1_CONSTRUCTED |
+                                                     MBEDTLS_ASN1_SEQUENCE));
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
-                                                 MBEDTLS_ASN1_CONSTRUCTED |
-                                                 MBEDTLS_ASN1_SET ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
+                                                     MBEDTLS_ASN1_CONSTRUCTED |
+                                                     MBEDTLS_ASN1_SET));
 
-    return( (int) len );
+    return (int) len;
 }
 
-int mbedtls_x509_write_names( unsigned char **p, unsigned char *start,
-                              mbedtls_asn1_named_data *first )
+int mbedtls_x509_write_names(unsigned char **p, unsigned char *start,
+                             mbedtls_asn1_named_data *first)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
     mbedtls_asn1_named_data *cur = first;
 
-    while( cur != NULL )
-    {
-        MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, cur ) );
+    while (cur != NULL) {
+        MBEDTLS_ASN1_CHK_ADD(len, x509_write_name(p, start, cur));
         cur = cur->next;
     }
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
-                                                 MBEDTLS_ASN1_SEQUENCE ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED |
+                                                     MBEDTLS_ASN1_SEQUENCE));
 
-    return( (int) len );
+    return (int) len;
 }
 
-int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start,
-                    const char *oid, size_t oid_len,
-                    unsigned char *sig, size_t size )
+int mbedtls_x509_write_sig(unsigned char **p, unsigned char *start,
+                           const char *oid, size_t oid_len,
+                           unsigned char *sig, size_t size)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
-    if( *p < start || (size_t)( *p - start ) < size )
-        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    if (*p < start || (size_t) (*p - start) < size) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    }
 
     len = size;
     (*p) -= len;
-    memcpy( *p, sig, len );
+    memcpy(*p, sig, len);
 
-    if( *p - start < 1 )
-        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+    if (*p - start < 1) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    }
 
     *--(*p) = 0;
     len += 1;
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BIT_STRING));
 
     // Write OID
     //
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( p, start, oid,
-                                                        oid_len, 0 ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier(p, start, oid,
+                                                                      oid_len, 0));
 
-    return( (int) len );
+    return (int) len;
 }
 
-static int x509_write_extension( unsigned char **p, unsigned char *start,
-                                 mbedtls_asn1_named_data *ext )
+static int x509_write_extension(unsigned char **p, unsigned char *start,
+                                mbedtls_asn1_named_data *ext)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1,
-                                              ext->val.len - 1 ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->val.len - 1 ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, ext->val.p + 1,
+                                                            ext->val.len - 1));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, ext->val.len - 1));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OCTET_STRING));
 
-    if( ext->val.p[0] != 0 )
-    {
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( p, start, 1 ) );
+    if (ext->val.p[0] != 0) {
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_bool(p, start, 1));
     }
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->oid.p,
-                                              ext->oid.len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->oid.len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, ext->oid.p,
+                                                            ext->oid.len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, ext->oid.len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OID));
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
-                                                 MBEDTLS_ASN1_SEQUENCE ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED |
+                                                     MBEDTLS_ASN1_SEQUENCE));
 
-    return( (int) len );
+    return (int) len;
 }
 
 /*
@@ -355,20 +350,19 @@
  *                 -- by extnID
  *     }
  */
-int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start,
-                           mbedtls_asn1_named_data *first )
+int mbedtls_x509_write_extensions(unsigned char **p, unsigned char *start,
+                                  mbedtls_asn1_named_data *first)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
     mbedtls_asn1_named_data *cur_ext = first;
 
-    while( cur_ext != NULL )
-    {
-        MBEDTLS_ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
+    while (cur_ext != NULL) {
+        MBEDTLS_ASN1_CHK_ADD(len, x509_write_extension(p, start, cur_ext));
         cur_ext = cur_ext->next;
     }
 
-    return( (int) len );
+    return (int) len;
 }
 
 #endif /* MBEDTLS_X509_CREATE_C */
diff --git a/lib/libmbedtls/mbedtls/library/x509_crl.c b/lib/libmbedtls/mbedtls/library/x509_crl.c
index d2d8042..f644203 100644
--- a/lib/libmbedtls/mbedtls/library/x509_crl.c
+++ b/lib/libmbedtls/mbedtls/library/x509_crl.c
@@ -1,5 +1,5 @@
 /*
- *  X.509 Certidicate Revocation List (CRL) parsing
+ *  X.509 Certificate Revocation List (CRL) parsing
  *
  *  Copyright The Mbed TLS Contributors
  *  SPDX-License-Identifier: Apache-2.0
@@ -42,15 +42,7 @@
 #include "mbedtls/pem.h"
 #endif
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#include <stdio.h>
-#define mbedtls_free       free
-#define mbedtls_calloc    calloc
-#define mbedtls_snprintf   snprintf
-#endif
 
 #if defined(MBEDTLS_HAVE_TIME)
 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
@@ -67,24 +59,22 @@
 /*
  *  Version  ::=  INTEGER  {  v1(0), v2(1)  }
  */
-static int x509_crl_get_version( unsigned char **p,
-                             const unsigned char *end,
-                             int *ver )
+static int x509_crl_get_version(unsigned char **p,
+                                const unsigned char *end,
+                                int *ver)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
-    {
-        if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-        {
+    if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) {
+        if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
             *ver = 0;
-            return( 0 );
+            return 0;
         }
 
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_VERSION, ret ) );
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret);
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -94,26 +84,27 @@
  * list of extensions is well-formed and abort on critical extensions (that
  * are unsupported as we don't support any extension so far)
  */
-static int x509_get_crl_ext( unsigned char **p,
-                             const unsigned char *end,
-                             mbedtls_x509_buf *ext )
+static int x509_get_crl_ext(unsigned char **p,
+                            const unsigned char *end,
+                            mbedtls_x509_buf *ext)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( *p == end )
-        return( 0 );
+    if (*p == end) {
+        return 0;
+    }
 
     /*
      * crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
      *                              -- if present, version MUST be v2
      */
-    if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0 ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_x509_get_ext(p, end, ext, 0)) != 0) {
+        return ret;
+    }
 
     end = ext->p + ext->len;
 
-    while( *p < end )
-    {
+    while (*p < end) {
         /*
          * Extension  ::=  SEQUENCE  {
          *      extnID      OBJECT IDENTIFIER,
@@ -125,65 +116,69 @@
         size_t len;
 
         /* Get enclosing sequence tag */
-        if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
+        if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
 
         end_ext_data = *p + len;
 
         /* Get OID (currently ignored) */
-        if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len,
-                                          MBEDTLS_ASN1_OID ) ) != 0 )
-        {
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
+        if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len,
+                                        MBEDTLS_ASN1_OID)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
         }
         *p += len;
 
         /* Get optional critical */
-        if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data,
-                                           &is_critical ) ) != 0 &&
-            ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
-        {
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
+        if ((ret = mbedtls_asn1_get_bool(p, end_ext_data,
+                                         &is_critical)) != 0 &&
+            (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
         }
 
         /* Data should be octet string type */
-        if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len,
-                MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
+        if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len,
+                                        MBEDTLS_ASN1_OCTET_STRING)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
 
         /* Ignore data so far and just check its length */
         *p += len;
-        if( *p != end_ext_data )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+        if (*p != end_ext_data) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+        }
 
         /* Abort on (unsupported) critical extensions */
-        if( is_critical )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                    MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
+        if (is_critical) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                     MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
+        }
     }
 
-    if( *p != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (*p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * X.509 CRL v2 entry extensions (no extensions parsed yet.)
  */
-static int x509_get_crl_entry_ext( unsigned char **p,
-                             const unsigned char *end,
-                             mbedtls_x509_buf *ext )
+static int x509_get_crl_entry_ext(unsigned char **p,
+                                  const unsigned char *end,
+                                  mbedtls_x509_buf *ext)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
     /* OPTIONAL */
-    if( end <= *p )
-        return( 0 );
+    if (end <= *p) {
+        return 0;
+    }
 
     ext->tag = **p;
     ext->p = *p;
@@ -192,110 +187,112 @@
      * Get CRL-entry extension sequence header
      * crlEntryExtensions      Extensions OPTIONAL  -- if present, MUST be v2
      */
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-        {
+    if ((ret = mbedtls_asn1_get_tag(p, end, &ext->len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
             ext->p = NULL;
-            return( 0 );
+            return 0;
         }
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
     }
 
     end = *p + ext->len;
 
-    if( end != *p + ext->len )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (end != *p + ext->len) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
-    while( *p < end )
-    {
-        if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
+    while (*p < end) {
+        if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
 
         *p += len;
     }
 
-    if( *p != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (*p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * X.509 CRL Entries
  */
-static int x509_get_entries( unsigned char **p,
-                             const unsigned char *end,
-                             mbedtls_x509_crl_entry *entry )
+static int x509_get_entries(unsigned char **p,
+                            const unsigned char *end,
+                            mbedtls_x509_crl_entry *entry)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t entry_len;
     mbedtls_x509_crl_entry *cur_entry = entry;
 
-    if( *p == end )
-        return( 0 );
+    if (*p == end) {
+        return 0;
+    }
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &entry_len,
-            MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 )
-    {
-        if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-            return( 0 );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &entry_len,
+                                    MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) {
+        if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
+            return 0;
+        }
 
-        return( ret );
+        return ret;
     }
 
     end = *p + entry_len;
 
-    while( *p < end )
-    {
+    while (*p < end) {
         size_t len2;
         const unsigned char *end2;
 
         cur_entry->raw.tag = **p;
-        if( ( ret = mbedtls_asn1_get_tag( p, end, &len2,
-                MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 )
-        {
-            return( ret );
+        if ((ret = mbedtls_asn1_get_tag(p, end, &len2,
+                                        MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) {
+            return ret;
         }
 
         cur_entry->raw.p = *p;
         cur_entry->raw.len = len2;
         end2 = *p + len2;
 
-        if( ( ret = mbedtls_x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 )
-            return( ret );
+        if ((ret = mbedtls_x509_get_serial(p, end2, &cur_entry->serial)) != 0) {
+            return ret;
+        }
 
-        if( ( ret = mbedtls_x509_get_time( p, end2,
-                                   &cur_entry->revocation_date ) ) != 0 )
-            return( ret );
+        if ((ret = mbedtls_x509_get_time(p, end2,
+                                         &cur_entry->revocation_date)) != 0) {
+            return ret;
+        }
 
-        if( ( ret = x509_get_crl_entry_ext( p, end2,
-                                            &cur_entry->entry_ext ) ) != 0 )
-            return( ret );
+        if ((ret = x509_get_crl_entry_ext(p, end2,
+                                          &cur_entry->entry_ext)) != 0) {
+            return ret;
+        }
 
-        if( *p < end )
-        {
-            cur_entry->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl_entry ) );
+        if (*p < end) {
+            cur_entry->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crl_entry));
 
-            if( cur_entry->next == NULL )
-                return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+            if (cur_entry->next == NULL) {
+                return MBEDTLS_ERR_X509_ALLOC_FAILED;
+            }
 
             cur_entry = cur_entry->next;
         }
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Parse one  CRLs in DER format and append it to the chained list
  */
-int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain,
-                        const unsigned char *buf, size_t buflen )
+int mbedtls_x509_crl_parse_der(mbedtls_x509_crl *chain,
+                               const unsigned char *buf, size_t buflen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
@@ -306,44 +303,46 @@
     /*
      * Check for valid input
      */
-    if( crl == NULL || buf == NULL )
-        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+    if (crl == NULL || buf == NULL) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
 
-    memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) );
-    memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) );
-    memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) );
+    memset(&sig_params1, 0, sizeof(mbedtls_x509_buf));
+    memset(&sig_params2, 0, sizeof(mbedtls_x509_buf));
+    memset(&sig_oid2, 0, sizeof(mbedtls_x509_buf));
 
     /*
      * Add new CRL on the end of the chain if needed.
      */
-    while( crl->version != 0 && crl->next != NULL )
+    while (crl->version != 0 && crl->next != NULL) {
         crl = crl->next;
+    }
 
-    if( crl->version != 0 && crl->next == NULL )
-    {
-        crl->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl ) );
+    if (crl->version != 0 && crl->next == NULL) {
+        crl->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crl));
 
-        if( crl->next == NULL )
-        {
-            mbedtls_x509_crl_free( crl );
-            return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+        if (crl->next == NULL) {
+            mbedtls_x509_crl_free(crl);
+            return MBEDTLS_ERR_X509_ALLOC_FAILED;
         }
 
-        mbedtls_x509_crl_init( crl->next );
+        mbedtls_x509_crl_init(crl->next);
         crl = crl->next;
     }
 
     /*
      * Copy raw DER-encoded CRL
      */
-    if( buflen == 0 )
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT );
+    if (buflen == 0) {
+        return MBEDTLS_ERR_X509_INVALID_FORMAT;
+    }
 
-    p = mbedtls_calloc( 1, buflen );
-    if( p == NULL )
-        return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+    p = mbedtls_calloc(1, buflen);
+    if (p == NULL) {
+        return MBEDTLS_ERR_X509_ALLOC_FAILED;
+    }
 
-    memcpy( p, buf, buflen );
+    memcpy(p, buf, buflen);
 
     crl->raw.p = p;
     crl->raw.len = buflen;
@@ -356,18 +355,16 @@
      *      signatureAlgorithm   AlgorithmIdentifier,
      *      signatureValue       BIT STRING  }
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        mbedtls_x509_crl_free( crl );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        mbedtls_x509_crl_free(crl);
+        return MBEDTLS_ERR_X509_INVALID_FORMAT;
     }
 
-    if( len != (size_t) ( end - p ) )
-    {
-        mbedtls_x509_crl_free( crl );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (len != (size_t) (end - p)) {
+        mbedtls_x509_crl_free(crl);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
     }
 
     /*
@@ -375,11 +372,10 @@
      */
     crl->tbs.p = p;
 
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        mbedtls_x509_crl_free( crl );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        mbedtls_x509_crl_free(crl);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
     }
 
     end = p + len;
@@ -391,27 +387,24 @@
      *
      * signature            AlgorithmIdentifier
      */
-    if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 ||
-        ( ret = mbedtls_x509_get_alg( &p, end, &crl->sig_oid, &sig_params1 ) ) != 0 )
-    {
-        mbedtls_x509_crl_free( crl );
-        return( ret );
+    if ((ret = x509_crl_get_version(&p, end, &crl->version)) != 0 ||
+        (ret = mbedtls_x509_get_alg(&p, end, &crl->sig_oid, &sig_params1)) != 0) {
+        mbedtls_x509_crl_free(crl);
+        return ret;
     }
 
-    if( crl->version < 0 || crl->version > 1 )
-    {
-        mbedtls_x509_crl_free( crl );
-        return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
+    if (crl->version < 0 || crl->version > 1) {
+        mbedtls_x509_crl_free(crl);
+        return MBEDTLS_ERR_X509_UNKNOWN_VERSION;
     }
 
     crl->version++;
 
-    if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1,
-                                  &crl->sig_md, &crl->sig_pk,
-                                  &crl->sig_opts ) ) != 0 )
-    {
-        mbedtls_x509_crl_free( crl );
-        return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG );
+    if ((ret = mbedtls_x509_get_sig_alg(&crl->sig_oid, &sig_params1,
+                                        &crl->sig_md, &crl->sig_pk,
+                                        &crl->sig_opts)) != 0) {
+        mbedtls_x509_crl_free(crl);
+        return MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG;
     }
 
     /*
@@ -419,17 +412,15 @@
      */
     crl->issuer_raw.p = p;
 
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        mbedtls_x509_crl_free( crl );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        mbedtls_x509_crl_free(crl);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
     }
 
-    if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 )
-    {
-        mbedtls_x509_crl_free( crl );
-        return( ret );
+    if ((ret = mbedtls_x509_get_name(&p, p + len, &crl->issuer)) != 0) {
+        mbedtls_x509_crl_free(crl);
+        return ret;
     }
 
     crl->issuer_raw.len = p - crl->issuer_raw.p;
@@ -438,21 +429,18 @@
      * thisUpdate          Time
      * nextUpdate          Time OPTIONAL
      */
-    if( ( ret = mbedtls_x509_get_time( &p, end, &crl->this_update ) ) != 0 )
-    {
-        mbedtls_x509_crl_free( crl );
-        return( ret );
+    if ((ret = mbedtls_x509_get_time(&p, end, &crl->this_update)) != 0) {
+        mbedtls_x509_crl_free(crl);
+        return ret;
     }
 
-    if( ( ret = mbedtls_x509_get_time( &p, end, &crl->next_update ) ) != 0 )
-    {
-        if( ret != ( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE,
-                        MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) &&
-            ret != ( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE,
-                        MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ) )
-        {
-            mbedtls_x509_crl_free( crl );
-            return( ret );
+    if ((ret = mbedtls_x509_get_time(&p, end, &crl->next_update)) != 0) {
+        if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,
+                                      MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) &&
+            ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,
+                                      MBEDTLS_ERR_ASN1_OUT_OF_DATA))) {
+            mbedtls_x509_crl_free(crl);
+            return ret;
         }
     }
 
@@ -464,32 +452,28 @@
      *                                   -- if present, MUST be v2
      *                        } OPTIONAL
      */
-    if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 )
-    {
-        mbedtls_x509_crl_free( crl );
-        return( ret );
+    if ((ret = x509_get_entries(&p, end, &crl->entry)) != 0) {
+        mbedtls_x509_crl_free(crl);
+        return ret;
     }
 
     /*
      * crlExtensions          EXPLICIT Extensions OPTIONAL
      *                              -- if present, MUST be v2
      */
-    if( crl->version == 2 )
-    {
-        ret = x509_get_crl_ext( &p, end, &crl->crl_ext );
+    if (crl->version == 2) {
+        ret = x509_get_crl_ext(&p, end, &crl->crl_ext);
 
-        if( ret != 0 )
-        {
-            mbedtls_x509_crl_free( crl );
-            return( ret );
+        if (ret != 0) {
+            mbedtls_x509_crl_free(crl);
+            return ret;
         }
     }
 
-    if( p != end )
-    {
-        mbedtls_x509_crl_free( crl );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (p != end) {
+        mbedtls_x509_crl_free(crl);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
     }
 
     end = crl->raw.p + crl->raw.len;
@@ -498,42 +482,38 @@
      *  signatureAlgorithm   AlgorithmIdentifier,
      *  signatureValue       BIT STRING
      */
-    if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 )
-    {
-        mbedtls_x509_crl_free( crl );
-        return( ret );
+    if ((ret = mbedtls_x509_get_alg(&p, end, &sig_oid2, &sig_params2)) != 0) {
+        mbedtls_x509_crl_free(crl);
+        return ret;
     }
 
-    if( crl->sig_oid.len != sig_oid2.len ||
-        memcmp( crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len ) != 0 ||
+    if (crl->sig_oid.len != sig_oid2.len ||
+        memcmp(crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len) != 0 ||
         sig_params1.len != sig_params2.len ||
-        ( sig_params1.len != 0 &&
-          memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) )
-    {
-        mbedtls_x509_crl_free( crl );
-        return( MBEDTLS_ERR_X509_SIG_MISMATCH );
+        (sig_params1.len != 0 &&
+         memcmp(sig_params1.p, sig_params2.p, sig_params1.len) != 0)) {
+        mbedtls_x509_crl_free(crl);
+        return MBEDTLS_ERR_X509_SIG_MISMATCH;
     }
 
-    if( ( ret = mbedtls_x509_get_sig( &p, end, &crl->sig ) ) != 0 )
-    {
-        mbedtls_x509_crl_free( crl );
-        return( ret );
+    if ((ret = mbedtls_x509_get_sig(&p, end, &crl->sig)) != 0) {
+        mbedtls_x509_crl_free(crl);
+        return ret;
     }
 
-    if( p != end )
-    {
-        mbedtls_x509_crl_free( crl );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (p != end) {
+        mbedtls_x509_crl_free(crl);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Parse one or more CRLs and add them to the chained list
  */
-int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen )
+int mbedtls_x509_crl_parse(mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen)
 {
 #if defined(MBEDTLS_PEM_PARSE_C)
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -541,25 +521,25 @@
     mbedtls_pem_context pem;
     int is_pem = 0;
 
-    if( chain == NULL || buf == NULL )
-        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+    if (chain == NULL || buf == NULL) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
 
-    do
-    {
-        mbedtls_pem_init( &pem );
+    do {
+        mbedtls_pem_init(&pem);
 
         // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated
         // string
-        if( buflen == 0 || buf[buflen - 1] != '\0' )
+        if (buflen == 0 || buf[buflen - 1] != '\0') {
             ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
-        else
-            ret = mbedtls_pem_read_buffer( &pem,
-                                           "-----BEGIN X509 CRL-----",
-                                           "-----END X509 CRL-----",
-                                            buf, NULL, 0, &use_len );
+        } else {
+            ret = mbedtls_pem_read_buffer(&pem,
+                                          "-----BEGIN X509 CRL-----",
+                                          "-----END X509 CRL-----",
+                                          buf, NULL, 0, &use_len);
+        }
 
-        if( ret == 0 )
-        {
+        if (ret == 0) {
             /*
              * Was PEM encoded
              */
@@ -568,54 +548,53 @@
             buflen -= use_len;
             buf += use_len;
 
-            if( ( ret = mbedtls_x509_crl_parse_der( chain,
-                                            pem.buf, pem.buflen ) ) != 0 )
-            {
-                mbedtls_pem_free( &pem );
-                return( ret );
+            if ((ret = mbedtls_x509_crl_parse_der(chain,
+                                                  pem.buf, pem.buflen)) != 0) {
+                mbedtls_pem_free(&pem);
+                return ret;
             }
-        }
-        else if( is_pem )
-        {
-            mbedtls_pem_free( &pem );
-            return( ret );
+        } else if (is_pem) {
+            mbedtls_pem_free(&pem);
+            return ret;
         }
 
-        mbedtls_pem_free( &pem );
+        mbedtls_pem_free(&pem);
     }
     /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte.
      * And a valid CRL cannot be less than 1 byte anyway. */
-    while( is_pem && buflen > 1 );
+    while (is_pem && buflen > 1);
 
-    if( is_pem )
-        return( 0 );
-    else
+    if (is_pem) {
+        return 0;
+    } else
 #endif /* MBEDTLS_PEM_PARSE_C */
-        return( mbedtls_x509_crl_parse_der( chain, buf, buflen ) );
+    return mbedtls_x509_crl_parse_der(chain, buf, buflen);
 }
 
 #if defined(MBEDTLS_FS_IO)
 /*
  * Load one or more CRLs and add them to the chained list
  */
-int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path )
+int mbedtls_x509_crl_parse_file(mbedtls_x509_crl *chain, const char *path)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
     unsigned char *buf;
 
-    if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
+        return ret;
+    }
 
-    ret = mbedtls_x509_crl_parse( chain, buf, n );
+    ret = mbedtls_x509_crl_parse(chain, buf, n);
 
-    mbedtls_platform_zeroize( buf, n );
-    mbedtls_free( buf );
+    mbedtls_platform_zeroize(buf, n);
+    mbedtls_free(buf);
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_FS_IO */
 
+#if !defined(MBEDTLS_X509_REMOVE_INFO)
 /*
  * Return an informational string about the certificate.
  */
@@ -624,8 +603,8 @@
 /*
  * Return an informational string about the CRL.
  */
-int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix,
-                   const mbedtls_x509_crl *crl )
+int mbedtls_x509_crl_info(char *buf, size_t size, const char *prefix,
+                          const mbedtls_x509_crl *crl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
@@ -635,136 +614,114 @@
     p = buf;
     n = size;
 
-    ret = mbedtls_snprintf( p, n, "%sCRL version   : %d",
-                               prefix, crl->version );
+    ret = mbedtls_snprintf(p, n, "%sCRL version   : %d",
+                           prefix, crl->version);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    ret = mbedtls_snprintf( p, n, "\n%sissuer name   : ", prefix );
+    ret = mbedtls_snprintf(p, n, "\n%sissuer name   : ", prefix);
     MBEDTLS_X509_SAFE_SNPRINTF;
-    ret = mbedtls_x509_dn_gets( p, n, &crl->issuer );
+    ret = mbedtls_x509_dn_gets(p, n, &crl->issuer);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    ret = mbedtls_snprintf( p, n, "\n%sthis update   : " \
-                   "%04d-%02d-%02d %02d:%02d:%02d", prefix,
-                   crl->this_update.year, crl->this_update.mon,
-                   crl->this_update.day,  crl->this_update.hour,
-                   crl->this_update.min,  crl->this_update.sec );
+    ret = mbedtls_snprintf(p, n, "\n%sthis update   : " \
+                                 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
+                           crl->this_update.year, crl->this_update.mon,
+                           crl->this_update.day,  crl->this_update.hour,
+                           crl->this_update.min,  crl->this_update.sec);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    ret = mbedtls_snprintf( p, n, "\n%snext update   : " \
-                   "%04d-%02d-%02d %02d:%02d:%02d", prefix,
-                   crl->next_update.year, crl->next_update.mon,
-                   crl->next_update.day,  crl->next_update.hour,
-                   crl->next_update.min,  crl->next_update.sec );
+    ret = mbedtls_snprintf(p, n, "\n%snext update   : " \
+                                 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
+                           crl->next_update.year, crl->next_update.mon,
+                           crl->next_update.day,  crl->next_update.hour,
+                           crl->next_update.min,  crl->next_update.sec);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
     entry = &crl->entry;
 
-    ret = mbedtls_snprintf( p, n, "\n%sRevoked certificates:",
-                               prefix );
+    ret = mbedtls_snprintf(p, n, "\n%sRevoked certificates:",
+                           prefix);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    while( entry != NULL && entry->raw.len != 0 )
-    {
-        ret = mbedtls_snprintf( p, n, "\n%sserial number: ",
-                               prefix );
+    while (entry != NULL && entry->raw.len != 0) {
+        ret = mbedtls_snprintf(p, n, "\n%sserial number: ",
+                               prefix);
         MBEDTLS_X509_SAFE_SNPRINTF;
 
-        ret = mbedtls_x509_serial_gets( p, n, &entry->serial );
+        ret = mbedtls_x509_serial_gets(p, n, &entry->serial);
         MBEDTLS_X509_SAFE_SNPRINTF;
 
-        ret = mbedtls_snprintf( p, n, " revocation date: " \
-                   "%04d-%02d-%02d %02d:%02d:%02d",
-                   entry->revocation_date.year, entry->revocation_date.mon,
-                   entry->revocation_date.day,  entry->revocation_date.hour,
-                   entry->revocation_date.min,  entry->revocation_date.sec );
+        ret = mbedtls_snprintf(p, n, " revocation date: " \
+                                     "%04d-%02d-%02d %02d:%02d:%02d",
+                               entry->revocation_date.year, entry->revocation_date.mon,
+                               entry->revocation_date.day,  entry->revocation_date.hour,
+                               entry->revocation_date.min,  entry->revocation_date.sec);
         MBEDTLS_X509_SAFE_SNPRINTF;
 
         entry = entry->next;
     }
 
-    ret = mbedtls_snprintf( p, n, "\n%ssigned using  : ", prefix );
+    ret = mbedtls_snprintf(p, n, "\n%ssigned using  : ", prefix);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    ret = mbedtls_x509_sig_alg_gets( p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md,
-                             crl->sig_opts );
+    ret = mbedtls_x509_sig_alg_gets(p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md,
+                                    crl->sig_opts);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    ret = mbedtls_snprintf( p, n, "\n" );
+    ret = mbedtls_snprintf(p, n, "\n");
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    return( (int) ( size - n ) );
+    return (int) (size - n);
 }
+#endif /* MBEDTLS_X509_REMOVE_INFO */
 
 /*
  * Initialize a CRL chain
  */
-void mbedtls_x509_crl_init( mbedtls_x509_crl *crl )
+void mbedtls_x509_crl_init(mbedtls_x509_crl *crl)
 {
-    memset( crl, 0, sizeof(mbedtls_x509_crl) );
+    memset(crl, 0, sizeof(mbedtls_x509_crl));
 }
 
 /*
  * Unallocate all CRL data
  */
-void mbedtls_x509_crl_free( mbedtls_x509_crl *crl )
+void mbedtls_x509_crl_free(mbedtls_x509_crl *crl)
 {
     mbedtls_x509_crl *crl_cur = crl;
     mbedtls_x509_crl *crl_prv;
-    mbedtls_x509_name *name_cur;
-    mbedtls_x509_name *name_prv;
     mbedtls_x509_crl_entry *entry_cur;
     mbedtls_x509_crl_entry *entry_prv;
 
-    if( crl == NULL )
-        return;
-
-    do
-    {
+    while (crl_cur != NULL) {
 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
-        mbedtls_free( crl_cur->sig_opts );
+        mbedtls_free(crl_cur->sig_opts);
 #endif
 
-        name_cur = crl_cur->issuer.next;
-        while( name_cur != NULL )
-        {
-            name_prv = name_cur;
-            name_cur = name_cur->next;
-            mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
-            mbedtls_free( name_prv );
-        }
+        mbedtls_asn1_free_named_data_list_shallow(crl_cur->issuer.next);
 
         entry_cur = crl_cur->entry.next;
-        while( entry_cur != NULL )
-        {
+        while (entry_cur != NULL) {
             entry_prv = entry_cur;
             entry_cur = entry_cur->next;
-            mbedtls_platform_zeroize( entry_prv,
-                                      sizeof( mbedtls_x509_crl_entry ) );
-            mbedtls_free( entry_prv );
+            mbedtls_platform_zeroize(entry_prv,
+                                     sizeof(mbedtls_x509_crl_entry));
+            mbedtls_free(entry_prv);
         }
 
-        if( crl_cur->raw.p != NULL )
-        {
-            mbedtls_platform_zeroize( crl_cur->raw.p, crl_cur->raw.len );
-            mbedtls_free( crl_cur->raw.p );
+        if (crl_cur->raw.p != NULL) {
+            mbedtls_platform_zeroize(crl_cur->raw.p, crl_cur->raw.len);
+            mbedtls_free(crl_cur->raw.p);
         }
 
-        crl_cur = crl_cur->next;
-    }
-    while( crl_cur != NULL );
-
-    crl_cur = crl;
-    do
-    {
         crl_prv = crl_cur;
         crl_cur = crl_cur->next;
 
-        mbedtls_platform_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) );
-        if( crl_prv != crl )
-            mbedtls_free( crl_prv );
+        mbedtls_platform_zeroize(crl_prv, sizeof(mbedtls_x509_crl));
+        if (crl_prv != crl) {
+            mbedtls_free(crl_prv);
+        }
     }
-    while( crl_cur != NULL );
 }
 
 #endif /* MBEDTLS_X509_CRL_PARSE_C */
diff --git a/lib/libmbedtls/mbedtls/library/x509_crt.c b/lib/libmbedtls/mbedtls/library/x509_crt.c
index 911644b..cf62532 100644
--- a/lib/libmbedtls/mbedtls/library/x509_crt.c
+++ b/lib/libmbedtls/mbedtls/library/x509_crt.c
@@ -47,17 +47,10 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 #include "psa/crypto.h"
 #include "mbedtls/psa_util.h"
-#endif
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#include "hash_info.h"
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#define mbedtls_free       free
-#define mbedtls_calloc    calloc
-#define mbedtls_snprintf   snprintf
-#endif
 
 #if defined(MBEDTLS_THREADING_C)
 #include "mbedtls/threading.h"
@@ -76,7 +69,12 @@
 #if !defined(_WIN32) || defined(EFIX64) || defined(EFI32)
 #include <sys/types.h>
 #include <sys/stat.h>
+#if defined(__MBED__)
+#include <platform/mbed_retarget.h>
+#else
 #include <dirent.h>
+#endif /* __MBED__ */
+#include <errno.h>
 #endif /* !_WIN32 || EFIX64 || EFI32 */
 #endif
 
@@ -91,41 +89,52 @@
 /*
  * Max size of verification chain: end-entity + intermediates + trusted root
  */
-#define X509_MAX_VERIFY_CHAIN_SIZE    ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 )
+#define X509_MAX_VERIFY_CHAIN_SIZE    (MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2)
 
 /* Default profile. Do not remove items unless there are serious security
  * concerns. */
 const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =
 {
-    /* Only SHA-2 hashes */
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
+    /* Hashes from SHA-256 and above. Note that this selection
+     * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512),
     0xFFFFFFF, /* Any PK alg    */
-    0xFFFFFFF, /* Any curve     */
+#if defined(MBEDTLS_ECP_C)
+    /* Curves at or above 128-bit security level. Note that this selection
+     * should be aligned with ssl_preset_default_curves in ssl_tls.c. */
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP256R1) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) |
+    0,
+#else
+    0,
+#endif
     2048,
 };
 
-/*
- * Next-default profile
- */
+/* Next-generation profile. Currently identical to the default, but may
+ * be tightened at any time. */
 const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next =
 {
-    /* Hashes from SHA-256 and above */
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
+    /* Hashes from SHA-256 and above. */
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512),
     0xFFFFFFF, /* Any PK alg    */
 #if defined(MBEDTLS_ECP_C)
-    /* Curves at or above 128-bit security level */
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) |
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) |
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) |
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) |
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) |
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ),
+    /* Curves at or above 128-bit security level. */
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP256R1) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256K1),
 #else
     0,
 #endif
@@ -138,15 +147,15 @@
 const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb =
 {
     /* Only SHA-256 and 384 */
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384),
     /* Only ECDSA */
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) |
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ),
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECDSA) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECKEY),
 #if defined(MBEDTLS_ECP_C)
     /* Only NIST P-256 and P-384 */
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
-    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) |
+    MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1),
 #else
     0,
 #endif
@@ -154,136 +163,150 @@
 };
 
 /*
+ * Empty / all-forbidden profile
+ */
+const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none =
+{
+    0,
+    0,
+    0,
+    (uint32_t) -1,
+};
+
+/*
  * Check md_alg against profile
  * Return 0 if md_alg is acceptable for this profile, -1 otherwise
  */
-static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile,
-                                      mbedtls_md_type_t md_alg )
+static int x509_profile_check_md_alg(const mbedtls_x509_crt_profile *profile,
+                                     mbedtls_md_type_t md_alg)
 {
-    if( md_alg == MBEDTLS_MD_NONE )
-        return( -1 );
+    if (md_alg == MBEDTLS_MD_NONE) {
+        return -1;
+    }
 
-    if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 )
-        return( 0 );
+    if ((profile->allowed_mds & MBEDTLS_X509_ID_FLAG(md_alg)) != 0) {
+        return 0;
+    }
 
-    return( -1 );
+    return -1;
 }
 
 /*
  * Check pk_alg against profile
  * Return 0 if pk_alg is acceptable for this profile, -1 otherwise
  */
-static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile,
-                                      mbedtls_pk_type_t pk_alg )
+static int x509_profile_check_pk_alg(const mbedtls_x509_crt_profile *profile,
+                                     mbedtls_pk_type_t pk_alg)
 {
-    if( pk_alg == MBEDTLS_PK_NONE )
-        return( -1 );
+    if (pk_alg == MBEDTLS_PK_NONE) {
+        return -1;
+    }
 
-    if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 )
-        return( 0 );
+    if ((profile->allowed_pks & MBEDTLS_X509_ID_FLAG(pk_alg)) != 0) {
+        return 0;
+    }
 
-    return( -1 );
+    return -1;
 }
 
 /*
  * Check key against profile
  * Return 0 if pk is acceptable for this profile, -1 otherwise
  */
-static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile,
-                                   const mbedtls_pk_context *pk )
+static int x509_profile_check_key(const mbedtls_x509_crt_profile *profile,
+                                  const mbedtls_pk_context *pk)
 {
-    const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type( pk );
+    const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type(pk);
 
 #if defined(MBEDTLS_RSA_C)
-    if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS )
-    {
-        if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen )
-            return( 0 );
+    if (pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS) {
+        if (mbedtls_pk_get_bitlen(pk) >= profile->rsa_min_bitlen) {
+            return 0;
+        }
 
-        return( -1 );
+        return -1;
     }
 #endif
 
 #if defined(MBEDTLS_ECP_C)
-    if( pk_alg == MBEDTLS_PK_ECDSA ||
+    if (pk_alg == MBEDTLS_PK_ECDSA ||
         pk_alg == MBEDTLS_PK_ECKEY ||
-        pk_alg == MBEDTLS_PK_ECKEY_DH )
-    {
-        const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id;
+        pk_alg == MBEDTLS_PK_ECKEY_DH) {
+        const mbedtls_ecp_group_id gid = mbedtls_pk_ec(*pk)->grp.id;
 
-        if( gid == MBEDTLS_ECP_DP_NONE )
-            return( -1 );
+        if (gid == MBEDTLS_ECP_DP_NONE) {
+            return -1;
+        }
 
-        if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 )
-            return( 0 );
+        if ((profile->allowed_curves & MBEDTLS_X509_ID_FLAG(gid)) != 0) {
+            return 0;
+        }
 
-        return( -1 );
+        return -1;
     }
 #endif
 
-    return( -1 );
+    return -1;
 }
 
 /*
  * Like memcmp, but case-insensitive and always returns -1 if different
  */
-static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
+static int x509_memcasecmp(const void *s1, const void *s2, size_t len)
 {
     size_t i;
     unsigned char diff;
     const unsigned char *n1 = s1, *n2 = s2;
 
-    for( i = 0; i < len; i++ )
-    {
+    for (i = 0; i < len; i++) {
         diff = n1[i] ^ n2[i];
 
-        if( diff == 0 )
-            continue;
-
-        if( diff == 32 &&
-            ( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
-              ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
-        {
+        if (diff == 0) {
             continue;
         }
 
-        return( -1 );
+        if (diff == 32 &&
+            ((n1[i] >= 'a' && n1[i] <= 'z') ||
+             (n1[i] >= 'A' && n1[i] <= 'Z'))) {
+            continue;
+        }
+
+        return -1;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Return 0 if name matches wildcard, -1 otherwise
  */
-static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name )
+static int x509_check_wildcard(const char *cn, const mbedtls_x509_buf *name)
 {
     size_t i;
-    size_t cn_idx = 0, cn_len = strlen( cn );
+    size_t cn_idx = 0, cn_len = strlen(cn);
 
     /* We can't have a match if there is no wildcard to match */
-    if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
-        return( -1 );
+    if (name->len < 3 || name->p[0] != '*' || name->p[1] != '.') {
+        return -1;
+    }
 
-    for( i = 0; i < cn_len; ++i )
-    {
-        if( cn[i] == '.' )
-        {
+    for (i = 0; i < cn_len; ++i) {
+        if (cn[i] == '.') {
             cn_idx = i;
             break;
         }
     }
 
-    if( cn_idx == 0 )
-        return( -1 );
-
-    if( cn_len - cn_idx == name->len - 1 &&
-        x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
-    {
-        return( 0 );
+    if (cn_idx == 0) {
+        return -1;
     }
 
-    return( -1 );
+    if (cn_len - cn_idx == name->len - 1 &&
+        x509_memcasecmp(name->p + 1, cn + cn_idx, name->len - 1) == 0) {
+        return 0;
+    }
+
+    return -1;
 }
 
 /*
@@ -292,24 +315,22 @@
  *
  * Return 0 if equal, -1 otherwise.
  */
-static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
+static int x509_string_cmp(const mbedtls_x509_buf *a, const mbedtls_x509_buf *b)
 {
-    if( a->tag == b->tag &&
+    if (a->tag == b->tag &&
         a->len == b->len &&
-        memcmp( a->p, b->p, b->len ) == 0 )
-    {
-        return( 0 );
+        memcmp(a->p, b->p, b->len) == 0) {
+        return 0;
     }
 
-    if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
-        ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
+    if ((a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING) &&
+        (b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING) &&
         a->len == b->len &&
-        x509_memcasecmp( a->p, b->p, b->len ) == 0 )
-    {
-        return( 0 );
+        x509_memcasecmp(a->p, b->p, b->len) == 0) {
+        return 0;
     }
 
-    return( -1 );
+    return -1;
 }
 
 /*
@@ -322,48 +343,48 @@
  *
  * Return 0 if equal, -1 otherwise.
  */
-static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
+static int x509_name_cmp(const mbedtls_x509_name *a, const mbedtls_x509_name *b)
 {
     /* Avoid recursion, it might not be optimised by the compiler */
-    while( a != NULL || b != NULL )
-    {
-        if( a == NULL || b == NULL )
-            return( -1 );
+    while (a != NULL || b != NULL) {
+        if (a == NULL || b == NULL) {
+            return -1;
+        }
 
         /* type */
-        if( a->oid.tag != b->oid.tag ||
+        if (a->oid.tag != b->oid.tag ||
             a->oid.len != b->oid.len ||
-            memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
-        {
-            return( -1 );
+            memcmp(a->oid.p, b->oid.p, b->oid.len) != 0) {
+            return -1;
         }
 
         /* value */
-        if( x509_string_cmp( &a->val, &b->val ) != 0 )
-            return( -1 );
+        if (x509_string_cmp(&a->val, &b->val) != 0) {
+            return -1;
+        }
 
         /* structure of the list of sets */
-        if( a->next_merged != b->next_merged )
-            return( -1 );
+        if (a->next_merged != b->next_merged) {
+            return -1;
+        }
 
         a = a->next;
         b = b->next;
     }
 
     /* a == NULL == b */
-    return( 0 );
+    return 0;
 }
 
 /*
  * Reset (init or clear) a verify_chain
  */
 static void x509_crt_verify_chain_reset(
-    mbedtls_x509_crt_verify_chain *ver_chain )
+    mbedtls_x509_crt_verify_chain *ver_chain)
 {
     size_t i;
 
-    for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ )
-    {
+    for (i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++) {
         ver_chain->items[i].crt = NULL;
         ver_chain->items[i].flags = (uint32_t) -1;
     }
@@ -378,35 +399,36 @@
 /*
  *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
  */
-static int x509_get_version( unsigned char **p,
-                             const unsigned char *end,
-                             int *ver )
+static int x509_get_version(unsigned char **p,
+                            const unsigned char *end,
+                            int *ver)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-            MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 )
-    {
-        if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-        {
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
+                                    0)) != 0) {
+        if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
             *ver = 0;
-            return( 0 );
+            return 0;
         }
 
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
     }
 
     end = *p + len;
 
-    if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_VERSION, ret ) );
+    if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret);
+    }
 
-    if( *p != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_VERSION,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (*p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -414,66 +436,72 @@
  *       notBefore      Time,
  *       notAfter       Time }
  */
-static int x509_get_dates( unsigned char **p,
-                           const unsigned char *end,
-                           mbedtls_x509_time *from,
-                           mbedtls_x509_time *to )
+static int x509_get_dates(unsigned char **p,
+                          const unsigned char *end,
+                          mbedtls_x509_time *from,
+                          mbedtls_x509_time *to)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret);
+    }
 
     end = *p + len;
 
-    if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_x509_get_time(p, end, from)) != 0) {
+        return ret;
+    }
 
-    if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_x509_get_time(p, end, to)) != 0) {
+        return ret;
+    }
 
-    if( *p != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (*p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * X.509 v2/v3 unique identifier (not parsed)
  */
-static int x509_get_uid( unsigned char **p,
-                         const unsigned char *end,
-                         mbedtls_x509_buf *uid, int n )
+static int x509_get_uid(unsigned char **p,
+                        const unsigned char *end,
+                        mbedtls_x509_buf *uid, int n)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( *p == end )
-        return( 0 );
+    if (*p == end) {
+        return 0;
+    }
 
     uid->tag = **p;
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len,
-            MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 )
-    {
-        if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-            return( 0 );
+    if ((ret = mbedtls_asn1_get_tag(p, end, &uid->len,
+                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
+                                    n)) != 0) {
+        if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
+            return 0;
+        }
 
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
     }
 
     uid->p = *p;
     *p += uid->len;
 
-    return( 0 );
+    return 0;
 }
 
-static int x509_get_basic_constraints( unsigned char **p,
-                                       const unsigned char *end,
-                                       int *ca_istrue,
-                                       int *max_pathlen )
+static int x509_get_basic_constraints(unsigned char **p,
+                                      const unsigned char *end,
+                                      int *ca_istrue,
+                                      int *max_pathlen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
@@ -486,88 +514,52 @@
     *ca_istrue = 0; /* DEFAULT FALSE */
     *max_pathlen = 0; /* endless */
 
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
-
-    if( *p == end )
-        return( 0 );
-
-    if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 )
-    {
-        if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-            ret = mbedtls_asn1_get_int( p, end, ca_istrue );
-
-        if( ret != 0 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
-
-        if( *ca_istrue != 0 )
-            *ca_istrue = 1;
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
     }
 
-    if( *p == end )
-        return( 0 );
+    if (*p == end) {
+        return 0;
+    }
 
-    if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
+    if ((ret = mbedtls_asn1_get_bool(p, end, ca_istrue)) != 0) {
+        if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
+            ret = mbedtls_asn1_get_int(p, end, ca_istrue);
+        }
 
-    if( *p != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+        if (ret != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
+
+        if (*ca_istrue != 0) {
+            *ca_istrue = 1;
+        }
+    }
+
+    if (*p == end) {
+        return 0;
+    }
+
+    if ((ret = mbedtls_asn1_get_int(p, end, max_pathlen)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+    }
+
+    if (*p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
     /* Do not accept max_pathlen equal to INT_MAX to avoid a signed integer
      * overflow, which is an undefined behavior. */
-    if( *max_pathlen == INT_MAX )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_INVALID_LENGTH ) );
+    if (*max_pathlen == INT_MAX) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_INVALID_LENGTH);
+    }
 
     (*max_pathlen)++;
 
-    return( 0 );
-}
-
-static int x509_get_ns_cert_type( unsigned char **p,
-                                       const unsigned char *end,
-                                       unsigned char *ns_cert_type)
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_x509_bitstring bs = { 0, 0, NULL };
-
-    if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
-
-    if( bs.len != 1 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_INVALID_LENGTH ) );
-
-    /* Get actual bitstring */
-    *ns_cert_type = *bs.p;
-    return( 0 );
-}
-
-static int x509_get_key_usage( unsigned char **p,
-                               const unsigned char *end,
-                               unsigned int *key_usage)
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t i;
-    mbedtls_x509_bitstring bs = { 0, 0, NULL };
-
-    if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
-
-    if( bs.len < 1 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_INVALID_LENGTH ) );
-
-    /* Get actual bitstring */
-    *key_usage = 0;
-    for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ )
-    {
-        *key_usage |= (unsigned int) bs.p[i] << (8*i);
-    }
-
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -575,140 +567,23 @@
  *
  * KeyPurposeId ::= OBJECT IDENTIFIER
  */
-static int x509_get_ext_key_usage( unsigned char **p,
-                               const unsigned char *end,
-                               mbedtls_x509_sequence *ext_key_usage)
+static int x509_get_ext_key_usage(unsigned char **p,
+                                  const unsigned char *end,
+                                  mbedtls_x509_sequence *ext_key_usage)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
-
-    /* Sequence length must be >= 1 */
-    if( ext_key_usage->buf.p == NULL )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_INVALID_LENGTH ) );
-
-    return( 0 );
-}
-
-/*
- * SubjectAltName ::= GeneralNames
- *
- * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
- *
- * GeneralName ::= CHOICE {
- *      otherName                       [0]     OtherName,
- *      rfc822Name                      [1]     IA5String,
- *      dNSName                         [2]     IA5String,
- *      x400Address                     [3]     ORAddress,
- *      directoryName                   [4]     Name,
- *      ediPartyName                    [5]     EDIPartyName,
- *      uniformResourceIdentifier       [6]     IA5String,
- *      iPAddress                       [7]     OCTET STRING,
- *      registeredID                    [8]     OBJECT IDENTIFIER }
- *
- * OtherName ::= SEQUENCE {
- *      type-id    OBJECT IDENTIFIER,
- *      value      [0] EXPLICIT ANY DEFINED BY type-id }
- *
- * EDIPartyName ::= SEQUENCE {
- *      nameAssigner            [0]     DirectoryString OPTIONAL,
- *      partyName               [1]     DirectoryString }
- *
- * NOTE: we list all types, but only use dNSName and otherName
- * of type HwModuleName, as defined in RFC 4108, at this point.
- */
-static int x509_get_subject_alt_name( unsigned char **p,
-                                      const unsigned char *end,
-                                      mbedtls_x509_sequence *subject_alt_name )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t len, tag_len;
-    mbedtls_asn1_buf *buf;
-    unsigned char tag;
-    mbedtls_asn1_sequence *cur = subject_alt_name;
-
-    /* Get main sequence tag */
-    if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
-
-    if( *p + len != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
-
-    while( *p < end )
-    {
-        mbedtls_x509_subject_alternative_name dummy_san_buf;
-        memset( &dummy_san_buf, 0, sizeof( dummy_san_buf ) );
-
-        tag = **p;
-        (*p)++;
-        if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
-
-        if( ( tag & MBEDTLS_ASN1_TAG_CLASS_MASK ) !=
-                MBEDTLS_ASN1_CONTEXT_SPECIFIC )
-        {
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                    MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
-        }
-
-        /*
-         * Check that the SAN is structured correctly.
-         */
-        ret = mbedtls_x509_parse_subject_alt_name( &(cur->buf), &dummy_san_buf );
-        /*
-         * In case the extension is malformed, return an error,
-         * and clear the allocated sequences.
-         */
-        if( ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
-        {
-            mbedtls_x509_sequence *seq_cur = subject_alt_name->next;
-            mbedtls_x509_sequence *seq_prv;
-            while( seq_cur != NULL )
-            {
-                seq_prv = seq_cur;
-                seq_cur = seq_cur->next;
-                mbedtls_platform_zeroize( seq_prv,
-                                          sizeof( mbedtls_x509_sequence ) );
-                mbedtls_free( seq_prv );
-            }
-            subject_alt_name->next = NULL;
-            return( ret );
-        }
-
-        /* Allocate and assign next pointer */
-        if( cur->buf.p != NULL )
-        {
-            if( cur->next != NULL )
-                return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
-
-            cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
-
-            if( cur->next == NULL )
-                return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                        MBEDTLS_ERR_ASN1_ALLOC_FAILED ) );
-
-            cur = cur->next;
-        }
-
-        buf = &(cur->buf);
-        buf->tag = tag;
-        buf->p = *p;
-        buf->len = tag_len;
-        *p += buf->len;
+    if ((ret = mbedtls_asn1_get_sequence_of(p, end, ext_key_usage, MBEDTLS_ASN1_OID)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
     }
 
-    /* Set final sequence entry's next pointer to NULL */
-    cur->next = NULL;
+    /* Sequence length must be >= 1 */
+    if (ext_key_usage->buf.p == NULL) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_INVALID_LENGTH);
+    }
 
-    if( *p != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
-
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -760,9 +635,9 @@
  * NOTE: we only parse and use anyPolicy without qualifiers at this point
  * as defined in RFC 5280.
  */
-static int x509_get_certificate_policies( unsigned char **p,
-                                          const unsigned char *end,
-                                          mbedtls_x509_sequence *certificate_policies )
+static int x509_get_certificate_policies(unsigned char **p,
+                                         const unsigned char *end,
+                                         mbedtls_x509_sequence *certificate_policies)
 {
     int ret, parse_ret = 0;
     size_t len;
@@ -770,39 +645,43 @@
     mbedtls_asn1_sequence *cur = certificate_policies;
 
     /* Get main sequence tag */
-    ret = mbedtls_asn1_get_tag( p, end, &len,
-                             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
-    if( ret != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
+    ret = mbedtls_asn1_get_tag(p, end, &len,
+                               MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+    if (ret != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+    }
 
-    if( *p + len != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (*p + len != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
     /*
      * Cannot be an empty sequence.
      */
-    if( len == 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (len == 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
-    while( *p < end )
-    {
+    while (*p < end) {
         mbedtls_x509_buf policy_oid;
         const unsigned char *policy_end;
 
         /*
          * Get the policy sequence
          */
-        if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
+        if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
 
         policy_end = *p + len;
 
-        if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len,
-                                          MBEDTLS_ASN1_OID ) ) != 0 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
+        if ((ret = mbedtls_asn1_get_tag(p, policy_end, &len,
+                                        MBEDTLS_ASN1_OID)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
 
         policy_oid.tag = MBEDTLS_ASN1_OID;
         policy_oid.len = len;
@@ -811,146 +690,153 @@
         /*
          * Only AnyPolicy is currently supported when enforcing policy.
          */
-        if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_POLICY, &policy_oid ) != 0 )
-        {
+        if (MBEDTLS_OID_CMP(MBEDTLS_OID_ANY_POLICY, &policy_oid) != 0) {
             /*
              * Set the parsing return code but continue parsing, in case this
-             * extension is critical and MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
-             * is configured.
+             * extension is critical.
              */
             parse_ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
         }
 
         /* Allocate and assign next pointer */
-        if( cur->buf.p != NULL )
-        {
-            if( cur->next != NULL )
-                return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
+        if (cur->buf.p != NULL) {
+            if (cur->next != NULL) {
+                return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
+            }
 
-            cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
+            cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
 
-            if( cur->next == NULL )
-                return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                        MBEDTLS_ERR_ASN1_ALLOC_FAILED ) );
+            if (cur->next == NULL) {
+                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                         MBEDTLS_ERR_ASN1_ALLOC_FAILED);
+            }
 
             cur = cur->next;
         }
 
-        buf = &( cur->buf );
+        buf = &(cur->buf);
         buf->tag = policy_oid.tag;
         buf->p = policy_oid.p;
         buf->len = policy_oid.len;
 
         *p += len;
 
-       /*
-        * If there is an optional qualifier, then *p < policy_end
-        * Check the Qualifier len to verify it doesn't exceed policy_end.
-        */
-        if( *p < policy_end )
-        {
-            if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len,
-                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-                return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
+        /*
+         * If there is an optional qualifier, then *p < policy_end
+         * Check the Qualifier len to verify it doesn't exceed policy_end.
+         */
+        if (*p < policy_end) {
+            if ((ret = mbedtls_asn1_get_tag(p, policy_end, &len,
+                                            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) !=
+                0) {
+                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+            }
             /*
              * Skip the optional policy qualifiers.
              */
             *p += len;
         }
 
-        if( *p != policy_end )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+        if (*p != policy_end) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+        }
     }
 
     /* Set final sequence entry's next pointer to NULL */
     cur->next = NULL;
 
-    if( *p != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (*p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
-    return( parse_ret );
+    return parse_ret;
 }
 
 /*
  * X.509 v3 extensions
  *
  */
-static int x509_get_crt_ext( unsigned char **p,
-                             const unsigned char *end,
-                             mbedtls_x509_crt *crt,
-                             mbedtls_x509_crt_ext_cb_t cb,
-                             void *p_ctx )
+static int x509_get_crt_ext(unsigned char **p,
+                            const unsigned char *end,
+                            mbedtls_x509_crt *crt,
+                            mbedtls_x509_crt_ext_cb_t cb,
+                            void *p_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
     unsigned char *end_ext_data, *start_ext_octet, *end_ext_octet;
 
-    if( *p == end )
-        return( 0 );
+    if (*p == end) {
+        return 0;
+    }
 
-    if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_x509_get_ext(p, end, &crt->v3_ext, 3)) != 0) {
+        return ret;
+    }
 
     end = crt->v3_ext.p + crt->v3_ext.len;
-    while( *p < end )
-    {
+    while (*p < end) {
         /*
          * Extension  ::=  SEQUENCE  {
          *      extnID      OBJECT IDENTIFIER,
          *      critical    BOOLEAN DEFAULT FALSE,
          *      extnValue   OCTET STRING  }
          */
-        mbedtls_x509_buf extn_oid = {0, 0, NULL};
+        mbedtls_x509_buf extn_oid = { 0, 0, NULL };
         int is_critical = 0; /* DEFAULT FALSE */
         int ext_type = 0;
 
-        if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
-                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
+        if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
 
         end_ext_data = *p + len;
 
         /* Get extension ID */
-        if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len,
-                                          MBEDTLS_ASN1_OID ) ) != 0 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
+        if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len,
+                                        MBEDTLS_ASN1_OID)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
 
         extn_oid.tag = MBEDTLS_ASN1_OID;
         extn_oid.p = *p;
         *p += extn_oid.len;
 
         /* Get optional critical */
-        if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
-            ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
+        if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 &&
+            (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
 
         /* Data should be octet string type */
-        if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len,
-                MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
+        if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len,
+                                        MBEDTLS_ASN1_OCTET_STRING)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
 
         start_ext_octet = *p;
         end_ext_octet = *p + len;
 
-        if( end_ext_octet != end_ext_data )
-            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+        if (end_ext_octet != end_ext_data) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+        }
 
         /*
          * Detect supported extensions
          */
-        ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type );
+        ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type);
 
-        if( ret != 0 )
-        {
+        if (ret != 0) {
             /* Give the callback (if any) a chance to handle the extension */
-            if( cb != NULL )
-            {
-                ret = cb( p_ctx, crt, &extn_oid, is_critical, *p, end_ext_octet );
-                if( ret != 0 && is_critical )
-                    return( ret );
+            if (cb != NULL) {
+                ret = cb(p_ctx, crt, &extn_oid, is_critical, *p, end_ext_octet);
+                if (ret != 0 && is_critical) {
+                    return ret;
+                }
                 *p = end_ext_octet;
                 continue;
             }
@@ -958,137 +844,139 @@
             /* No parser found, skip extension */
             *p = end_ext_octet;
 
-#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
-            if( is_critical )
-            {
+            if (is_critical) {
                 /* Data is marked as critical: fail */
-                return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                        MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
+                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                         MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
             }
-#endif
             continue;
         }
 
         /* Forbid repeated extensions */
-        if( ( crt->ext_types & ext_type ) != 0 )
-            return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
+        if ((crt->ext_types & ext_type) != 0) {
+            return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
+        }
 
         crt->ext_types |= ext_type;
 
-        switch( ext_type )
-        {
-        case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS:
-            /* Parse basic constraints */
-            if( ( ret = x509_get_basic_constraints( p, end_ext_octet,
-                    &crt->ca_istrue, &crt->max_pathlen ) ) != 0 )
-                return( ret );
-            break;
+        switch (ext_type) {
+            case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS:
+                /* Parse basic constraints */
+                if ((ret = x509_get_basic_constraints(p, end_ext_octet,
+                                                      &crt->ca_istrue, &crt->max_pathlen)) != 0) {
+                    return ret;
+                }
+                break;
 
-        case MBEDTLS_X509_EXT_KEY_USAGE:
-            /* Parse key usage */
-            if( ( ret = x509_get_key_usage( p, end_ext_octet,
-                    &crt->key_usage ) ) != 0 )
-                return( ret );
-            break;
+            case MBEDTLS_X509_EXT_KEY_USAGE:
+                /* Parse key usage */
+                if ((ret = mbedtls_x509_get_key_usage(p, end_ext_octet,
+                                                      &crt->key_usage)) != 0) {
+                    return ret;
+                }
+                break;
 
-        case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE:
-            /* Parse extended key usage */
-            if( ( ret = x509_get_ext_key_usage( p, end_ext_octet,
-                    &crt->ext_key_usage ) ) != 0 )
-                return( ret );
-            break;
+            case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE:
+                /* Parse extended key usage */
+                if ((ret = x509_get_ext_key_usage(p, end_ext_octet,
+                                                  &crt->ext_key_usage)) != 0) {
+                    return ret;
+                }
+                break;
 
-        case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
-            /* Parse subject alt name */
-            if( ( ret = x509_get_subject_alt_name( p, end_ext_octet,
-                    &crt->subject_alt_names ) ) != 0 )
-                return( ret );
-            break;
+            case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
+                /* Parse subject alt name */
+                if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_octet,
+                                                             &crt->subject_alt_names)) != 0) {
+                    return ret;
+                }
+                break;
 
-        case MBEDTLS_X509_EXT_NS_CERT_TYPE:
-            /* Parse netscape certificate type */
-            if( ( ret = x509_get_ns_cert_type( p, end_ext_octet,
-                    &crt->ns_cert_type ) ) != 0 )
-                return( ret );
-            break;
+            case MBEDTLS_X509_EXT_NS_CERT_TYPE:
+                /* Parse netscape certificate type */
+                if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_octet,
+                                                         &crt->ns_cert_type)) != 0) {
+                    return ret;
+                }
+                break;
 
-        case MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES:
-            /* Parse certificate policies type */
-            if( ( ret = x509_get_certificate_policies( p, end_ext_octet,
-                    &crt->certificate_policies ) ) != 0 )
-            {
-                /* Give the callback (if any) a chance to handle the extension
-                 * if it contains unsupported policies */
-                if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE && cb != NULL &&
-                    cb( p_ctx, crt, &extn_oid, is_critical,
-                        start_ext_octet, end_ext_octet ) == 0 )
-                    break;
+            case MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES:
+                /* Parse certificate policies type */
+                if ((ret = x509_get_certificate_policies(p, end_ext_octet,
+                                                         &crt->certificate_policies)) != 0) {
+                    /* Give the callback (if any) a chance to handle the extension
+                     * if it contains unsupported policies */
+                    if (ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE && cb != NULL &&
+                        cb(p_ctx, crt, &extn_oid, is_critical,
+                           start_ext_octet, end_ext_octet) == 0) {
+                        break;
+                    }
 
-#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
-                if( is_critical )
-                    return( ret );
-                else
-#endif
+                    if (is_critical) {
+                        return ret;
+                    } else
+                    /*
+                     * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, then we
+                     * cannot interpret or enforce the policy. However, it is up to
+                     * the user to choose how to enforce the policies,
+                     * unless the extension is critical.
+                     */
+                    if (ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
+                        return ret;
+                    }
+                }
+                break;
+
+            default:
                 /*
-                 * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, then we
-                 * cannot interpret or enforce the policy. However, it is up to
-                 * the user to choose how to enforce the policies,
-                 * unless the extension is critical.
+                 * If this is a non-critical extension, which the oid layer
+                 * supports, but there isn't an x509 parser for it,
+                 * skip the extension.
                  */
-                if( ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
-                    return( ret );
-            }
-            break;
-
-        default:
-            /*
-             * If this is a non-critical extension, which the oid layer
-             * supports, but there isn't an x509 parser for it,
-             * skip the extension.
-             */
-#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
-            if( is_critical )
-                return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
-            else
-#endif
-                *p = end_ext_octet;
+                if (is_critical) {
+                    return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
+                } else {
+                    *p = end_ext_octet;
+                }
         }
     }
 
-    if( *p != end )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (*p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Parse and fill a single X.509 certificate in DER format
  */
-static int x509_crt_parse_der_core( mbedtls_x509_crt *crt,
-                                    const unsigned char *buf,
-                                    size_t buflen,
-                                    int make_copy,
-                                    mbedtls_x509_crt_ext_cb_t cb,
-                                    void *p_ctx )
+static int x509_crt_parse_der_core(mbedtls_x509_crt *crt,
+                                   const unsigned char *buf,
+                                   size_t buflen,
+                                   int make_copy,
+                                   mbedtls_x509_crt_ext_cb_t cb,
+                                   void *p_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
     unsigned char *p, *end, *crt_end;
     mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;
 
-    memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) );
-    memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) );
-    memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) );
+    memset(&sig_params1, 0, sizeof(mbedtls_x509_buf));
+    memset(&sig_params2, 0, sizeof(mbedtls_x509_buf));
+    memset(&sig_oid2, 0, sizeof(mbedtls_x509_buf));
 
     /*
      * Check for valid input
      */
-    if( crt == NULL || buf == NULL )
-        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+    if (crt == NULL || buf == NULL) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
 
     /* Use the original buffer until we figure out actual length. */
-    p = (unsigned char*) buf;
+    p = (unsigned char *) buf;
     len = buflen;
     end = p + len;
 
@@ -1098,31 +986,28 @@
      *      signatureAlgorithm   AlgorithmIdentifier,
      *      signatureValue       BIT STRING  }
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        mbedtls_x509_crt_free(crt);
+        return MBEDTLS_ERR_X509_INVALID_FORMAT;
     }
 
     end = crt_end = p + len;
     crt->raw.len = crt_end - buf;
-    if( make_copy != 0 )
-    {
+    if (make_copy != 0) {
         /* Create and populate a new buffer for the raw field. */
-        crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len );
-        if( crt->raw.p == NULL )
-            return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+        crt->raw.p = p = mbedtls_calloc(1, crt->raw.len);
+        if (crt->raw.p == NULL) {
+            return MBEDTLS_ERR_X509_ALLOC_FAILED;
+        }
 
-        memcpy( crt->raw.p, buf, crt->raw.len );
+        memcpy(crt->raw.p, buf, crt->raw.len);
         crt->own_buffer = 1;
 
         p += crt->raw.len - len;
         end = crt_end = p + len;
-    }
-    else
-    {
-        crt->raw.p = (unsigned char*) buf;
+    } else {
+        crt->raw.p = (unsigned char *) buf;
         crt->own_buffer = 0;
     }
 
@@ -1131,11 +1016,10 @@
      */
     crt->tbs.p = p;
 
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        mbedtls_x509_crt_free(crt);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
     }
 
     end = p + len;
@@ -1148,29 +1032,26 @@
      *
      * signature            AlgorithmIdentifier
      */
-    if( ( ret = x509_get_version(  &p, end, &crt->version  ) ) != 0 ||
-        ( ret = mbedtls_x509_get_serial(   &p, end, &crt->serial   ) ) != 0 ||
-        ( ret = mbedtls_x509_get_alg(      &p, end, &crt->sig_oid,
-                                            &sig_params1 ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( ret );
+    if ((ret = x509_get_version(&p, end, &crt->version)) != 0 ||
+        (ret = mbedtls_x509_get_serial(&p, end, &crt->serial)) != 0 ||
+        (ret = mbedtls_x509_get_alg(&p, end, &crt->sig_oid,
+                                    &sig_params1)) != 0) {
+        mbedtls_x509_crt_free(crt);
+        return ret;
     }
 
-    if( crt->version < 0 || crt->version > 2 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
+    if (crt->version < 0 || crt->version > 2) {
+        mbedtls_x509_crt_free(crt);
+        return MBEDTLS_ERR_X509_UNKNOWN_VERSION;
     }
 
     crt->version++;
 
-    if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1,
-                                  &crt->sig_md, &crt->sig_pk,
-                                  &crt->sig_opts ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( ret );
+    if ((ret = mbedtls_x509_get_sig_alg(&crt->sig_oid, &sig_params1,
+                                        &crt->sig_md, &crt->sig_pk,
+                                        &crt->sig_opts)) != 0) {
+        mbedtls_x509_crt_free(crt);
+        return ret;
     }
 
     /*
@@ -1178,17 +1059,15 @@
      */
     crt->issuer_raw.p = p;
 
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        mbedtls_x509_crt_free(crt);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
     }
 
-    if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( ret );
+    if ((ret = mbedtls_x509_get_name(&p, p + len, &crt->issuer)) != 0) {
+        mbedtls_x509_crt_free(crt);
+        return ret;
     }
 
     crt->issuer_raw.len = p - crt->issuer_raw.p;
@@ -1199,11 +1078,10 @@
      *      notAfter       Time }
      *
      */
-    if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
-                                         &crt->valid_to ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( ret );
+    if ((ret = x509_get_dates(&p, end, &crt->valid_from,
+                              &crt->valid_to)) != 0) {
+        mbedtls_x509_crt_free(crt);
+        return ret;
     }
 
     /*
@@ -1211,17 +1089,15 @@
      */
     crt->subject_raw.p = p;
 
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        mbedtls_x509_crt_free(crt);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
     }
 
-    if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( ret );
+    if (len && (ret = mbedtls_x509_get_name(&p, p + len, &crt->subject)) != 0) {
+        mbedtls_x509_crt_free(crt);
+        return ret;
     }
 
     crt->subject_raw.len = p - crt->subject_raw.p;
@@ -1230,10 +1106,9 @@
      * SubjectPublicKeyInfo
      */
     crt->pk_raw.p = p;
-    if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( ret );
+    if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &crt->pk)) != 0) {
+        mbedtls_x509_crt_free(crt);
+        return ret;
     }
     crt->pk_raw.len = p - crt->pk_raw.p;
 
@@ -1245,43 +1120,34 @@
      *  extensions      [3]  EXPLICIT Extensions OPTIONAL
      *                       -- If present, version shall be v3
      */
-    if( crt->version == 2 || crt->version == 3 )
-    {
-        ret = x509_get_uid( &p, end, &crt->issuer_id,  1 );
-        if( ret != 0 )
-        {
-            mbedtls_x509_crt_free( crt );
-            return( ret );
+    if (crt->version == 2 || crt->version == 3) {
+        ret = x509_get_uid(&p, end, &crt->issuer_id,  1);
+        if (ret != 0) {
+            mbedtls_x509_crt_free(crt);
+            return ret;
         }
     }
 
-    if( crt->version == 2 || crt->version == 3 )
-    {
-        ret = x509_get_uid( &p, end, &crt->subject_id,  2 );
-        if( ret != 0 )
-        {
-            mbedtls_x509_crt_free( crt );
-            return( ret );
+    if (crt->version == 2 || crt->version == 3) {
+        ret = x509_get_uid(&p, end, &crt->subject_id,  2);
+        if (ret != 0) {
+            mbedtls_x509_crt_free(crt);
+            return ret;
         }
     }
 
-#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3)
-    if( crt->version == 3 )
-#endif
-    {
-        ret = x509_get_crt_ext( &p, end, crt, cb, p_ctx );
-        if( ret != 0 )
-        {
-            mbedtls_x509_crt_free( crt );
-            return( ret );
+    if (crt->version == 3) {
+        ret = x509_get_crt_ext(&p, end, crt, cb, p_ctx);
+        if (ret != 0) {
+            mbedtls_x509_crt_free(crt);
+            return ret;
         }
     }
 
-    if( p != end )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (p != end) {
+        mbedtls_x509_crt_free(crt);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
     }
 
     end = crt_end;
@@ -1293,49 +1159,45 @@
      *  signatureAlgorithm   AlgorithmIdentifier,
      *  signatureValue       BIT STRING
      */
-    if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( ret );
+    if ((ret = mbedtls_x509_get_alg(&p, end, &sig_oid2, &sig_params2)) != 0) {
+        mbedtls_x509_crt_free(crt);
+        return ret;
     }
 
-    if( crt->sig_oid.len != sig_oid2.len ||
-        memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 ||
+    if (crt->sig_oid.len != sig_oid2.len ||
+        memcmp(crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len) != 0 ||
         sig_params1.tag != sig_params2.tag ||
         sig_params1.len != sig_params2.len ||
-        ( sig_params1.len != 0 &&
-          memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERR_X509_SIG_MISMATCH );
+        (sig_params1.len != 0 &&
+         memcmp(sig_params1.p, sig_params2.p, sig_params1.len) != 0)) {
+        mbedtls_x509_crt_free(crt);
+        return MBEDTLS_ERR_X509_SIG_MISMATCH;
     }
 
-    if( ( ret = mbedtls_x509_get_sig( &p, end, &crt->sig ) ) != 0 )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( ret );
+    if ((ret = mbedtls_x509_get_sig(&p, end, &crt->sig)) != 0) {
+        mbedtls_x509_crt_free(crt);
+        return ret;
     }
 
-    if( p != end )
-    {
-        mbedtls_x509_crt_free( crt );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (p != end) {
+        mbedtls_x509_crt_free(crt);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Parse one X.509 certificate in DER format from a buffer and add them to a
  * chained list
  */
-static int mbedtls_x509_crt_parse_der_internal( mbedtls_x509_crt *chain,
-                                                const unsigned char *buf,
-                                                size_t buflen,
-                                                int make_copy,
-                                                mbedtls_x509_crt_ext_cb_t cb,
-                                                void *p_ctx )
+static int mbedtls_x509_crt_parse_der_internal(mbedtls_x509_crt *chain,
+                                               const unsigned char *buf,
+                                               size_t buflen,
+                                               int make_copy,
+                                               mbedtls_x509_crt_ext_cb_t cb,
+                                               void *p_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_x509_crt *crt = chain, *prev = NULL;
@@ -1343,11 +1205,11 @@
     /*
      * Check for valid input
      */
-    if( crt == NULL || buf == NULL )
-        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+    if (crt == NULL || buf == NULL) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
 
-    while( crt->version != 0 && crt->next != NULL )
-    {
+    while (crt->version != 0 && crt->next != NULL) {
         prev = crt;
         crt = crt->next;
     }
@@ -1355,64 +1217,65 @@
     /*
      * Add new certificate on the end of the chain if needed.
      */
-    if( crt->version != 0 && crt->next == NULL )
-    {
-        crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
+    if (crt->version != 0 && crt->next == NULL) {
+        crt->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crt));
 
-        if( crt->next == NULL )
-            return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+        if (crt->next == NULL) {
+            return MBEDTLS_ERR_X509_ALLOC_FAILED;
+        }
 
         prev = crt;
-        mbedtls_x509_crt_init( crt->next );
+        mbedtls_x509_crt_init(crt->next);
         crt = crt->next;
     }
 
-    ret = x509_crt_parse_der_core( crt, buf, buflen, make_copy, cb, p_ctx );
-    if( ret != 0 )
-    {
-        if( prev )
+    ret = x509_crt_parse_der_core(crt, buf, buflen, make_copy, cb, p_ctx);
+    if (ret != 0) {
+        if (prev) {
             prev->next = NULL;
+        }
 
-        if( crt != chain )
-            mbedtls_free( crt );
+        if (crt != chain) {
+            mbedtls_free(crt);
+        }
 
-        return( ret );
+        return ret;
     }
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_x509_crt_parse_der_nocopy( mbedtls_x509_crt *chain,
-                                       const unsigned char *buf,
-                                       size_t buflen )
+int mbedtls_x509_crt_parse_der_nocopy(mbedtls_x509_crt *chain,
+                                      const unsigned char *buf,
+                                      size_t buflen)
 {
-    return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 0, NULL, NULL ) );
+    return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, 0, NULL, NULL);
 }
 
-int mbedtls_x509_crt_parse_der_with_ext_cb( mbedtls_x509_crt *chain,
-                                            const unsigned char *buf,
-                                            size_t buflen,
-                                            int make_copy,
-                                            mbedtls_x509_crt_ext_cb_t cb,
-                                            void *p_ctx )
+int mbedtls_x509_crt_parse_der_with_ext_cb(mbedtls_x509_crt *chain,
+                                           const unsigned char *buf,
+                                           size_t buflen,
+                                           int make_copy,
+                                           mbedtls_x509_crt_ext_cb_t cb,
+                                           void *p_ctx)
 {
-    return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, make_copy, cb, p_ctx ) );
+    return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, make_copy, cb, p_ctx);
 }
 
-int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain,
-                                const unsigned char *buf,
-                                size_t buflen )
+int mbedtls_x509_crt_parse_der(mbedtls_x509_crt *chain,
+                               const unsigned char *buf,
+                               size_t buflen)
 {
-    return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 1, NULL, NULL ) );
+    return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, 1, NULL, NULL);
 }
 
 /*
  * Parse one or more PEM certificates from a buffer and add them to the chained
  * list
  */
-int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain,
-                            const unsigned char *buf,
-                            size_t buflen )
+int mbedtls_x509_crt_parse(mbedtls_x509_crt *chain,
+                           const unsigned char *buf,
+                           size_t buflen)
 {
 #if defined(MBEDTLS_PEM_PARSE_C)
     int success = 0, first_error = 0, total_failed = 0;
@@ -1422,59 +1285,53 @@
     /*
      * Check for valid input
      */
-    if( chain == NULL || buf == NULL )
-        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+    if (chain == NULL || buf == NULL) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
 
     /*
      * Determine buffer content. Buffer contains either one DER certificate or
      * one or more PEM certificates.
      */
 #if defined(MBEDTLS_PEM_PARSE_C)
-    if( buflen != 0 && buf[buflen - 1] == '\0' &&
-        strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
-    {
+    if (buflen != 0 && buf[buflen - 1] == '\0' &&
+        strstr((const char *) buf, "-----BEGIN CERTIFICATE-----") != NULL) {
         buf_format = MBEDTLS_X509_FORMAT_PEM;
     }
 
-    if( buf_format == MBEDTLS_X509_FORMAT_DER )
-        return mbedtls_x509_crt_parse_der( chain, buf, buflen );
+    if (buf_format == MBEDTLS_X509_FORMAT_DER) {
+        return mbedtls_x509_crt_parse_der(chain, buf, buflen);
+    }
 #else
-    return mbedtls_x509_crt_parse_der( chain, buf, buflen );
+    return mbedtls_x509_crt_parse_der(chain, buf, buflen);
 #endif
 
 #if defined(MBEDTLS_PEM_PARSE_C)
-    if( buf_format == MBEDTLS_X509_FORMAT_PEM )
-    {
+    if (buf_format == MBEDTLS_X509_FORMAT_PEM) {
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         mbedtls_pem_context pem;
 
         /* 1 rather than 0 since the terminating NULL byte is counted in */
-        while( buflen > 1 )
-        {
+        while (buflen > 1) {
             size_t use_len;
-            mbedtls_pem_init( &pem );
+            mbedtls_pem_init(&pem);
 
             /* If we get there, we know the string is null-terminated */
-            ret = mbedtls_pem_read_buffer( &pem,
-                           "-----BEGIN CERTIFICATE-----",
-                           "-----END CERTIFICATE-----",
-                           buf, NULL, 0, &use_len );
+            ret = mbedtls_pem_read_buffer(&pem,
+                                          "-----BEGIN CERTIFICATE-----",
+                                          "-----END CERTIFICATE-----",
+                                          buf, NULL, 0, &use_len);
 
-            if( ret == 0 )
-            {
+            if (ret == 0) {
                 /*
                  * Was PEM encoded
                  */
                 buflen -= use_len;
                 buf += use_len;
-            }
-            else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA )
-            {
-                return( ret );
-            }
-            else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-            {
-                mbedtls_pem_free( &pem );
+            } else if (ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA) {
+                return ret;
+            } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
+                mbedtls_pem_free(&pem);
 
                 /*
                  * PEM header and footer were found
@@ -1482,29 +1339,31 @@
                 buflen -= use_len;
                 buf += use_len;
 
-                if( first_error == 0 )
+                if (first_error == 0) {
                     first_error = ret;
+                }
 
                 total_failed++;
                 continue;
-            }
-            else
+            } else {
                 break;
+            }
 
-            ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen );
+            ret = mbedtls_x509_crt_parse_der(chain, pem.buf, pem.buflen);
 
-            mbedtls_pem_free( &pem );
+            mbedtls_pem_free(&pem);
 
-            if( ret != 0 )
-            {
+            if (ret != 0) {
                 /*
                  * Quit parsing on a memory error
                  */
-                if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED )
-                    return( ret );
+                if (ret == MBEDTLS_ERR_X509_ALLOC_FAILED) {
+                    return ret;
+                }
 
-                if( first_error == 0 )
+                if (first_error == 0) {
                     first_error = ret;
+                }
 
                 total_failed++;
                 continue;
@@ -1514,12 +1373,13 @@
         }
     }
 
-    if( success )
-        return( total_failed );
-    else if( first_error )
-        return( first_error );
-    else
-        return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT );
+    if (success) {
+        return total_failed;
+    } else if (first_error) {
+        return first_error;
+    } else {
+        return MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT;
+    }
 #endif /* MBEDTLS_PEM_PARSE_C */
 }
 
@@ -1527,24 +1387,25 @@
 /*
  * Load one or more certificates and add them to the chained list
  */
-int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path )
+int mbedtls_x509_crt_parse_file(mbedtls_x509_crt *chain, const char *path)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
     unsigned char *buf;
 
-    if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
+        return ret;
+    }
 
-    ret = mbedtls_x509_crt_parse( chain, buf, n );
+    ret = mbedtls_x509_crt_parse(chain, buf, n);
 
-    mbedtls_platform_zeroize( buf, n );
-    mbedtls_free( buf );
+    mbedtls_platform_zeroize(buf, n);
+    mbedtls_free(buf);
 
-    return( ret );
+    return ret;
 }
 
-int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
+int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path)
 {
     int ret = 0;
 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
@@ -1552,445 +1413,140 @@
     WCHAR szDir[MAX_PATH];
     char filename[MAX_PATH];
     char *p;
-    size_t len = strlen( path );
+    size_t len = strlen(path);
 
     WIN32_FIND_DATAW file_data;
     HANDLE hFind;
 
-    if( len > MAX_PATH - 3 )
-        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+    if (len > MAX_PATH - 3) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
 
-    memset( szDir, 0, sizeof(szDir) );
-    memset( filename, 0, MAX_PATH );
-    memcpy( filename, path, len );
+    memset(szDir, 0, sizeof(szDir));
+    memset(filename, 0, MAX_PATH);
+    memcpy(filename, path, len);
     filename[len++] = '\\';
     p = filename + len;
     filename[len++] = '*';
 
-    w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir,
-                                 MAX_PATH - 3 );
-    if( w_ret == 0 )
-        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+    w_ret = MultiByteToWideChar(CP_ACP, 0, filename, (int) len, szDir,
+                                MAX_PATH - 3);
+    if (w_ret == 0) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
 
-    hFind = FindFirstFileW( szDir, &file_data );
-    if( hFind == INVALID_HANDLE_VALUE )
-        return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
+    hFind = FindFirstFileW(szDir, &file_data);
+    if (hFind == INVALID_HANDLE_VALUE) {
+        return MBEDTLS_ERR_X509_FILE_IO_ERROR;
+    }
 
     len = MAX_PATH - len;
-    do
-    {
-        memset( p, 0, len );
+    do {
+        memset(p, 0, len);
 
-        if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
+        if (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
             continue;
+        }
 
-        w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
-                                     lstrlenW( file_data.cFileName ),
-                                     p, (int) len - 1,
-                                     NULL, NULL );
-        if( w_ret == 0 )
-        {
+        w_ret = WideCharToMultiByte(CP_ACP, 0, file_data.cFileName,
+                                    -1,
+                                    p, (int) len,
+                                    NULL, NULL);
+        if (w_ret == 0) {
             ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
             goto cleanup;
         }
 
-        w_ret = mbedtls_x509_crt_parse_file( chain, filename );
-        if( w_ret < 0 )
+        w_ret = mbedtls_x509_crt_parse_file(chain, filename);
+        if (w_ret < 0) {
             ret++;
-        else
+        } else {
             ret += w_ret;
-    }
-    while( FindNextFileW( hFind, &file_data ) != 0 );
+        }
+    } while (FindNextFileW(hFind, &file_data) != 0);
 
-    if( GetLastError() != ERROR_NO_MORE_FILES )
+    if (GetLastError() != ERROR_NO_MORE_FILES) {
         ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
+    }
 
 cleanup:
-    FindClose( hFind );
+    FindClose(hFind);
 #else /* _WIN32 */
     int t_ret;
     int snp_ret;
     struct stat sb;
     struct dirent *entry;
     char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN];
-    DIR *dir = opendir( path );
+    DIR *dir = opendir(path);
 
-    if( dir == NULL )
-        return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
+    if (dir == NULL) {
+        return MBEDTLS_ERR_X509_FILE_IO_ERROR;
+    }
 
 #if defined(MBEDTLS_THREADING_C)
-    if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 )
-    {
-        closedir( dir );
-        return( ret );
+    if ((ret = mbedtls_mutex_lock(&mbedtls_threading_readdir_mutex)) != 0) {
+        closedir(dir);
+        return ret;
     }
 #endif /* MBEDTLS_THREADING_C */
 
-    memset( &sb, 0, sizeof( sb ) );
+    memset(&sb, 0, sizeof(sb));
 
-    while( ( entry = readdir( dir ) ) != NULL )
-    {
-        snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name,
-                                    "%s/%s", path, entry->d_name );
+    while ((entry = readdir(dir)) != NULL) {
+        snp_ret = mbedtls_snprintf(entry_name, sizeof(entry_name),
+                                   "%s/%s", path, entry->d_name);
 
-        if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name )
-        {
+        if (snp_ret < 0 || (size_t) snp_ret >= sizeof(entry_name)) {
             ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
             goto cleanup;
-        }
-        else if( stat( entry_name, &sb ) == -1 )
-        {
-            ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
-            goto cleanup;
+        } else if (stat(entry_name, &sb) == -1) {
+            if (errno == ENOENT) {
+                /* Broken symbolic link - ignore this entry.
+                    stat(2) will return this error for either (a) a dangling
+                    symlink or (b) a missing file.
+                    Given that we have just obtained the filename from readdir,
+                    assume that it does exist and therefore treat this as a
+                    dangling symlink. */
+                continue;
+            } else {
+                /* Some other file error; report the error. */
+                ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
+                goto cleanup;
+            }
         }
 
-        if( !S_ISREG( sb.st_mode ) )
+        if (!S_ISREG(sb.st_mode)) {
             continue;
+        }
 
         // Ignore parse errors
         //
-        t_ret = mbedtls_x509_crt_parse_file( chain, entry_name );
-        if( t_ret < 0 )
+        t_ret = mbedtls_x509_crt_parse_file(chain, entry_name);
+        if (t_ret < 0) {
             ret++;
-        else
+        } else {
             ret += t_ret;
+        }
     }
 
 cleanup:
-    closedir( dir );
+    closedir(dir);
 
 #if defined(MBEDTLS_THREADING_C)
-    if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 )
+    if (mbedtls_mutex_unlock(&mbedtls_threading_readdir_mutex) != 0) {
         ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
+    }
 #endif /* MBEDTLS_THREADING_C */
 
 #endif /* _WIN32 */
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_FS_IO */
 
-/*
- * OtherName ::= SEQUENCE {
- *      type-id    OBJECT IDENTIFIER,
- *      value      [0] EXPLICIT ANY DEFINED BY type-id }
- *
- * HardwareModuleName ::= SEQUENCE {
- *                           hwType OBJECT IDENTIFIER,
- *                           hwSerialNum OCTET STRING }
- *
- * NOTE: we currently only parse and use otherName of type HwModuleName,
- * as defined in RFC 4108.
- */
-static int x509_get_other_name( const mbedtls_x509_buf *subject_alt_name,
-                                mbedtls_x509_san_other_name *other_name )
-{
-    int ret = 0;
-    size_t len;
-    unsigned char *p = subject_alt_name->p;
-    const unsigned char *end = p + subject_alt_name->len;
-    mbedtls_x509_buf cur_oid;
-
-    if( ( subject_alt_name->tag &
-        ( MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK ) ) !=
-        ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ) )
-    {
-        /*
-         * The given subject alternative name is not of type "othername".
-         */
-        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
-    }
-
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-                                      MBEDTLS_ASN1_OID ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
-
-    cur_oid.tag = MBEDTLS_ASN1_OID;
-    cur_oid.p = p;
-    cur_oid.len = len;
-
-    /*
-     * Only HwModuleName is currently supported.
-     */
-    if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid ) != 0 )
-    {
-        return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
-    }
-
-    if( p + len >= end )
-    {
-        mbedtls_platform_zeroize( other_name, sizeof( *other_name ) );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
-    }
-    p += len;
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
-
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-       return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
-
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OID ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
-
-    other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID;
-    other_name->value.hardware_module_name.oid.p = p;
-    other_name->value.hardware_module_name.oid.len = len;
-
-    if( p + len >= end )
-    {
-        mbedtls_platform_zeroize( other_name, sizeof( *other_name ) );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
-    }
-    p += len;
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-                                      MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) );
-
-    other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;
-    other_name->value.hardware_module_name.val.p = p;
-    other_name->value.hardware_module_name.val.len = len;
-    p += len;
-    if( p != end )
-    {
-        mbedtls_platform_zeroize( other_name,
-                                  sizeof( *other_name ) );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
-    }
-    return( 0 );
-}
-
-static int x509_info_subject_alt_name( char **buf, size_t *size,
-                                       const mbedtls_x509_sequence
-                                                    *subject_alt_name,
-                                       const char *prefix )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t n = *size;
-    char *p = *buf;
-    const mbedtls_x509_sequence *cur = subject_alt_name;
-    mbedtls_x509_subject_alternative_name san;
-    int parse_ret;
-
-    while( cur != NULL )
-    {
-        memset( &san, 0, sizeof( san ) );
-        parse_ret = mbedtls_x509_parse_subject_alt_name( &cur->buf, &san );
-        if( parse_ret != 0 )
-        {
-            if( parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
-            {
-                ret = mbedtls_snprintf( p, n, "\n%s    <unsupported>", prefix );
-                MBEDTLS_X509_SAFE_SNPRINTF;
-            }
-            else
-            {
-                ret = mbedtls_snprintf( p, n, "\n%s    <malformed>", prefix );
-                MBEDTLS_X509_SAFE_SNPRINTF;
-            }
-            cur = cur->next;
-            continue;
-        }
-
-        switch( san.type )
-        {
-            /*
-             * otherName
-             */
-            case MBEDTLS_X509_SAN_OTHER_NAME:
-            {
-                mbedtls_x509_san_other_name *other_name = &san.san.other_name;
-
-                ret = mbedtls_snprintf( p, n, "\n%s    otherName :", prefix );
-                MBEDTLS_X509_SAFE_SNPRINTF;
-
-                if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME,
-                                     &other_name->value.hardware_module_name.oid ) != 0 )
-                {
-                    ret = mbedtls_snprintf( p, n, "\n%s        hardware module name :", prefix );
-                    MBEDTLS_X509_SAFE_SNPRINTF;
-                    ret = mbedtls_snprintf( p, n, "\n%s            hardware type          : ", prefix );
-                    MBEDTLS_X509_SAFE_SNPRINTF;
-
-                    ret = mbedtls_oid_get_numeric_string( p, n, &other_name->value.hardware_module_name.oid );
-                    MBEDTLS_X509_SAFE_SNPRINTF;
-
-                    ret = mbedtls_snprintf( p, n, "\n%s            hardware serial number : ", prefix );
-                    MBEDTLS_X509_SAFE_SNPRINTF;
-
-                    if( other_name->value.hardware_module_name.val.len >= n )
-                    {
-                        *p = '\0';
-                        return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
-                    }
-
-                    memcpy( p, other_name->value.hardware_module_name.val.p,
-                            other_name->value.hardware_module_name.val.len );
-                    p += other_name->value.hardware_module_name.val.len;
-
-                    n -= other_name->value.hardware_module_name.val.len;
-
-                }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
-            }
-            break;
-
-            /*
-             * dNSName
-             */
-            case MBEDTLS_X509_SAN_DNS_NAME:
-            {
-                ret = mbedtls_snprintf( p, n, "\n%s    dNSName : ", prefix );
-                MBEDTLS_X509_SAFE_SNPRINTF;
-                if( san.san.unstructured_name.len >= n )
-                {
-                    *p = '\0';
-                    return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
-                }
-
-                memcpy( p, san.san.unstructured_name.p, san.san.unstructured_name.len );
-                p += san.san.unstructured_name.len;
-                n -= san.san.unstructured_name.len;
-            }
-            break;
-
-            /*
-             * Type not supported, skip item.
-             */
-            default:
-                ret = mbedtls_snprintf( p, n, "\n%s    <unsupported>", prefix );
-                MBEDTLS_X509_SAFE_SNPRINTF;
-                break;
-        }
-
-        cur = cur->next;
-    }
-
-    *p = '\0';
-
-    *size = n;
-    *buf = p;
-
-    return( 0 );
-}
-
-int mbedtls_x509_parse_subject_alt_name( const mbedtls_x509_buf *san_buf,
-                                         mbedtls_x509_subject_alternative_name *san )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    switch( san_buf->tag &
-            ( MBEDTLS_ASN1_TAG_CLASS_MASK |
-              MBEDTLS_ASN1_TAG_VALUE_MASK ) )
-    {
-        /*
-         * otherName
-         */
-        case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ):
-        {
-            mbedtls_x509_san_other_name other_name;
-
-            ret = x509_get_other_name( san_buf, &other_name );
-            if( ret != 0 )
-                return( ret );
-
-            memset( san, 0, sizeof( mbedtls_x509_subject_alternative_name ) );
-            san->type = MBEDTLS_X509_SAN_OTHER_NAME;
-            memcpy( &san->san.other_name,
-                    &other_name, sizeof( other_name ) );
-
-        }
-        break;
-
-        /*
-         * dNSName
-         */
-        case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME ):
-        {
-            memset( san, 0, sizeof( mbedtls_x509_subject_alternative_name ) );
-            san->type = MBEDTLS_X509_SAN_DNS_NAME;
-
-            memcpy( &san->san.unstructured_name,
-                    san_buf, sizeof( *san_buf ) );
-
-        }
-        break;
-
-        /*
-         * Type not supported
-         */
-        default:
-            return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
-    }
-    return( 0 );
-}
-
-#define PRINT_ITEM(i)                           \
-    {                                           \
-        ret = mbedtls_snprintf( p, n, "%s" i, sep );    \
-        MBEDTLS_X509_SAFE_SNPRINTF;                        \
-        sep = ", ";                             \
-    }
-
-#define CERT_TYPE(type,name)                    \
-    if( ns_cert_type & (type) )                 \
-        PRINT_ITEM( name );
-
-static int x509_info_cert_type( char **buf, size_t *size,
-                                unsigned char ns_cert_type )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t n = *size;
-    char *p = *buf;
-    const char *sep = "";
-
-    CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT,         "SSL Client" );
-    CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER,         "SSL Server" );
-    CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL,              "Email" );
-    CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING,     "Object Signing" );
-    CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED,           "Reserved" );
-    CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA,             "SSL CA" );
-    CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA,           "Email CA" );
-    CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA,  "Object Signing CA" );
-
-    *size = n;
-    *buf = p;
-
-    return( 0 );
-}
-
-#define KEY_USAGE(code,name)    \
-    if( key_usage & (code) )    \
-        PRINT_ITEM( name );
-
-static int x509_info_key_usage( char **buf, size_t *size,
-                                unsigned int key_usage )
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t n = *size;
-    char *p = *buf;
-    const char *sep = "";
-
-    KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE,    "Digital Signature" );
-    KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION,      "Non Repudiation" );
-    KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT,     "Key Encipherment" );
-    KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT,    "Data Encipherment" );
-    KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT,        "Key Agreement" );
-    KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN,        "Key Cert Sign" );
-    KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN,             "CRL Sign" );
-    KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY,        "Encipher Only" );
-    KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY,        "Decipher Only" );
-
-    *size = n;
-    *buf = p;
-
-    return( 0 );
-}
-
-static int x509_info_ext_key_usage( char **buf, size_t *size,
-                                    const mbedtls_x509_sequence *extended_key_usage )
+#if !defined(MBEDTLS_X509_REMOVE_INFO)
+static int x509_info_ext_key_usage(char **buf, size_t *size,
+                                   const mbedtls_x509_sequence *extended_key_usage)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const char *desc;
@@ -1999,12 +1555,12 @@
     const mbedtls_x509_sequence *cur = extended_key_usage;
     const char *sep = "";
 
-    while( cur != NULL )
-    {
-        if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 )
+    while (cur != NULL) {
+        if (mbedtls_oid_get_extended_key_usage(&cur->buf, &desc) != 0) {
             desc = "???";
+        }
 
-        ret = mbedtls_snprintf( p, n, "%s%s", sep, desc );
+        ret = mbedtls_snprintf(p, n, "%s%s", sep, desc);
         MBEDTLS_X509_SAFE_SNPRINTF;
 
         sep = ", ";
@@ -2015,11 +1571,11 @@
     *size = n;
     *buf = p;
 
-    return( 0 );
+    return 0;
 }
 
-static int x509_info_cert_policies( char **buf, size_t *size,
-                                    const mbedtls_x509_sequence *certificate_policies )
+static int x509_info_cert_policies(char **buf, size_t *size,
+                                   const mbedtls_x509_sequence *certificate_policies)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const char *desc;
@@ -2028,12 +1584,12 @@
     const mbedtls_x509_sequence *cur = certificate_policies;
     const char *sep = "";
 
-    while( cur != NULL )
-    {
-        if( mbedtls_oid_get_certificate_policies( &cur->buf, &desc ) != 0 )
+    while (cur != NULL) {
+        if (mbedtls_oid_get_certificate_policies(&cur->buf, &desc) != 0) {
             desc = "???";
+        }
 
-        ret = mbedtls_snprintf( p, n, "%s%s", sep, desc );
+        ret = mbedtls_snprintf(p, n, "%s%s", sep, desc);
         MBEDTLS_X509_SAFE_SNPRINTF;
 
         sep = ", ";
@@ -2044,7 +1600,7 @@
     *size = n;
     *buf = p;
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -2052,8 +1608,8 @@
  */
 #define BEFORE_COLON    18
 #define BC              "18"
-int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
-                   const mbedtls_x509_crt *crt )
+int mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix,
+                          const mbedtls_x509_crt *crt)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
@@ -2063,136 +1619,132 @@
     p = buf;
     n = size;
 
-    if( NULL == crt )
-    {
-        ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" );
+    if (NULL == crt) {
+        ret = mbedtls_snprintf(p, n, "\nCertificate is uninitialised!\n");
         MBEDTLS_X509_SAFE_SNPRINTF;
 
-        return( (int) ( size - n ) );
+        return (int) (size - n);
     }
 
-    ret = mbedtls_snprintf( p, n, "%scert. version     : %d\n",
-                               prefix, crt->version );
+    ret = mbedtls_snprintf(p, n, "%scert. version     : %d\n",
+                           prefix, crt->version);
     MBEDTLS_X509_SAFE_SNPRINTF;
-    ret = mbedtls_snprintf( p, n, "%sserial number     : ",
-                               prefix );
+    ret = mbedtls_snprintf(p, n, "%sserial number     : ",
+                           prefix);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    ret = mbedtls_x509_serial_gets( p, n, &crt->serial );
+    ret = mbedtls_x509_serial_gets(p, n, &crt->serial);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    ret = mbedtls_snprintf( p, n, "\n%sissuer name       : ", prefix );
+    ret = mbedtls_snprintf(p, n, "\n%sissuer name       : ", prefix);
     MBEDTLS_X509_SAFE_SNPRINTF;
-    ret = mbedtls_x509_dn_gets( p, n, &crt->issuer  );
+    ret = mbedtls_x509_dn_gets(p, n, &crt->issuer);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    ret = mbedtls_snprintf( p, n, "\n%ssubject name      : ", prefix );
+    ret = mbedtls_snprintf(p, n, "\n%ssubject name      : ", prefix);
     MBEDTLS_X509_SAFE_SNPRINTF;
-    ret = mbedtls_x509_dn_gets( p, n, &crt->subject );
+    ret = mbedtls_x509_dn_gets(p, n, &crt->subject);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    ret = mbedtls_snprintf( p, n, "\n%sissued  on        : " \
-                   "%04d-%02d-%02d %02d:%02d:%02d", prefix,
-                   crt->valid_from.year, crt->valid_from.mon,
-                   crt->valid_from.day,  crt->valid_from.hour,
-                   crt->valid_from.min,  crt->valid_from.sec );
+    ret = mbedtls_snprintf(p, n, "\n%sissued  on        : " \
+                                 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
+                           crt->valid_from.year, crt->valid_from.mon,
+                           crt->valid_from.day,  crt->valid_from.hour,
+                           crt->valid_from.min,  crt->valid_from.sec);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    ret = mbedtls_snprintf( p, n, "\n%sexpires on        : " \
-                   "%04d-%02d-%02d %02d:%02d:%02d", prefix,
-                   crt->valid_to.year, crt->valid_to.mon,
-                   crt->valid_to.day,  crt->valid_to.hour,
-                   crt->valid_to.min,  crt->valid_to.sec );
+    ret = mbedtls_snprintf(p, n, "\n%sexpires on        : " \
+                                 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
+                           crt->valid_to.year, crt->valid_to.mon,
+                           crt->valid_to.day,  crt->valid_to.hour,
+                           crt->valid_to.min,  crt->valid_to.sec);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    ret = mbedtls_snprintf( p, n, "\n%ssigned using      : ", prefix );
+    ret = mbedtls_snprintf(p, n, "\n%ssigned using      : ", prefix);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    ret = mbedtls_x509_sig_alg_gets( p, n, &crt->sig_oid, crt->sig_pk,
-                             crt->sig_md, crt->sig_opts );
+    ret = mbedtls_x509_sig_alg_gets(p, n, &crt->sig_oid, crt->sig_pk,
+                                    crt->sig_md, crt->sig_opts);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
     /* Key size */
-    if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON,
-                                      mbedtls_pk_get_name( &crt->pk ) ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_x509_key_size_helper(key_size_str, BEFORE_COLON,
+                                            mbedtls_pk_get_name(&crt->pk))) != 0) {
+        return ret;
     }
 
-    ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str,
-                          (int) mbedtls_pk_get_bitlen( &crt->pk ) );
+    ret = mbedtls_snprintf(p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str,
+                           (int) mbedtls_pk_get_bitlen(&crt->pk));
     MBEDTLS_X509_SAFE_SNPRINTF;
 
     /*
      * Optional extensions
      */
 
-    if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS )
-    {
-        ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix,
-                        crt->ca_istrue ? "true" : "false" );
+    if (crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS) {
+        ret = mbedtls_snprintf(p, n, "\n%sbasic constraints : CA=%s", prefix,
+                               crt->ca_istrue ? "true" : "false");
         MBEDTLS_X509_SAFE_SNPRINTF;
 
-        if( crt->max_pathlen > 0 )
-        {
-            ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 );
+        if (crt->max_pathlen > 0) {
+            ret = mbedtls_snprintf(p, n, ", max_pathlen=%d", crt->max_pathlen - 1);
             MBEDTLS_X509_SAFE_SNPRINTF;
         }
     }
 
-    if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
-    {
-        ret = mbedtls_snprintf( p, n, "\n%ssubject alt name  :", prefix );
+    if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
+        ret = mbedtls_snprintf(p, n, "\n%ssubject alt name  :", prefix);
         MBEDTLS_X509_SAFE_SNPRINTF;
 
-        if( ( ret = x509_info_subject_alt_name( &p, &n,
-                                                &crt->subject_alt_names,
-                                                prefix ) ) != 0 )
-            return( ret );
+        if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n,
+                                                      &crt->subject_alt_names,
+                                                      prefix)) != 0) {
+            return ret;
+        }
     }
 
-    if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE )
-    {
-        ret = mbedtls_snprintf( p, n, "\n%scert. type        : ", prefix );
+    if (crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) {
+        ret = mbedtls_snprintf(p, n, "\n%scert. type        : ", prefix);
         MBEDTLS_X509_SAFE_SNPRINTF;
 
-        if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 )
-            return( ret );
+        if ((ret = mbedtls_x509_info_cert_type(&p, &n, crt->ns_cert_type)) != 0) {
+            return ret;
+        }
     }
 
-    if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE )
-    {
-        ret = mbedtls_snprintf( p, n, "\n%skey usage         : ", prefix );
+    if (crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) {
+        ret = mbedtls_snprintf(p, n, "\n%skey usage         : ", prefix);
         MBEDTLS_X509_SAFE_SNPRINTF;
 
-        if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 )
-            return( ret );
+        if ((ret = mbedtls_x509_info_key_usage(&p, &n, crt->key_usage)) != 0) {
+            return ret;
+        }
     }
 
-    if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE )
-    {
-        ret = mbedtls_snprintf( p, n, "\n%sext key usage     : ", prefix );
+    if (crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) {
+        ret = mbedtls_snprintf(p, n, "\n%sext key usage     : ", prefix);
         MBEDTLS_X509_SAFE_SNPRINTF;
 
-        if( ( ret = x509_info_ext_key_usage( &p, &n,
-                                             &crt->ext_key_usage ) ) != 0 )
-            return( ret );
+        if ((ret = x509_info_ext_key_usage(&p, &n,
+                                           &crt->ext_key_usage)) != 0) {
+            return ret;
+        }
     }
 
-    if( crt->ext_types & MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES )
-    {
-        ret = mbedtls_snprintf( p, n, "\n%scertificate policies : ", prefix );
+    if (crt->ext_types & MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES) {
+        ret = mbedtls_snprintf(p, n, "\n%scertificate policies : ", prefix);
         MBEDTLS_X509_SAFE_SNPRINTF;
 
-        if( ( ret = x509_info_cert_policies( &p, &n,
-                                             &crt->certificate_policies ) ) != 0 )
-            return( ret );
+        if ((ret = x509_info_cert_policies(&p, &n,
+                                           &crt->certificate_policies)) != 0) {
+            return ret;
+        }
     }
 
-    ret = mbedtls_snprintf( p, n, "\n" );
+    ret = mbedtls_snprintf(p, n, "\n");
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    return( (int) ( size - n ) );
+    return (int) (size - n);
 }
 
 struct x509_crt_verify_string {
@@ -2200,157 +1752,141 @@
     const char *string;
 };
 
+#define X509_CRT_ERROR_INFO(err, err_str, info) { err, info },
 static const struct x509_crt_verify_string x509_crt_verify_strings[] = {
-    { MBEDTLS_X509_BADCERT_EXPIRED,       "The certificate validity has expired" },
-    { MBEDTLS_X509_BADCERT_REVOKED,       "The certificate has been revoked (is on a CRL)" },
-    { MBEDTLS_X509_BADCERT_CN_MISMATCH,   "The certificate Common Name (CN) does not match with the expected CN" },
-    { MBEDTLS_X509_BADCERT_NOT_TRUSTED,   "The certificate is not correctly signed by the trusted CA" },
-    { MBEDTLS_X509_BADCRL_NOT_TRUSTED,    "The CRL is not correctly signed by the trusted CA" },
-    { MBEDTLS_X509_BADCRL_EXPIRED,        "The CRL is expired" },
-    { MBEDTLS_X509_BADCERT_MISSING,       "Certificate was missing" },
-    { MBEDTLS_X509_BADCERT_SKIP_VERIFY,   "Certificate verification was skipped" },
-    { MBEDTLS_X509_BADCERT_OTHER,         "Other reason (can be used by verify callback)" },
-    { MBEDTLS_X509_BADCERT_FUTURE,        "The certificate validity starts in the future" },
-    { MBEDTLS_X509_BADCRL_FUTURE,         "The CRL is from the future" },
-    { MBEDTLS_X509_BADCERT_KEY_USAGE,     "Usage does not match the keyUsage extension" },
-    { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" },
-    { MBEDTLS_X509_BADCERT_NS_CERT_TYPE,  "Usage does not match the nsCertType extension" },
-    { MBEDTLS_X509_BADCERT_BAD_MD,        "The certificate is signed with an unacceptable hash." },
-    { MBEDTLS_X509_BADCERT_BAD_PK,        "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
-    { MBEDTLS_X509_BADCERT_BAD_KEY,       "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." },
-    { MBEDTLS_X509_BADCRL_BAD_MD,         "The CRL is signed with an unacceptable hash." },
-    { MBEDTLS_X509_BADCRL_BAD_PK,         "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
-    { MBEDTLS_X509_BADCRL_BAD_KEY,        "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." },
+    MBEDTLS_X509_CRT_ERROR_INFO_LIST
     { 0, NULL }
 };
+#undef X509_CRT_ERROR_INFO
 
-int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
-                          uint32_t flags )
+int mbedtls_x509_crt_verify_info(char *buf, size_t size, const char *prefix,
+                                 uint32_t flags)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const struct x509_crt_verify_string *cur;
     char *p = buf;
     size_t n = size;
 
-    for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ )
-    {
-        if( ( flags & cur->code ) == 0 )
+    for (cur = x509_crt_verify_strings; cur->string != NULL; cur++) {
+        if ((flags & cur->code) == 0) {
             continue;
+        }
 
-        ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string );
+        ret = mbedtls_snprintf(p, n, "%s%s\n", prefix, cur->string);
         MBEDTLS_X509_SAFE_SNPRINTF;
         flags ^= cur->code;
     }
 
-    if( flags != 0 )
-    {
-        ret = mbedtls_snprintf( p, n, "%sUnknown reason "
-                                       "(this should not happen)\n", prefix );
+    if (flags != 0) {
+        ret = mbedtls_snprintf(p, n, "%sUnknown reason "
+                                     "(this should not happen)\n", prefix);
         MBEDTLS_X509_SAFE_SNPRINTF;
     }
 
-    return( (int) ( size - n ) );
+    return (int) (size - n);
 }
+#endif /* MBEDTLS_X509_REMOVE_INFO */
 
-#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
-int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt,
-                                      unsigned int usage )
+int mbedtls_x509_crt_check_key_usage(const mbedtls_x509_crt *crt,
+                                     unsigned int usage)
 {
     unsigned int usage_must, usage_may;
     unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY
-                          | MBEDTLS_X509_KU_DECIPHER_ONLY;
+                            | MBEDTLS_X509_KU_DECIPHER_ONLY;
 
-    if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 )
-        return( 0 );
+    if ((crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) == 0) {
+        return 0;
+    }
 
     usage_must = usage & ~may_mask;
 
-    if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must )
-        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+    if (((crt->key_usage & ~may_mask) & usage_must) != usage_must) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
 
     usage_may = usage & may_mask;
 
-    if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may )
-        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+    if (((crt->key_usage & may_mask) | usage_may) != usage_may) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
 
-    return( 0 );
+    return 0;
 }
-#endif
 
-#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
-int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt,
-                                       const char *usage_oid,
-                                       size_t usage_len )
+int mbedtls_x509_crt_check_extended_key_usage(const mbedtls_x509_crt *crt,
+                                              const char *usage_oid,
+                                              size_t usage_len)
 {
     const mbedtls_x509_sequence *cur;
 
     /* Extension is not mandatory, absent means no restriction */
-    if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 )
-        return( 0 );
+    if ((crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) == 0) {
+        return 0;
+    }
 
     /*
      * Look for the requested usage (or wildcard ANY) in our list
      */
-    for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next )
-    {
+    for (cur = &crt->ext_key_usage; cur != NULL; cur = cur->next) {
         const mbedtls_x509_buf *cur_oid = &cur->buf;
 
-        if( cur_oid->len == usage_len &&
-            memcmp( cur_oid->p, usage_oid, usage_len ) == 0 )
-        {
-            return( 0 );
+        if (cur_oid->len == usage_len &&
+            memcmp(cur_oid->p, usage_oid, usage_len) == 0) {
+            return 0;
         }
 
-        if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 )
-            return( 0 );
+        if (MBEDTLS_OID_CMP(MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid) == 0) {
+            return 0;
+        }
     }
 
-    return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+    return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
 }
-#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */
 
 #if defined(MBEDTLS_X509_CRL_PARSE_C)
 /*
  * Return 1 if the certificate is revoked, or 0 otherwise.
  */
-int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl )
+int mbedtls_x509_crt_is_revoked(const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl)
 {
     const mbedtls_x509_crl_entry *cur = &crl->entry;
 
-    while( cur != NULL && cur->serial.len != 0 )
-    {
-        if( crt->serial.len == cur->serial.len &&
-            memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
-        {
-            return( 1 );
+    while (cur != NULL && cur->serial.len != 0) {
+        if (crt->serial.len == cur->serial.len &&
+            memcmp(crt->serial.p, cur->serial.p, crt->serial.len) == 0) {
+            return 1;
         }
 
         cur = cur->next;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Check that the given certificate is not revoked according to the CRL.
  * Skip validation if no CRL for the given CA is present.
  */
-static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
-                               mbedtls_x509_crl *crl_list,
-                               const mbedtls_x509_crt_profile *profile )
+static int x509_crt_verifycrl(mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
+                              mbedtls_x509_crl *crl_list,
+                              const mbedtls_x509_crt_profile *profile)
 {
     int flags = 0;
-    unsigned char hash[MBEDTLS_MD_MAX_SIZE];
+    unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_algorithm_t psa_algorithm;
+#else
     const mbedtls_md_info_t *md_info;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    size_t hash_length;
 
-    if( ca == NULL )
-        return( flags );
+    if (ca == NULL) {
+        return flags;
+    }
 
-    while( crl_list != NULL )
-    {
-        if( crl_list->version == 0 ||
-            x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 )
-        {
+    while (crl_list != NULL) {
+        if (crl_list->version == 0 ||
+            x509_name_cmp(&crl_list->issuer, &ca->subject) != 0) {
             crl_list = crl_list->next;
             continue;
         }
@@ -2358,39 +1894,55 @@
         /*
          * Check if the CA is configured to sign CRLs
          */
-#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
-        if( mbedtls_x509_crt_check_key_usage( ca,
-                                              MBEDTLS_X509_KU_CRL_SIGN ) != 0 )
-        {
+        if (mbedtls_x509_crt_check_key_usage(ca,
+                                             MBEDTLS_X509_KU_CRL_SIGN) != 0) {
             flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
             break;
         }
-#endif
 
         /*
          * Check if CRL is correctly signed by the trusted CA
          */
-        if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 )
+        if (x509_profile_check_md_alg(profile, crl_list->sig_md) != 0) {
             flags |= MBEDTLS_X509_BADCRL_BAD_MD;
+        }
 
-        if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 )
+        if (x509_profile_check_pk_alg(profile, crl_list->sig_pk) != 0) {
             flags |= MBEDTLS_X509_BADCRL_BAD_PK;
+        }
 
-        md_info = mbedtls_md_info_from_type( crl_list->sig_md );
-        if( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 )
-        {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        psa_algorithm = mbedtls_hash_info_psa_from_md(crl_list->sig_md);
+        if (psa_hash_compute(psa_algorithm,
+                             crl_list->tbs.p,
+                             crl_list->tbs.len,
+                             hash,
+                             sizeof(hash),
+                             &hash_length) != PSA_SUCCESS) {
             /* Note: this can't happen except after an internal error */
             flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
             break;
         }
+#else
+        md_info = mbedtls_md_info_from_type(crl_list->sig_md);
+        hash_length = mbedtls_md_get_size(md_info);
+        if (mbedtls_md(md_info,
+                       crl_list->tbs.p,
+                       crl_list->tbs.len,
+                       hash) != 0) {
+            /* Note: this can't happen except after an internal error */
+            flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
+            break;
+        }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-        if( x509_profile_check_key( profile, &ca->pk ) != 0 )
+        if (x509_profile_check_key(profile, &ca->pk) != 0) {
             flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
+        }
 
-        if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk,
-                           crl_list->sig_md, hash, mbedtls_md_get_size( md_info ),
-                           crl_list->sig.p, crl_list->sig.len ) != 0 )
-        {
+        if (mbedtls_pk_verify_ext(crl_list->sig_pk, crl_list->sig_opts, &ca->pk,
+                                  crl_list->sig_md, hash, hash_length,
+                                  crl_list->sig.p, crl_list->sig.len) != 0) {
             flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
             break;
         }
@@ -2398,17 +1950,18 @@
         /*
          * Check for validity of CRL (Do not drop out)
          */
-        if( mbedtls_x509_time_is_past( &crl_list->next_update ) )
+        if (mbedtls_x509_time_is_past(&crl_list->next_update)) {
             flags |= MBEDTLS_X509_BADCRL_EXPIRED;
+        }
 
-        if( mbedtls_x509_time_is_future( &crl_list->this_update ) )
+        if (mbedtls_x509_time_is_future(&crl_list->this_update)) {
             flags |= MBEDTLS_X509_BADCRL_FUTURE;
+        }
 
         /*
          * Check if certificate is revoked
          */
-        if( mbedtls_x509_crt_is_revoked( crt, crl_list ) )
-        {
+        if (mbedtls_x509_crt_is_revoked(crt, crl_list)) {
             flags |= MBEDTLS_X509_BADCERT_REVOKED;
             break;
         }
@@ -2416,64 +1969,61 @@
         crl_list = crl_list->next;
     }
 
-    return( flags );
+    return flags;
 }
 #endif /* MBEDTLS_X509_CRL_PARSE_C */
 
 /*
  * Check the signature of a certificate by its parent
  */
-static int x509_crt_check_signature( const mbedtls_x509_crt *child,
-                                     mbedtls_x509_crt *parent,
-                                     mbedtls_x509_crt_restart_ctx *rs_ctx )
+static int x509_crt_check_signature(const mbedtls_x509_crt *child,
+                                    mbedtls_x509_crt *parent,
+                                    mbedtls_x509_crt_restart_ctx *rs_ctx)
 {
-    unsigned char hash[MBEDTLS_MD_MAX_SIZE];
     size_t hash_len;
+    unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
 #if !defined(MBEDTLS_USE_PSA_CRYPTO)
     const mbedtls_md_info_t *md_info;
-    md_info = mbedtls_md_info_from_type( child->sig_md );
-    hash_len = mbedtls_md_get_size( md_info );
+    md_info = mbedtls_md_info_from_type(child->sig_md);
+    hash_len = mbedtls_md_get_size(md_info);
 
     /* Note: hash errors can happen only after an internal error */
-    if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 )
-        return( -1 );
+    if (mbedtls_md(md_info, child->tbs.p, child->tbs.len, hash) != 0) {
+        return -1;
+    }
 #else
-    psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT;
-    psa_algorithm_t hash_alg = mbedtls_psa_translate_md( child->sig_md );
+    psa_algorithm_t hash_alg = mbedtls_hash_info_psa_from_md(child->sig_md);
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 
-    if( psa_hash_setup( &hash_operation, hash_alg ) != PSA_SUCCESS )
-        return( -1 );
-
-    if( psa_hash_update( &hash_operation, child->tbs.p, child->tbs.len )
-        != PSA_SUCCESS )
-    {
-        return( -1 );
+    status = psa_hash_compute(hash_alg,
+                              child->tbs.p,
+                              child->tbs.len,
+                              hash,
+                              sizeof(hash),
+                              &hash_len);
+    if (status != PSA_SUCCESS) {
+        return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
     }
 
-    if( psa_hash_finish( &hash_operation, hash, sizeof( hash ), &hash_len )
-        != PSA_SUCCESS )
-    {
-        return( -1 );
-    }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
     /* Skip expensive computation on obvious mismatch */
-    if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) )
-        return( -1 );
+    if (!mbedtls_pk_can_do(&parent->pk, child->sig_pk)) {
+        return -1;
+    }
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA )
-    {
-        return( mbedtls_pk_verify_restartable( &parent->pk,
-                    child->sig_md, hash, hash_len,
-                    child->sig.p, child->sig.len, &rs_ctx->pk ) );
+    if (rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA) {
+        return mbedtls_pk_verify_restartable(&parent->pk,
+                                             child->sig_md, hash, hash_len,
+                                             child->sig.p, child->sig.len, &rs_ctx->pk);
     }
 #else
     (void) rs_ctx;
 #endif
 
-    return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
-                child->sig_md, hash, hash_len,
-                child->sig.p, child->sig.len ) );
+    return mbedtls_pk_verify_ext(child->sig_pk, child->sig_opts, &parent->pk,
+                                 child->sig_md, hash, hash_len,
+                                 child->sig.p, child->sig.len);
 }
 
 /*
@@ -2482,35 +2032,35 @@
  *
  * top means parent is a locally-trusted certificate
  */
-static int x509_crt_check_parent( const mbedtls_x509_crt *child,
-                                  const mbedtls_x509_crt *parent,
-                                  int top )
+static int x509_crt_check_parent(const mbedtls_x509_crt *child,
+                                 const mbedtls_x509_crt *parent,
+                                 int top)
 {
     int need_ca_bit;
 
     /* Parent must be the issuer */
-    if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 )
-        return( -1 );
+    if (x509_name_cmp(&child->issuer, &parent->subject) != 0) {
+        return -1;
+    }
 
     /* Parent must have the basicConstraints CA bit set as a general rule */
     need_ca_bit = 1;
 
     /* Exception: v1/v2 certificates that are locally trusted. */
-    if( top && parent->version < 3 )
+    if (top && parent->version < 3) {
         need_ca_bit = 0;
-
-    if( need_ca_bit && ! parent->ca_istrue )
-        return( -1 );
-
-#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
-    if( need_ca_bit &&
-        mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 )
-    {
-        return( -1 );
     }
-#endif
 
-    return( 0 );
+    if (need_ca_bit && !parent->ca_istrue) {
+        return -1;
+    }
+
+    if (need_ca_bit &&
+        mbedtls_x509_crt_check_key_usage(parent, MBEDTLS_X509_KU_KEY_CERT_SIGN) != 0) {
+        return -1;
+    }
+
+    return 0;
 }
 
 /*
@@ -2557,14 +2107,14 @@
  *  - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
  */
 static int x509_crt_find_parent_in(
-                        mbedtls_x509_crt *child,
-                        mbedtls_x509_crt *candidates,
-                        mbedtls_x509_crt **r_parent,
-                        int *r_signature_is_good,
-                        int top,
-                        unsigned path_cnt,
-                        unsigned self_cnt,
-                        mbedtls_x509_crt_restart_ctx *rs_ctx )
+    mbedtls_x509_crt *child,
+    mbedtls_x509_crt *candidates,
+    mbedtls_x509_crt **r_parent,
+    int *r_signature_is_good,
+    int top,
+    unsigned path_cnt,
+    unsigned self_cnt,
+    mbedtls_x509_crt_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_x509_crt *parent, *fallback_parent;
@@ -2572,8 +2122,7 @@
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
     /* did we have something in progress? */
-    if( rs_ctx != NULL && rs_ctx->parent != NULL )
-    {
+    if (rs_ctx != NULL && rs_ctx->parent != NULL) {
         /* restore saved state */
         parent = rs_ctx->parent;
         fallback_parent = rs_ctx->fallback_parent;
@@ -2592,16 +2141,15 @@
     fallback_parent = NULL;
     fallback_signature_is_good = 0;
 
-    for( parent = candidates; parent != NULL; parent = parent->next )
-    {
+    for (parent = candidates; parent != NULL; parent = parent->next) {
         /* basic parenting skills (name, CA bit, key usage) */
-        if( x509_crt_check_parent( child, parent, top ) != 0 )
+        if (x509_crt_check_parent(child, parent, top) != 0) {
             continue;
+        }
 
         /* +1 because stored max_pathlen is 1 higher that the actual value */
-        if( parent->max_pathlen > 0 &&
-            (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt )
-        {
+        if (parent->max_pathlen > 0 &&
+            (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt) {
             continue;
         }
 
@@ -2609,32 +2157,30 @@
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
 check_signature:
 #endif
-        ret = x509_crt_check_signature( child, parent, rs_ctx );
+        ret = x509_crt_check_signature(child, parent, rs_ctx);
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-        if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
-        {
+        if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
             /* save state */
             rs_ctx->parent = parent;
             rs_ctx->fallback_parent = fallback_parent;
             rs_ctx->fallback_signature_is_good = fallback_signature_is_good;
 
-            return( ret );
+            return ret;
         }
 #else
         (void) ret;
 #endif
 
         signature_is_good = ret == 0;
-        if( top && ! signature_is_good )
+        if (top && !signature_is_good) {
             continue;
+        }
 
         /* optional time check */
-        if( mbedtls_x509_time_is_past( &parent->valid_to ) ||
-            mbedtls_x509_time_is_future( &parent->valid_from ) )
-        {
-            if( fallback_parent == NULL )
-            {
+        if (mbedtls_x509_time_is_past(&parent->valid_to) ||
+            mbedtls_x509_time_is_future(&parent->valid_from)) {
+            if (fallback_parent == NULL) {
                 fallback_parent = parent;
                 fallback_signature_is_good = signature_is_good;
             }
@@ -2648,13 +2194,12 @@
         break;
     }
 
-    if( parent == NULL )
-    {
+    if (parent == NULL) {
         *r_parent = fallback_parent;
         *r_signature_is_good = fallback_signature_is_good;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -2680,14 +2225,14 @@
  *  - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
  */
 static int x509_crt_find_parent(
-                        mbedtls_x509_crt *child,
-                        mbedtls_x509_crt *trust_ca,
-                        mbedtls_x509_crt **parent,
-                        int *parent_is_trusted,
-                        int *signature_is_good,
-                        unsigned path_cnt,
-                        unsigned self_cnt,
-                        mbedtls_x509_crt_restart_ctx *rs_ctx )
+    mbedtls_x509_crt *child,
+    mbedtls_x509_crt *trust_ca,
+    mbedtls_x509_crt **parent,
+    int *parent_is_trusted,
+    int *signature_is_good,
+    unsigned path_cnt,
+    unsigned self_cnt,
+    mbedtls_x509_crt_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_x509_crt *search_list;
@@ -2696,48 +2241,46 @@
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
     /* restore then clear saved state if we have some stored */
-    if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 )
-    {
+    if (rs_ctx != NULL && rs_ctx->parent_is_trusted != -1) {
         *parent_is_trusted = rs_ctx->parent_is_trusted;
         rs_ctx->parent_is_trusted = -1;
     }
 #endif
 
-    while( 1 ) {
+    while (1) {
         search_list = *parent_is_trusted ? trust_ca : child->next;
 
-        ret = x509_crt_find_parent_in( child, search_list,
-                                       parent, signature_is_good,
-                                       *parent_is_trusted,
-                                       path_cnt, self_cnt, rs_ctx );
+        ret = x509_crt_find_parent_in(child, search_list,
+                                      parent, signature_is_good,
+                                      *parent_is_trusted,
+                                      path_cnt, self_cnt, rs_ctx);
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-        if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
-        {
+        if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
             /* save state */
             rs_ctx->parent_is_trusted = *parent_is_trusted;
-            return( ret );
+            return ret;
         }
 #else
         (void) ret;
 #endif
 
         /* stop here if found or already in second iteration */
-        if( *parent != NULL || *parent_is_trusted == 0 )
+        if (*parent != NULL || *parent_is_trusted == 0) {
             break;
+        }
 
         /* prepare second iteration */
         *parent_is_trusted = 0;
     }
 
     /* extra precaution against mistakes in the caller */
-    if( *parent == NULL )
-    {
+    if (*parent == NULL) {
         *parent_is_trusted = 0;
         *signature_is_good = 0;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -2747,27 +2290,26 @@
  * check for self-issued as self-signatures are not checked)
  */
 static int x509_crt_check_ee_locally_trusted(
-                    mbedtls_x509_crt *crt,
-                    mbedtls_x509_crt *trust_ca )
+    mbedtls_x509_crt *crt,
+    mbedtls_x509_crt *trust_ca)
 {
     mbedtls_x509_crt *cur;
 
     /* must be self-issued */
-    if( x509_name_cmp( &crt->issuer, &crt->subject ) != 0 )
-        return( -1 );
+    if (x509_name_cmp(&crt->issuer, &crt->subject) != 0) {
+        return -1;
+    }
 
     /* look for an exact match with trusted cert */
-    for( cur = trust_ca; cur != NULL; cur = cur->next )
-    {
-        if( crt->raw.len == cur->raw.len &&
-            memcmp( crt->raw.p, cur->raw.p, crt->raw.len ) == 0 )
-        {
-            return( 0 );
+    for (cur = trust_ca; cur != NULL; cur = cur->next) {
+        if (crt->raw.len == cur->raw.len &&
+            memcmp(crt->raw.p, cur->raw.p, crt->raw.len) == 0) {
+            return 0;
         }
     }
 
     /* too bad */
-    return( -1 );
+    return -1;
 }
 
 /*
@@ -2811,14 +2353,14 @@
  *      even if it was found to be invalid
  */
 static int x509_crt_verify_chain(
-                mbedtls_x509_crt *crt,
-                mbedtls_x509_crt *trust_ca,
-                mbedtls_x509_crl *ca_crl,
-                mbedtls_x509_crt_ca_cb_t f_ca_cb,
-                void *p_ca_cb,
-                const mbedtls_x509_crt_profile *profile,
-                mbedtls_x509_crt_verify_chain *ver_chain,
-                mbedtls_x509_crt_restart_ctx *rs_ctx )
+    mbedtls_x509_crt *crt,
+    mbedtls_x509_crt *trust_ca,
+    mbedtls_x509_crl *ca_crl,
+    mbedtls_x509_crt_ca_cb_t f_ca_cb,
+    void *p_ca_cb,
+    const mbedtls_x509_crt_profile *profile,
+    mbedtls_x509_crt_verify_chain *ver_chain,
+    mbedtls_x509_crt_restart_ctx *rs_ctx)
 {
     /* Don't initialize any of those variables here, so that the compiler can
      * catch potential issues with jumping ahead when restarting */
@@ -2835,8 +2377,7 @@
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
     /* resume if we had an operation in progress */
-    if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent )
-    {
+    if (rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent) {
         /* restore saved state */
         *ver_chain = rs_ctx->ver_chain; /* struct copy */
         self_cnt = rs_ctx->self_cnt;
@@ -2855,7 +2396,7 @@
     parent_is_trusted = 0;
     child_is_trusted = 0;
 
-    while( 1 ) {
+    while (1) {
         /* Add certificate to the verification chain */
         cur = &ver_chain->items[ver_chain->len];
         cur->crt = child;
@@ -2864,28 +2405,32 @@
         flags = &cur->flags;
 
         /* Check time-validity (all certificates) */
-        if( mbedtls_x509_time_is_past( &child->valid_to ) )
+        if (mbedtls_x509_time_is_past(&child->valid_to)) {
             *flags |= MBEDTLS_X509_BADCERT_EXPIRED;
+        }
 
-        if( mbedtls_x509_time_is_future( &child->valid_from ) )
+        if (mbedtls_x509_time_is_future(&child->valid_from)) {
             *flags |= MBEDTLS_X509_BADCERT_FUTURE;
+        }
 
         /* Stop here for trusted roots (but not for trusted EE certs) */
-        if( child_is_trusted )
-            return( 0 );
+        if (child_is_trusted) {
+            return 0;
+        }
 
         /* Check signature algorithm: MD & PK algs */
-        if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 )
+        if (x509_profile_check_md_alg(profile, child->sig_md) != 0) {
             *flags |= MBEDTLS_X509_BADCERT_BAD_MD;
+        }
 
-        if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 )
+        if (x509_profile_check_pk_alg(profile, child->sig_pk) != 0) {
             *flags |= MBEDTLS_X509_BADCERT_BAD_PK;
+        }
 
         /* Special case: EE certs that are locally trusted */
-        if( ver_chain->len == 1 &&
-            x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 )
-        {
-            return( 0 );
+        if (ver_chain->len == 1 &&
+            x509_crt_check_ee_locally_trusted(child, trust_ca) == 0) {
+            return 0;
         }
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
@@ -2895,19 +2440,18 @@
         /* Obtain list of potential trusted signers from CA callback,
          * or use statically provided list. */
 #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
-        if( f_ca_cb != NULL )
-        {
-            mbedtls_x509_crt_free( ver_chain->trust_ca_cb_result );
-            mbedtls_free( ver_chain->trust_ca_cb_result );
+        if (f_ca_cb != NULL) {
+            mbedtls_x509_crt_free(ver_chain->trust_ca_cb_result);
+            mbedtls_free(ver_chain->trust_ca_cb_result);
             ver_chain->trust_ca_cb_result = NULL;
 
-            ret = f_ca_cb( p_ca_cb, child, &ver_chain->trust_ca_cb_result );
-            if( ret != 0 )
-                return( MBEDTLS_ERR_X509_FATAL_ERROR );
+            ret = f_ca_cb(p_ca_cb, child, &ver_chain->trust_ca_cb_result);
+            if (ret != 0) {
+                return MBEDTLS_ERR_X509_FATAL_ERROR;
+            }
 
             cur_trust_ca = ver_chain->trust_ca_cb_result;
-        }
-        else
+        } else
 #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
         {
             ((void) f_ca_cb);
@@ -2916,60 +2460,58 @@
         }
 
         /* Look for a parent in trusted CAs or up the chain */
-        ret = x509_crt_find_parent( child, cur_trust_ca, &parent,
-                                       &parent_is_trusted, &signature_is_good,
-                                       ver_chain->len - 1, self_cnt, rs_ctx );
+        ret = x509_crt_find_parent(child, cur_trust_ca, &parent,
+                                   &parent_is_trusted, &signature_is_good,
+                                   ver_chain->len - 1, self_cnt, rs_ctx);
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-        if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
-        {
+        if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
             /* save state */
             rs_ctx->in_progress = x509_crt_rs_find_parent;
             rs_ctx->self_cnt = self_cnt;
             rs_ctx->ver_chain = *ver_chain; /* struct copy */
 
-            return( ret );
+            return ret;
         }
 #else
         (void) ret;
 #endif
 
         /* No parent? We're done here */
-        if( parent == NULL )
-        {
+        if (parent == NULL) {
             *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
-            return( 0 );
+            return 0;
         }
 
         /* Count intermediate self-issued (not necessarily self-signed) certs.
          * These can occur with some strategies for key rollover, see [SIRO],
          * and should be excluded from max_pathlen checks. */
-        if( ver_chain->len != 1 &&
-            x509_name_cmp( &child->issuer, &child->subject ) == 0 )
-        {
+        if (ver_chain->len != 1 &&
+            x509_name_cmp(&child->issuer, &child->subject) == 0) {
             self_cnt++;
         }
 
         /* path_cnt is 0 for the first intermediate CA,
          * and if parent is trusted it's not an intermediate CA */
-        if( ! parent_is_trusted &&
-            ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
-        {
+        if (!parent_is_trusted &&
+            ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA) {
             /* return immediately to avoid overflow the chain array */
-            return( MBEDTLS_ERR_X509_FATAL_ERROR );
+            return MBEDTLS_ERR_X509_FATAL_ERROR;
         }
 
         /* signature was checked while searching parent */
-        if( ! signature_is_good )
+        if (!signature_is_good) {
             *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
+        }
 
         /* check size of signing key */
-        if( x509_profile_check_key( profile, &parent->pk ) != 0 )
+        if (x509_profile_check_key(profile, &parent->pk) != 0) {
             *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
+        }
 
 #if defined(MBEDTLS_X509_CRL_PARSE_C)
         /* Check trusted CA's CRL for the given crt */
-        *flags |= x509_crt_verifycrl( child, parent, ca_crl, profile );
+        *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile);
 #else
         (void) ca_crl;
 #endif
@@ -2985,79 +2527,75 @@
 /*
  * Check for CN match
  */
-static int x509_crt_check_cn( const mbedtls_x509_buf *name,
-                              const char *cn, size_t cn_len )
+static int x509_crt_check_cn(const mbedtls_x509_buf *name,
+                             const char *cn, size_t cn_len)
 {
     /* try exact match */
-    if( name->len == cn_len &&
-        x509_memcasecmp( cn, name->p, cn_len ) == 0 )
-    {
-        return( 0 );
+    if (name->len == cn_len &&
+        x509_memcasecmp(cn, name->p, cn_len) == 0) {
+        return 0;
     }
 
     /* try wildcard match */
-    if( x509_check_wildcard( cn, name ) == 0 )
-    {
-        return( 0 );
+    if (x509_check_wildcard(cn, name) == 0) {
+        return 0;
     }
 
-    return( -1 );
+    return -1;
 }
 
 /*
  * Check for SAN match, see RFC 5280 Section 4.2.1.6
  */
-static int x509_crt_check_san( const mbedtls_x509_buf *name,
-                               const char *cn, size_t cn_len )
+static int x509_crt_check_san(const mbedtls_x509_buf *name,
+                              const char *cn, size_t cn_len)
 {
     const unsigned char san_type = (unsigned char) name->tag &
                                    MBEDTLS_ASN1_TAG_VALUE_MASK;
 
     /* dNSName */
-    if( san_type == MBEDTLS_X509_SAN_DNS_NAME )
-        return( x509_crt_check_cn( name, cn, cn_len ) );
+    if (san_type == MBEDTLS_X509_SAN_DNS_NAME) {
+        return x509_crt_check_cn(name, cn, cn_len);
+    }
 
     /* (We may handle other types here later.) */
 
     /* Unrecognized type */
-    return( -1 );
+    return -1;
 }
 
 /*
  * Verify the requested CN - only call this if cn is not NULL!
  */
-static void x509_crt_verify_name( const mbedtls_x509_crt *crt,
-                                  const char *cn,
-                                  uint32_t *flags )
+static void x509_crt_verify_name(const mbedtls_x509_crt *crt,
+                                 const char *cn,
+                                 uint32_t *flags)
 {
     const mbedtls_x509_name *name;
     const mbedtls_x509_sequence *cur;
-    size_t cn_len = strlen( cn );
+    size_t cn_len = strlen(cn);
 
-    if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
-    {
-        for( cur = &crt->subject_alt_names; cur != NULL; cur = cur->next )
-        {
-            if( x509_crt_check_san( &cur->buf, cn, cn_len ) == 0 )
-                break;
-        }
-
-        if( cur == NULL )
-            *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
-    }
-    else
-    {
-        for( name = &crt->subject; name != NULL; name = name->next )
-        {
-            if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 &&
-                x509_crt_check_cn( &name->val, cn, cn_len ) == 0 )
-            {
+    if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
+        for (cur = &crt->subject_alt_names; cur != NULL; cur = cur->next) {
+            if (x509_crt_check_san(&cur->buf, cn, cn_len) == 0) {
                 break;
             }
         }
 
-        if( name == NULL )
+        if (cur == NULL) {
             *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
+        }
+    } else {
+        for (name = &crt->subject; name != NULL; name = name->next) {
+            if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0 &&
+                x509_crt_check_cn(&name->val, cn, cn_len) == 0) {
+                break;
+            }
+        }
+
+        if (name == NULL) {
+            *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
+        }
     }
 }
 
@@ -3065,29 +2603,30 @@
  * Merge the flags for all certs in the chain, after calling callback
  */
 static int x509_crt_merge_flags_with_cb(
-           uint32_t *flags,
-           const mbedtls_x509_crt_verify_chain *ver_chain,
-           int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
-           void *p_vrfy )
+    uint32_t *flags,
+    const mbedtls_x509_crt_verify_chain *ver_chain,
+    int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+    void *p_vrfy)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned i;
     uint32_t cur_flags;
     const mbedtls_x509_crt_verify_chain_item *cur;
 
-    for( i = ver_chain->len; i != 0; --i )
-    {
+    for (i = ver_chain->len; i != 0; --i) {
         cur = &ver_chain->items[i-1];
         cur_flags = cur->flags;
 
-        if( NULL != f_vrfy )
-            if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 )
-                return( ret );
+        if (NULL != f_vrfy) {
+            if ((ret = f_vrfy(p_vrfy, cur->crt, (int) i-1, &cur_flags)) != 0) {
+                return ret;
+            }
+        }
 
         *flags |= cur_flags;
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
@@ -3107,16 +2646,19 @@
  * of trusted signers, and `ca_crl` will be use as the static list
  * of CRLs.
  */
-static int x509_crt_verify_restartable_ca_cb( mbedtls_x509_crt *crt,
-                     mbedtls_x509_crt *trust_ca,
-                     mbedtls_x509_crl *ca_crl,
-                     mbedtls_x509_crt_ca_cb_t f_ca_cb,
-                     void *p_ca_cb,
-                     const mbedtls_x509_crt_profile *profile,
-                     const char *cn, uint32_t *flags,
-                     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
-                     void *p_vrfy,
-                     mbedtls_x509_crt_restart_ctx *rs_ctx )
+static int x509_crt_verify_restartable_ca_cb(mbedtls_x509_crt *crt,
+                                             mbedtls_x509_crt *trust_ca,
+                                             mbedtls_x509_crl *ca_crl,
+                                             mbedtls_x509_crt_ca_cb_t f_ca_cb,
+                                             void *p_ca_cb,
+                                             const mbedtls_x509_crt_profile *profile,
+                                             const char *cn, uint32_t *flags,
+                                             int (*f_vrfy)(void *,
+                                                           mbedtls_x509_crt *,
+                                                           int,
+                                                           uint32_t *),
+                                             void *p_vrfy,
+                                             mbedtls_x509_crt_restart_ctx *rs_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_pk_type_t pk_type;
@@ -3125,105 +2667,110 @@
 
     *flags = 0;
     ee_flags = 0;
-    x509_crt_verify_chain_reset( &ver_chain );
+    x509_crt_verify_chain_reset(&ver_chain);
 
-    if( profile == NULL )
-    {
+    if (profile == NULL) {
         ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
         goto exit;
     }
 
     /* check name if requested */
-    if( cn != NULL )
-        x509_crt_verify_name( crt, cn, &ee_flags );
+    if (cn != NULL) {
+        x509_crt_verify_name(crt, cn, &ee_flags);
+    }
 
     /* Check the type and size of the key */
-    pk_type = mbedtls_pk_get_type( &crt->pk );
+    pk_type = mbedtls_pk_get_type(&crt->pk);
 
-    if( x509_profile_check_pk_alg( profile, pk_type ) != 0 )
+    if (x509_profile_check_pk_alg(profile, pk_type) != 0) {
         ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
+    }
 
-    if( x509_profile_check_key( profile, &crt->pk ) != 0 )
+    if (x509_profile_check_key(profile, &crt->pk) != 0) {
         ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
+    }
 
     /* Check the chain */
-    ret = x509_crt_verify_chain( crt, trust_ca, ca_crl,
-                                 f_ca_cb, p_ca_cb, profile,
-                                 &ver_chain, rs_ctx );
+    ret = x509_crt_verify_chain(crt, trust_ca, ca_crl,
+                                f_ca_cb, p_ca_cb, profile,
+                                &ver_chain, rs_ctx);
 
-    if( ret != 0 )
+    if (ret != 0) {
         goto exit;
+    }
 
     /* Merge end-entity flags */
     ver_chain.items[0].flags |= ee_flags;
 
     /* Build final flags, calling callback on the way if any */
-    ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy );
+    ret = x509_crt_merge_flags_with_cb(flags, &ver_chain, f_vrfy, p_vrfy);
 
 exit:
 
 #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
-    mbedtls_x509_crt_free( ver_chain.trust_ca_cb_result );
-    mbedtls_free( ver_chain.trust_ca_cb_result );
+    mbedtls_x509_crt_free(ver_chain.trust_ca_cb_result);
+    mbedtls_free(ver_chain.trust_ca_cb_result);
     ver_chain.trust_ca_cb_result = NULL;
 #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-    if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
-        mbedtls_x509_crt_restart_free( rs_ctx );
+    if (rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS) {
+        mbedtls_x509_crt_restart_free(rs_ctx);
+    }
 #endif
 
     /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by
      * the SSL module for authmode optional, but non-zero return from the
      * callback means a fatal error so it shouldn't be ignored */
-    if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
+    if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
         ret = MBEDTLS_ERR_X509_FATAL_ERROR;
-
-    if( ret != 0 )
-    {
-        *flags = (uint32_t) -1;
-        return( ret );
     }
 
-    if( *flags != 0 )
-        return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED );
+    if (ret != 0) {
+        *flags = (uint32_t) -1;
+        return ret;
+    }
 
-    return( 0 );
+    if (*flags != 0) {
+        return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
+    }
+
+    return 0;
 }
 
 
 /*
  * Verify the certificate validity (default profile, not restartable)
  */
-int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
-                     mbedtls_x509_crt *trust_ca,
-                     mbedtls_x509_crl *ca_crl,
-                     const char *cn, uint32_t *flags,
-                     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
-                     void *p_vrfy )
+int mbedtls_x509_crt_verify(mbedtls_x509_crt *crt,
+                            mbedtls_x509_crt *trust_ca,
+                            mbedtls_x509_crl *ca_crl,
+                            const char *cn, uint32_t *flags,
+                            int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+                            void *p_vrfy)
 {
-    return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl,
-                                         NULL, NULL,
-                                         &mbedtls_x509_crt_profile_default,
-                                         cn, flags,
-                                         f_vrfy, p_vrfy, NULL ) );
+    return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl,
+                                             NULL, NULL,
+                                             &mbedtls_x509_crt_profile_default,
+                                             cn, flags,
+                                             f_vrfy, p_vrfy, NULL);
 }
 
 /*
  * Verify the certificate validity (user-chosen profile, not restartable)
  */
-int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
-                     mbedtls_x509_crt *trust_ca,
-                     mbedtls_x509_crl *ca_crl,
-                     const mbedtls_x509_crt_profile *profile,
-                     const char *cn, uint32_t *flags,
-                     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
-                     void *p_vrfy )
+int mbedtls_x509_crt_verify_with_profile(mbedtls_x509_crt *crt,
+                                         mbedtls_x509_crt *trust_ca,
+                                         mbedtls_x509_crl *ca_crl,
+                                         const mbedtls_x509_crt_profile *profile,
+                                         const char *cn, uint32_t *flags,
+                                         int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+                                         void *p_vrfy)
 {
-    return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl,
-                                                 NULL, NULL,
-                                                 profile, cn, flags,
-                                                 f_vrfy, p_vrfy, NULL ) );
+    return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl,
+                                             NULL, NULL,
+                                             profile, cn, flags,
+                                             f_vrfy, p_vrfy, NULL);
 }
 
 #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
@@ -3231,146 +2778,88 @@
  * Verify the certificate validity (user-chosen profile, CA callback,
  *                                  not restartable).
  */
-int mbedtls_x509_crt_verify_with_ca_cb( mbedtls_x509_crt *crt,
-                     mbedtls_x509_crt_ca_cb_t f_ca_cb,
-                     void *p_ca_cb,
-                     const mbedtls_x509_crt_profile *profile,
-                     const char *cn, uint32_t *flags,
-                     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
-                     void *p_vrfy )
+int mbedtls_x509_crt_verify_with_ca_cb(mbedtls_x509_crt *crt,
+                                       mbedtls_x509_crt_ca_cb_t f_ca_cb,
+                                       void *p_ca_cb,
+                                       const mbedtls_x509_crt_profile *profile,
+                                       const char *cn, uint32_t *flags,
+                                       int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+                                       void *p_vrfy)
 {
-    return( x509_crt_verify_restartable_ca_cb( crt, NULL, NULL,
-                                                 f_ca_cb, p_ca_cb,
-                                                 profile, cn, flags,
-                                                 f_vrfy, p_vrfy, NULL ) );
+    return x509_crt_verify_restartable_ca_cb(crt, NULL, NULL,
+                                             f_ca_cb, p_ca_cb,
+                                             profile, cn, flags,
+                                             f_vrfy, p_vrfy, NULL);
 }
 #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
 
-int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
-                     mbedtls_x509_crt *trust_ca,
-                     mbedtls_x509_crl *ca_crl,
-                     const mbedtls_x509_crt_profile *profile,
-                     const char *cn, uint32_t *flags,
-                     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
-                     void *p_vrfy,
-                     mbedtls_x509_crt_restart_ctx *rs_ctx )
+int mbedtls_x509_crt_verify_restartable(mbedtls_x509_crt *crt,
+                                        mbedtls_x509_crt *trust_ca,
+                                        mbedtls_x509_crl *ca_crl,
+                                        const mbedtls_x509_crt_profile *profile,
+                                        const char *cn, uint32_t *flags,
+                                        int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+                                        void *p_vrfy,
+                                        mbedtls_x509_crt_restart_ctx *rs_ctx)
 {
-    return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl,
-                                                 NULL, NULL,
-                                                 profile, cn, flags,
-                                                 f_vrfy, p_vrfy, rs_ctx ) );
+    return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl,
+                                             NULL, NULL,
+                                             profile, cn, flags,
+                                             f_vrfy, p_vrfy, rs_ctx);
 }
 
 
 /*
  * Initialize a certificate chain
  */
-void mbedtls_x509_crt_init( mbedtls_x509_crt *crt )
+void mbedtls_x509_crt_init(mbedtls_x509_crt *crt)
 {
-    memset( crt, 0, sizeof(mbedtls_x509_crt) );
+    memset(crt, 0, sizeof(mbedtls_x509_crt));
 }
 
 /*
  * Unallocate all certificate data
  */
-void mbedtls_x509_crt_free( mbedtls_x509_crt *crt )
+void mbedtls_x509_crt_free(mbedtls_x509_crt *crt)
 {
     mbedtls_x509_crt *cert_cur = crt;
     mbedtls_x509_crt *cert_prv;
-    mbedtls_x509_name *name_cur;
-    mbedtls_x509_name *name_prv;
-    mbedtls_x509_sequence *seq_cur;
-    mbedtls_x509_sequence *seq_prv;
 
-    if( crt == NULL )
-        return;
-
-    do
-    {
-        mbedtls_pk_free( &cert_cur->pk );
+    while (cert_cur != NULL) {
+        mbedtls_pk_free(&cert_cur->pk);
 
 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
-        mbedtls_free( cert_cur->sig_opts );
+        mbedtls_free(cert_cur->sig_opts);
 #endif
 
-        name_cur = cert_cur->issuer.next;
-        while( name_cur != NULL )
-        {
-            name_prv = name_cur;
-            name_cur = name_cur->next;
-            mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
-            mbedtls_free( name_prv );
+        mbedtls_asn1_free_named_data_list_shallow(cert_cur->issuer.next);
+        mbedtls_asn1_free_named_data_list_shallow(cert_cur->subject.next);
+        mbedtls_asn1_sequence_free(cert_cur->ext_key_usage.next);
+        mbedtls_asn1_sequence_free(cert_cur->subject_alt_names.next);
+        mbedtls_asn1_sequence_free(cert_cur->certificate_policies.next);
+
+        if (cert_cur->raw.p != NULL && cert_cur->own_buffer) {
+            mbedtls_platform_zeroize(cert_cur->raw.p, cert_cur->raw.len);
+            mbedtls_free(cert_cur->raw.p);
         }
 
-        name_cur = cert_cur->subject.next;
-        while( name_cur != NULL )
-        {
-            name_prv = name_cur;
-            name_cur = name_cur->next;
-            mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
-            mbedtls_free( name_prv );
-        }
-
-        seq_cur = cert_cur->ext_key_usage.next;
-        while( seq_cur != NULL )
-        {
-            seq_prv = seq_cur;
-            seq_cur = seq_cur->next;
-            mbedtls_platform_zeroize( seq_prv,
-                                      sizeof( mbedtls_x509_sequence ) );
-            mbedtls_free( seq_prv );
-        }
-
-        seq_cur = cert_cur->subject_alt_names.next;
-        while( seq_cur != NULL )
-        {
-            seq_prv = seq_cur;
-            seq_cur = seq_cur->next;
-            mbedtls_platform_zeroize( seq_prv,
-                                      sizeof( mbedtls_x509_sequence ) );
-            mbedtls_free( seq_prv );
-        }
-
-        seq_cur = cert_cur->certificate_policies.next;
-        while( seq_cur != NULL )
-        {
-            seq_prv = seq_cur;
-            seq_cur = seq_cur->next;
-            mbedtls_platform_zeroize( seq_prv,
-                                      sizeof( mbedtls_x509_sequence ) );
-            mbedtls_free( seq_prv );
-        }
-
-        if( cert_cur->raw.p != NULL && cert_cur->own_buffer )
-        {
-            mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len );
-            mbedtls_free( cert_cur->raw.p );
-        }
-
-        cert_cur = cert_cur->next;
-    }
-    while( cert_cur != NULL );
-
-    cert_cur = crt;
-    do
-    {
         cert_prv = cert_cur;
         cert_cur = cert_cur->next;
 
-        mbedtls_platform_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) );
-        if( cert_prv != crt )
-            mbedtls_free( cert_prv );
+        mbedtls_platform_zeroize(cert_prv, sizeof(mbedtls_x509_crt));
+        if (cert_prv != crt) {
+            mbedtls_free(cert_prv);
+        }
     }
-    while( cert_cur != NULL );
 }
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
 /*
  * Initialize a restart context
  */
-void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx )
+void mbedtls_x509_crt_restart_init(mbedtls_x509_crt_restart_ctx *ctx)
 {
-    mbedtls_pk_restart_init( &ctx->pk );
+    mbedtls_pk_restart_init(&ctx->pk);
 
     ctx->parent = NULL;
     ctx->fallback_parent = NULL;
@@ -3380,19 +2869,20 @@
 
     ctx->in_progress = x509_crt_rs_none;
     ctx->self_cnt = 0;
-    x509_crt_verify_chain_reset( &ctx->ver_chain );
+    x509_crt_verify_chain_reset(&ctx->ver_chain);
 }
 
 /*
  * Free the components of a restart context
  */
-void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx )
+void mbedtls_x509_crt_restart_free(mbedtls_x509_crt_restart_ctx *ctx)
 {
-    if( ctx == NULL )
+    if (ctx == NULL) {
         return;
+    }
 
-    mbedtls_pk_restart_free( &ctx->pk );
-    mbedtls_x509_crt_restart_init( ctx );
+    mbedtls_pk_restart_free(&ctx->pk);
+    mbedtls_x509_crt_restart_init(ctx);
 }
 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
 
diff --git a/lib/libmbedtls/mbedtls/library/x509_csr.c b/lib/libmbedtls/mbedtls/library/x509_csr.c
index e259410..cd117cb 100644
--- a/lib/libmbedtls/mbedtls/library/x509_csr.c
+++ b/lib/libmbedtls/mbedtls/library/x509_csr.c
@@ -42,15 +42,7 @@
 #include "mbedtls/pem.h"
 #endif
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#include <stdio.h>
-#define mbedtls_free       free
-#define mbedtls_calloc    calloc
-#define mbedtls_snprintf   snprintf
-#endif
 
 #if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32)
 #include <stdio.h>
@@ -59,56 +51,215 @@
 /*
  *  Version  ::=  INTEGER  {  v1(0)  }
  */
-static int x509_csr_get_version( unsigned char **p,
-                             const unsigned char *end,
-                             int *ver )
+static int x509_csr_get_version(unsigned char **p,
+                                const unsigned char *end,
+                                int *ver)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
-    {
-        if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-        {
+    if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) {
+        if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
             *ver = 0;
-            return( 0 );
+            return 0;
         }
 
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_VERSION, ret ) );
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret);
     }
 
-    return( 0 );
+    return 0;
+}
+
+/*
+ * Parse CSR extension requests in DER format
+ */
+static int x509_csr_parse_extensions(mbedtls_x509_csr *csr,
+                                     unsigned char **p, const unsigned char *end)
+{
+    int ret;
+    size_t len;
+    unsigned char *end_ext_data;
+    while (*p < end) {
+        mbedtls_x509_buf extn_oid = { 0, 0, NULL };
+        int ext_type = 0;
+
+        /* Read sequence tag */
+        if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
+
+        end_ext_data = *p + len;
+
+        /* Get extension ID */
+        if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len,
+                                        MBEDTLS_ASN1_OID)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
+
+        extn_oid.tag = MBEDTLS_ASN1_OID;
+        extn_oid.p = *p;
+        *p += extn_oid.len;
+
+        /* Data should be octet string type */
+        if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len,
+                                        MBEDTLS_ASN1_OCTET_STRING)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
+
+        if (*p + len != end_ext_data) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+        }
+
+        /*
+         * Detect supported extensions and skip unsupported extensions
+         */
+        ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type);
+
+        if (ret == 0) {
+            /* Forbid repeated extensions */
+            if ((csr->ext_types & ext_type) != 0) {
+                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                         MBEDTLS_ERR_ASN1_INVALID_DATA);
+            }
+
+            csr->ext_types |= ext_type;
+
+            switch (ext_type) {
+                case MBEDTLS_X509_EXT_KEY_USAGE:
+                    /* Parse key usage */
+                    if ((ret = mbedtls_x509_get_key_usage(p, end_ext_data,
+                                                          &csr->key_usage)) != 0) {
+                        return ret;
+                    }
+                    break;
+
+                case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
+                    /* Parse subject alt name */
+                    if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_data,
+                                                                 &csr->subject_alt_names)) != 0) {
+                        return ret;
+                    }
+                    break;
+
+                case MBEDTLS_X509_EXT_NS_CERT_TYPE:
+                    /* Parse netscape certificate type */
+                    if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_data,
+                                                             &csr->ns_cert_type)) != 0) {
+                        return ret;
+                    }
+                    break;
+                default:
+                    break;
+            }
+        }
+        *p = end_ext_data;
+    }
+
+    if (*p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+
+    return 0;
+}
+
+/*
+ * Parse CSR attributes in DER format
+ */
+static int x509_csr_parse_attributes(mbedtls_x509_csr *csr,
+                                     const unsigned char *start, const unsigned char *end)
+{
+    int ret;
+    size_t len;
+    unsigned char *end_attr_data;
+    unsigned char **p = (unsigned char **) &start;
+
+    while (*p < end) {
+        mbedtls_x509_buf attr_oid = { 0, 0, NULL };
+
+        if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
+        end_attr_data = *p + len;
+
+        /* Get attribute ID */
+        if ((ret = mbedtls_asn1_get_tag(p, end_attr_data, &attr_oid.len,
+                                        MBEDTLS_ASN1_OID)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
+
+        attr_oid.tag = MBEDTLS_ASN1_OID;
+        attr_oid.p = *p;
+        *p += attr_oid.len;
+
+        /* Check that this is an extension-request attribute */
+        if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS9_CSR_EXT_REQ, &attr_oid) == 0) {
+            if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) {
+                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+            }
+
+            if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) !=
+                0) {
+                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+            }
+
+            if ((ret = x509_csr_parse_extensions(csr, p, *p + len)) != 0) {
+                return ret;
+            }
+
+            if (*p != end_attr_data) {
+                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                         MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+            }
+        }
+
+        *p = end_attr_data;
+    }
+
+    if (*p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+
+    return 0;
 }
 
 /*
  * Parse a CSR in DER format
  */
-int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr,
-                        const unsigned char *buf, size_t buflen )
+int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,
+                               const unsigned char *buf, size_t buflen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
     unsigned char *p, *end;
     mbedtls_x509_buf sig_params;
 
-    memset( &sig_params, 0, sizeof( mbedtls_x509_buf ) );
+    memset(&sig_params, 0, sizeof(mbedtls_x509_buf));
 
     /*
      * Check for valid input
      */
-    if( csr == NULL || buf == NULL || buflen == 0 )
-        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+    if (csr == NULL || buf == NULL || buflen == 0) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
 
-    mbedtls_x509_csr_init( csr );
+    mbedtls_x509_csr_init(csr);
 
     /*
      * first copy the raw DER data
      */
-    p = mbedtls_calloc( 1, len = buflen );
+    p = mbedtls_calloc(1, len = buflen);
 
-    if( p == NULL )
-        return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+    if (p == NULL) {
+        return MBEDTLS_ERR_X509_ALLOC_FAILED;
+    }
 
-    memcpy( p, buf, buflen );
+    memcpy(p, buf, buflen);
 
     csr->raw.p = p;
     csr->raw.len = len;
@@ -121,18 +272,16 @@
      *       signature          BIT STRING
      *  }
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        mbedtls_x509_csr_free( csr );
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        mbedtls_x509_csr_free(csr);
+        return MBEDTLS_ERR_X509_INVALID_FORMAT;
     }
 
-    if( len != (size_t) ( end - p ) )
-    {
-        mbedtls_x509_csr_free( csr );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (len != (size_t) (end - p)) {
+        mbedtls_x509_csr_free(csr);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
     }
 
     /*
@@ -140,11 +289,10 @@
      */
     csr->cri.p = p;
 
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        mbedtls_x509_csr_free( csr );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        mbedtls_x509_csr_free(csr);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
     }
 
     end = p + len;
@@ -153,16 +301,14 @@
     /*
      *  Version  ::=  INTEGER {  v1(0) }
      */
-    if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 )
-    {
-        mbedtls_x509_csr_free( csr );
-        return( ret );
+    if ((ret = x509_csr_get_version(&p, end, &csr->version)) != 0) {
+        mbedtls_x509_csr_free(csr);
+        return ret;
     }
 
-    if( csr->version != 0 )
-    {
-        mbedtls_x509_csr_free( csr );
-        return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
+    if (csr->version != 0) {
+        mbedtls_x509_csr_free(csr);
+        return MBEDTLS_ERR_X509_UNKNOWN_VERSION;
     }
 
     csr->version++;
@@ -172,17 +318,15 @@
      */
     csr->subject_raw.p = p;
 
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
-    {
-        mbedtls_x509_csr_free( csr );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        mbedtls_x509_csr_free(csr);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
     }
 
-    if( ( ret = mbedtls_x509_get_name( &p, p + len, &csr->subject ) ) != 0 )
-    {
-        mbedtls_x509_csr_free( csr );
-        return( ret );
+    if ((ret = mbedtls_x509_get_name(&p, p + len, &csr->subject)) != 0) {
+        mbedtls_x509_csr_free(csr);
+        return ret;
     }
 
     csr->subject_raw.len = p - csr->subject_raw.p;
@@ -190,10 +334,9 @@
     /*
      *  subjectPKInfo SubjectPublicKeyInfo
      */
-    if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 )
-    {
-        mbedtls_x509_csr_free( csr );
-        return( ret );
+    if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &csr->pk)) != 0) {
+        mbedtls_x509_csr_free(csr);
+        return ret;
     }
 
     /*
@@ -206,11 +349,16 @@
      *  the requester's expectations - this cannot cause a violation of our
      *  signature policies.
      */
-    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
-    {
-        mbedtls_x509_csr_free( csr );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) );
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=
+        0) {
+        mbedtls_x509_csr_free(csr);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
+    }
+
+    if ((ret = x509_csr_parse_attributes(csr, p, p + len)) != 0) {
+        mbedtls_x509_csr_free(csr);
+        return ret;
     }
 
     p += len;
@@ -221,40 +369,36 @@
      *  signatureAlgorithm   AlgorithmIdentifier,
      *  signature            BIT STRING
      */
-    if( ( ret = mbedtls_x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 )
-    {
-        mbedtls_x509_csr_free( csr );
-        return( ret );
+    if ((ret = mbedtls_x509_get_alg(&p, end, &csr->sig_oid, &sig_params)) != 0) {
+        mbedtls_x509_csr_free(csr);
+        return ret;
     }
 
-    if( ( ret = mbedtls_x509_get_sig_alg( &csr->sig_oid, &sig_params,
-                                  &csr->sig_md, &csr->sig_pk,
-                                  &csr->sig_opts ) ) != 0 )
-    {
-        mbedtls_x509_csr_free( csr );
-        return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG );
+    if ((ret = mbedtls_x509_get_sig_alg(&csr->sig_oid, &sig_params,
+                                        &csr->sig_md, &csr->sig_pk,
+                                        &csr->sig_opts)) != 0) {
+        mbedtls_x509_csr_free(csr);
+        return MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG;
     }
 
-    if( ( ret = mbedtls_x509_get_sig( &p, end, &csr->sig ) ) != 0 )
-    {
-        mbedtls_x509_csr_free( csr );
-        return( ret );
+    if ((ret = mbedtls_x509_get_sig(&p, end, &csr->sig)) != 0) {
+        mbedtls_x509_csr_free(csr);
+        return ret;
     }
 
-    if( p != end )
-    {
-        mbedtls_x509_csr_free( csr );
-        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT,
-                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
+    if (p != end) {
+        mbedtls_x509_csr_free(csr);
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
     }
 
-    return( 0 );
+    return 0;
 }
 
 /*
  * Parse a CSR, allowing for PEM or raw DER encoding
  */
-int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen )
+int mbedtls_x509_csr_parse(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen)
 {
 #if defined(MBEDTLS_PEM_PARSE_C)
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -265,71 +409,72 @@
     /*
      * Check for valid input
      */
-    if( csr == NULL || buf == NULL || buflen == 0 )
-        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+    if (csr == NULL || buf == NULL || buflen == 0) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
 
 #if defined(MBEDTLS_PEM_PARSE_C)
     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
-    if( buf[buflen - 1] == '\0' )
-    {
-        mbedtls_pem_init( &pem );
-        ret = mbedtls_pem_read_buffer( &pem,
-                                       "-----BEGIN CERTIFICATE REQUEST-----",
-                                       "-----END CERTIFICATE REQUEST-----",
-                                       buf, NULL, 0, &use_len );
-        if( ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-        {
-            ret = mbedtls_pem_read_buffer( &pem,
-                                           "-----BEGIN NEW CERTIFICATE REQUEST-----",
-                                           "-----END NEW CERTIFICATE REQUEST-----",
-                                           buf, NULL, 0, &use_len );
+    if (buf[buflen - 1] == '\0') {
+        mbedtls_pem_init(&pem);
+        ret = mbedtls_pem_read_buffer(&pem,
+                                      "-----BEGIN CERTIFICATE REQUEST-----",
+                                      "-----END CERTIFICATE REQUEST-----",
+                                      buf, NULL, 0, &use_len);
+        if (ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
+            ret = mbedtls_pem_read_buffer(&pem,
+                                          "-----BEGIN NEW CERTIFICATE REQUEST-----",
+                                          "-----END NEW CERTIFICATE REQUEST-----",
+                                          buf, NULL, 0, &use_len);
         }
 
-        if( ret == 0 )
-        {
+        if (ret == 0) {
             /*
              * Was PEM encoded, parse the result
              */
-            ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen );
+            ret = mbedtls_x509_csr_parse_der(csr, pem.buf, pem.buflen);
         }
 
-        mbedtls_pem_free( &pem );
-        if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
-            return( ret );
+        mbedtls_pem_free(&pem);
+        if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
+            return ret;
+        }
     }
 #endif /* MBEDTLS_PEM_PARSE_C */
-    return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) );
+    return mbedtls_x509_csr_parse_der(csr, buf, buflen);
 }
 
 #if defined(MBEDTLS_FS_IO)
 /*
  * Load a CSR into the structure
  */
-int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path )
+int mbedtls_x509_csr_parse_file(mbedtls_x509_csr *csr, const char *path)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
     unsigned char *buf;
 
-    if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
-        return( ret );
+    if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
+        return ret;
+    }
 
-    ret = mbedtls_x509_csr_parse( csr, buf, n );
+    ret = mbedtls_x509_csr_parse(csr, buf, n);
 
-    mbedtls_platform_zeroize( buf, n );
-    mbedtls_free( buf );
+    mbedtls_platform_zeroize(buf, n);
+    mbedtls_free(buf);
 
-    return( ret );
+    return ret;
 }
 #endif /* MBEDTLS_FS_IO */
 
+#if !defined(MBEDTLS_X509_REMOVE_INFO)
 #define BEFORE_COLON    14
 #define BC              "14"
 /*
  * Return an informational string about the CSR.
  */
-int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix,
-                   const mbedtls_x509_csr *csr )
+int mbedtls_x509_csr_info(char *buf, size_t size, const char *prefix,
+                          const mbedtls_x509_csr *csr)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
@@ -339,76 +484,105 @@
     p = buf;
     n = size;
 
-    ret = mbedtls_snprintf( p, n, "%sCSR version   : %d",
-                               prefix, csr->version );
+    ret = mbedtls_snprintf(p, n, "%sCSR version   : %d",
+                           prefix, csr->version);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    ret = mbedtls_snprintf( p, n, "\n%ssubject name  : ", prefix );
+    ret = mbedtls_snprintf(p, n, "\n%ssubject name  : ", prefix);
     MBEDTLS_X509_SAFE_SNPRINTF;
-    ret = mbedtls_x509_dn_gets( p, n, &csr->subject );
+    ret = mbedtls_x509_dn_gets(p, n, &csr->subject);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    ret = mbedtls_snprintf( p, n, "\n%ssigned using  : ", prefix );
+    ret = mbedtls_snprintf(p, n, "\n%ssigned using  : ", prefix);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    ret = mbedtls_x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md,
-                             csr->sig_opts );
+    ret = mbedtls_x509_sig_alg_gets(p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md,
+                                    csr->sig_opts);
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON,
-                                      mbedtls_pk_get_name( &csr->pk ) ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_x509_key_size_helper(key_size_str, BEFORE_COLON,
+                                            mbedtls_pk_get_name(&csr->pk))) != 0) {
+        return ret;
     }
 
-    ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
-                          (int) mbedtls_pk_get_bitlen( &csr->pk ) );
+    ret = mbedtls_snprintf(p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
+                           (int) mbedtls_pk_get_bitlen(&csr->pk));
     MBEDTLS_X509_SAFE_SNPRINTF;
 
-    return( (int) ( size - n ) );
+    /*
+     * Optional extensions
+     */
+
+    if (csr->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
+        ret = mbedtls_snprintf(p, n, "\n%ssubject alt name  :", prefix);
+        MBEDTLS_X509_SAFE_SNPRINTF;
+
+        if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n,
+                                                      &csr->subject_alt_names,
+                                                      prefix)) != 0) {
+            return ret;
+        }
+    }
+
+    if (csr->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) {
+        ret = mbedtls_snprintf(p, n, "\n%scert. type        : ", prefix);
+        MBEDTLS_X509_SAFE_SNPRINTF;
+
+        if ((ret = mbedtls_x509_info_cert_type(&p, &n, csr->ns_cert_type)) != 0) {
+            return ret;
+        }
+    }
+
+    if (csr->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) {
+        ret = mbedtls_snprintf(p, n, "\n%skey usage         : ", prefix);
+        MBEDTLS_X509_SAFE_SNPRINTF;
+
+        if ((ret = mbedtls_x509_info_key_usage(&p, &n, csr->key_usage)) != 0) {
+            return ret;
+        }
+    }
+
+    if (csr->ext_types != 0) {
+        ret = mbedtls_snprintf(p, n, "\n");
+        MBEDTLS_X509_SAFE_SNPRINTF;
+    }
+
+    return (int) (size - n);
 }
+#endif /* MBEDTLS_X509_REMOVE_INFO */
 
 /*
  * Initialize a CSR
  */
-void mbedtls_x509_csr_init( mbedtls_x509_csr *csr )
+void mbedtls_x509_csr_init(mbedtls_x509_csr *csr)
 {
-    memset( csr, 0, sizeof(mbedtls_x509_csr) );
+    memset(csr, 0, sizeof(mbedtls_x509_csr));
 }
 
 /*
  * Unallocate all CSR data
  */
-void mbedtls_x509_csr_free( mbedtls_x509_csr *csr )
+void mbedtls_x509_csr_free(mbedtls_x509_csr *csr)
 {
-    mbedtls_x509_name *name_cur;
-    mbedtls_x509_name *name_prv;
-
-    if( csr == NULL )
+    if (csr == NULL) {
         return;
+    }
 
-    mbedtls_pk_free( &csr->pk );
+    mbedtls_pk_free(&csr->pk);
 
 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
-    mbedtls_free( csr->sig_opts );
+    mbedtls_free(csr->sig_opts);
 #endif
 
-    name_cur = csr->subject.next;
-    while( name_cur != NULL )
-    {
-        name_prv = name_cur;
-        name_cur = name_cur->next;
-        mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
-        mbedtls_free( name_prv );
+    mbedtls_asn1_free_named_data_list_shallow(csr->subject.next);
+    mbedtls_asn1_sequence_free(csr->subject_alt_names.next);
+
+    if (csr->raw.p != NULL) {
+        mbedtls_platform_zeroize(csr->raw.p, csr->raw.len);
+        mbedtls_free(csr->raw.p);
     }
 
-    if( csr->raw.p != NULL )
-    {
-        mbedtls_platform_zeroize( csr->raw.p, csr->raw.len );
-        mbedtls_free( csr->raw.p );
-    }
-
-    mbedtls_platform_zeroize( csr, sizeof( mbedtls_x509_csr ) );
+    mbedtls_platform_zeroize(csr, sizeof(mbedtls_x509_csr));
 }
 
 #endif /* MBEDTLS_X509_CSR_PARSE_C */
diff --git a/lib/libmbedtls/mbedtls/library/x509write_crt.c b/lib/libmbedtls/mbedtls/library/x509write_crt.c
index 0c5e991..f481155 100644
--- a/lib/libmbedtls/mbedtls/library/x509write_crt.c
+++ b/lib/libmbedtls/mbedtls/library/x509write_crt.c
@@ -32,7 +32,7 @@
 #include "mbedtls/error.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/platform_util.h"
-#include "mbedtls/sha1.h"
+#include "mbedtls/md.h"
 
 #include <string.h>
 
@@ -40,258 +40,356 @@
 #include "mbedtls/pem.h"
 #endif /* MBEDTLS_PEM_WRITE_C */
 
-void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx )
-{
-    memset( ctx, 0, sizeof( mbedtls_x509write_cert ) );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-    mbedtls_mpi_init( &ctx->serial );
+#include "hash_info.h"
+#include "mbedtls/legacy_or_psa.h"
+
+void mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx)
+{
+    memset(ctx, 0, sizeof(mbedtls_x509write_cert));
+
     ctx->version = MBEDTLS_X509_CRT_VERSION_3;
 }
 
-void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx )
+void mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx)
 {
-    mbedtls_mpi_free( &ctx->serial );
+    mbedtls_asn1_free_named_data_list(&ctx->subject);
+    mbedtls_asn1_free_named_data_list(&ctx->issuer);
+    mbedtls_asn1_free_named_data_list(&ctx->extensions);
 
-    mbedtls_asn1_free_named_data_list( &ctx->subject );
-    mbedtls_asn1_free_named_data_list( &ctx->issuer );
-    mbedtls_asn1_free_named_data_list( &ctx->extensions );
-
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_cert ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_cert));
 }
 
-void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx,
-                                        int version )
+void mbedtls_x509write_crt_set_version(mbedtls_x509write_cert *ctx,
+                                       int version)
 {
     ctx->version = version;
 }
 
-void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx,
-                                       mbedtls_md_type_t md_alg )
+void mbedtls_x509write_crt_set_md_alg(mbedtls_x509write_cert *ctx,
+                                      mbedtls_md_type_t md_alg)
 {
     ctx->md_alg = md_alg;
 }
 
-void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx,
-                                            mbedtls_pk_context *key )
+void mbedtls_x509write_crt_set_subject_key(mbedtls_x509write_cert *ctx,
+                                           mbedtls_pk_context *key)
 {
     ctx->subject_key = key;
 }
 
-void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx,
-                                           mbedtls_pk_context *key )
+void mbedtls_x509write_crt_set_issuer_key(mbedtls_x509write_cert *ctx,
+                                          mbedtls_pk_context *key)
 {
     ctx->issuer_key = key;
 }
 
-int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx,
-                                            const char *subject_name )
+int mbedtls_x509write_crt_set_subject_name(mbedtls_x509write_cert *ctx,
+                                           const char *subject_name)
 {
-    return mbedtls_x509_string_to_names( &ctx->subject, subject_name );
+    return mbedtls_x509_string_to_names(&ctx->subject, subject_name);
 }
 
-int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx,
-                                           const char *issuer_name )
+int mbedtls_x509write_crt_set_issuer_name(mbedtls_x509write_cert *ctx,
+                                          const char *issuer_name)
 {
-    return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name );
+    return mbedtls_x509_string_to_names(&ctx->issuer, issuer_name);
 }
 
-int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx,
-                                      const mbedtls_mpi *serial )
+#if defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
+int mbedtls_x509write_crt_set_serial(mbedtls_x509write_cert *ctx,
+                                     const mbedtls_mpi *serial)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    int ret;
+    size_t tmp_len;
 
-    if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 )
-        return( ret );
-
-    return( 0 );
-}
-
-int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx,
-                                        const char *not_before,
-                                        const char *not_after )
-{
-    if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ||
-        strlen( not_after )  != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 )
-    {
-        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+    /* Ensure that the MPI value fits into the buffer */
+    tmp_len = mbedtls_mpi_size(serial);
+    if (tmp_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
     }
-    strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
-    strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
+
+    ctx->serial_len = tmp_len;
+
+    ret = mbedtls_mpi_write_binary(serial, ctx->serial, tmp_len);
+    if (ret < 0) {
+        return ret;
+    }
+
+    return 0;
+}
+#endif // MBEDTLS_BIGNUM_C && !MBEDTLS_DEPRECATED_REMOVED
+
+int mbedtls_x509write_crt_set_serial_raw(mbedtls_x509write_cert *ctx,
+                                         unsigned char *serial, size_t serial_len)
+{
+    if (serial_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
+
+    ctx->serial_len = serial_len;
+    memcpy(ctx->serial, serial, serial_len);
+
+    return 0;
+}
+
+int mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert *ctx,
+                                       const char *not_before,
+                                       const char *not_after)
+{
+    if (strlen(not_before) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ||
+        strlen(not_after)  != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
+    strncpy(ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN);
+    strncpy(ctx->not_after, not_after, MBEDTLS_X509_RFC5280_UTC_TIME_LEN);
     ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
     ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx,
-                                 const char *oid, size_t oid_len,
-                                 int critical,
-                                 const unsigned char *val, size_t val_len )
+int mbedtls_x509write_crt_set_extension(mbedtls_x509write_cert *ctx,
+                                        const char *oid, size_t oid_len,
+                                        int critical,
+                                        const unsigned char *val, size_t val_len)
 {
-    return( mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,
-                                        critical, val, val_len ) );
+    return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len,
+                                      critical, val, val_len);
 }
 
-int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx,
-                                                 int is_ca, int max_pathlen )
+int mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert *ctx,
+                                                int is_ca, int max_pathlen)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char buf[9];
     unsigned char *c = buf + sizeof(buf);
     size_t len = 0;
 
-    memset( buf, 0, sizeof(buf) );
+    memset(buf, 0, sizeof(buf));
 
-    if( is_ca && max_pathlen > 127 )
-        return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
-
-    if( is_ca )
-    {
-        if( max_pathlen >= 0 )
-        {
-            MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf,
-                                                               max_pathlen ) );
-        }
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) );
+    if (is_ca && max_pathlen > 127) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
     }
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf,
-                                                MBEDTLS_ASN1_CONSTRUCTED |
-                                                MBEDTLS_ASN1_SEQUENCE ) );
+    if (is_ca) {
+        if (max_pathlen >= 0) {
+            MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf,
+                                                             max_pathlen));
+        }
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_bool(&c, buf, 1));
+    }
 
-    return(
-        mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,
-                             MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ),
-                             is_ca, buf + sizeof(buf) - len, len ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf,
+                                                     MBEDTLS_ASN1_CONSTRUCTED |
+                                                     MBEDTLS_ASN1_SEQUENCE));
+
+    return
+        mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,
+                                            MBEDTLS_OID_SIZE(MBEDTLS_OID_BASIC_CONSTRAINTS),
+                                            is_ca, buf + sizeof(buf) - len, len);
 }
 
-#if defined(MBEDTLS_SHA1_C)
-int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx )
+#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+static int mbedtls_x509write_crt_set_key_identifier(mbedtls_x509write_cert *ctx,
+                                                    int is_ca,
+                                                    unsigned char tag)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
     unsigned char *c = buf + sizeof(buf);
     size_t len = 0;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t hash_length;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-    memset( buf, 0, sizeof(buf) );
-    MBEDTLS_ASN1_CHK_ADD( len,
-                mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) );
+    memset(buf, 0, sizeof(buf));
+    MBEDTLS_ASN1_CHK_ADD(len,
+                         mbedtls_pk_write_pubkey(&c,
+                                                 buf,
+                                                 is_ca ?
+                                                 ctx->issuer_key :
+                                                 ctx->subject_key));
 
-    ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len,
-                            buf + sizeof( buf ) - 20 );
-    if( ret != 0 )
-        return( ret );
-    c = buf + sizeof( buf ) - 20;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    status = psa_hash_compute(PSA_ALG_SHA_1,
+                              buf + sizeof(buf) - len,
+                              len,
+                              buf + sizeof(buf) - 20,
+                              20,
+                              &hash_length);
+    if (status != PSA_SUCCESS) {
+        return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+    }
+#else
+    ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1),
+                     buf + sizeof(buf) - len, len,
+                     buf + sizeof(buf) - 20);
+    if (ret != 0) {
+        return ret;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    c = buf + sizeof(buf) - 20;
     len = 20;
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len,
-            mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, tag));
 
-    return mbedtls_x509write_crt_set_extension( ctx,
-                 MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
-                 MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ),
-                 0, buf + sizeof(buf) - len, len );
+    if (is_ca) { // writes AuthorityKeyIdentifier sequence
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
+        MBEDTLS_ASN1_CHK_ADD(len,
+                             mbedtls_asn1_write_tag(&c,
+                                                    buf,
+                                                    MBEDTLS_ASN1_CONSTRUCTED |
+                                                    MBEDTLS_ASN1_SEQUENCE));
+    }
+
+    if (is_ca) {
+        return mbedtls_x509write_crt_set_extension(ctx,
+                                                   MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
+                                                   MBEDTLS_OID_SIZE(
+                                                       MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER),
+                                                   0, buf + sizeof(buf) - len, len);
+    } else {
+        return mbedtls_x509write_crt_set_extension(ctx,
+                                                   MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
+                                                   MBEDTLS_OID_SIZE(
+                                                       MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER),
+                                                   0, buf + sizeof(buf) - len, len);
+    }
 }
 
-int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx )
+int mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert *ctx)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
-    unsigned char *c = buf + sizeof( buf );
-    size_t len = 0;
-
-    memset( buf, 0, sizeof(buf) );
-    MBEDTLS_ASN1_CHK_ADD( len,
-                          mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) );
-
-    ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len,
-                            buf + sizeof( buf ) - 20 );
-    if( ret != 0 )
-        return( ret );
-    c = buf + sizeof( buf ) - 20;
-    len = 20;
-
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len,
-        mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) );
-
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len,
-                          mbedtls_asn1_write_tag( &c, buf,
-                                                  MBEDTLS_ASN1_CONSTRUCTED |
-                                                  MBEDTLS_ASN1_SEQUENCE ) );
-
-    return mbedtls_x509write_crt_set_extension(
-        ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
-        MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ),
-        0, buf + sizeof( buf ) - len, len );
+    return mbedtls_x509write_crt_set_key_identifier(ctx,
+                                                    0,
+                                                    MBEDTLS_ASN1_OCTET_STRING);
 }
-#endif /* MBEDTLS_SHA1_C */
 
-int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx,
-                                         unsigned int key_usage )
+int mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *ctx)
 {
-    unsigned char buf[5] = {0}, ku[2] = {0};
+    return mbedtls_x509write_crt_set_key_identifier(ctx,
+                                                    1,
+                                                    (MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0));
+}
+#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+
+int mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert *ctx,
+                                        unsigned int key_usage)
+{
+    unsigned char buf[5] = { 0 }, ku[2] = { 0 };
     unsigned char *c;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
-        MBEDTLS_X509_KU_NON_REPUDIATION   |
-        MBEDTLS_X509_KU_KEY_ENCIPHERMENT  |
-        MBEDTLS_X509_KU_DATA_ENCIPHERMENT |
-        MBEDTLS_X509_KU_KEY_AGREEMENT     |
-        MBEDTLS_X509_KU_KEY_CERT_SIGN     |
-        MBEDTLS_X509_KU_CRL_SIGN          |
-        MBEDTLS_X509_KU_ENCIPHER_ONLY     |
-        MBEDTLS_X509_KU_DECIPHER_ONLY;
+                                      MBEDTLS_X509_KU_NON_REPUDIATION   |
+                                      MBEDTLS_X509_KU_KEY_ENCIPHERMENT  |
+                                      MBEDTLS_X509_KU_DATA_ENCIPHERMENT |
+                                      MBEDTLS_X509_KU_KEY_AGREEMENT     |
+                                      MBEDTLS_X509_KU_KEY_CERT_SIGN     |
+                                      MBEDTLS_X509_KU_CRL_SIGN          |
+                                      MBEDTLS_X509_KU_ENCIPHER_ONLY     |
+                                      MBEDTLS_X509_KU_DECIPHER_ONLY;
 
     /* Check that nothing other than the allowed flags is set */
-    if( ( key_usage & ~allowed_bits ) != 0 )
-        return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
+    if ((key_usage & ~allowed_bits) != 0) {
+        return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
+    }
 
     c = buf + 5;
-    MBEDTLS_PUT_UINT16_LE( key_usage, ku, 0 );
-    ret = mbedtls_asn1_write_named_bitstring( &c, buf, ku, 9 );
+    MBEDTLS_PUT_UINT16_LE(key_usage, ku, 0);
+    ret = mbedtls_asn1_write_named_bitstring(&c, buf, ku, 9);
 
-    if( ret < 0 )
-        return( ret );
-    else if( ret < 3 || ret > 5 )
-        return( MBEDTLS_ERR_X509_INVALID_FORMAT );
+    if (ret < 0) {
+        return ret;
+    } else if (ret < 3 || ret > 5) {
+        return MBEDTLS_ERR_X509_INVALID_FORMAT;
+    }
 
-    ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
-                                   MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
-                                   1, c, (size_t)ret );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_KEY_USAGE,
+                                              MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE),
+                                              1, c, (size_t) ret);
+    if (ret != 0) {
+        return ret;
+    }
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
-                                    unsigned char ns_cert_type )
+int mbedtls_x509write_crt_set_ext_key_usage(mbedtls_x509write_cert *ctx,
+                                            const mbedtls_asn1_sequence *exts)
 {
-    unsigned char buf[4] = {0};
+    unsigned char buf[256];
+    unsigned char *c = buf + sizeof(buf);
+    int ret;
+    size_t len = 0;
+    const mbedtls_asn1_sequence *last_ext = NULL;
+    const mbedtls_asn1_sequence *ext;
+
+    memset(buf, 0, sizeof(buf));
+
+    /* We need at least one extension: SEQUENCE SIZE (1..MAX) OF KeyPurposeId */
+    if (exts == NULL) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
+
+    /* Iterate over exts backwards, so we write them out in the requested order */
+    while (last_ext != exts) {
+        for (ext = exts; ext->next != last_ext; ext = ext->next) {
+        }
+        if (ext->buf.tag != MBEDTLS_ASN1_OID) {
+            return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+        }
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf, ext->buf.p, ext->buf.len));
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, ext->buf.len));
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_OID));
+        last_ext = ext;
+    }
+
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
+    MBEDTLS_ASN1_CHK_ADD(len,
+                         mbedtls_asn1_write_tag(&c, buf,
+                                                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
+
+    return mbedtls_x509write_crt_set_extension(ctx,
+                                               MBEDTLS_OID_EXTENDED_KEY_USAGE,
+                                               MBEDTLS_OID_SIZE(MBEDTLS_OID_EXTENDED_KEY_USAGE),
+                                               1, c, len);
+}
+
+int mbedtls_x509write_crt_set_ns_cert_type(mbedtls_x509write_cert *ctx,
+                                           unsigned char ns_cert_type)
+{
+    unsigned char buf[4] = { 0 };
     unsigned char *c;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     c = buf + 4;
 
-    ret = mbedtls_asn1_write_named_bitstring( &c, buf, &ns_cert_type, 8 );
-    if( ret < 3 || ret > 4 )
-        return( ret );
+    ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8);
+    if (ret < 3 || ret > 4) {
+        return ret;
+    }
 
-    ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
-                                   MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
-                                   0, c, (size_t)ret );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE,
+                                              MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE),
+                                              0, c, (size_t) ret);
+    if (ret != 0) {
+        return ret;
+    }
 
-    return( 0 );
+    return 0;
 }
 
-static int x509_write_time( unsigned char **p, unsigned char *start,
-                            const char *t, size_t size )
+static int x509_write_time(unsigned char **p, unsigned char *start,
+                           const char *t, size_t size)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
@@ -299,39 +397,42 @@
     /*
      * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
      */
-    if( t[0] < '2' || ( t[0] == '2' && t[1] == '0' && t[2] < '5' ) )
-    {
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
-                                             (const unsigned char *) t + 2,
-                                             size - 2 ) );
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
-                                             MBEDTLS_ASN1_UTC_TIME ) );
-    }
-    else
-    {
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
-                                                  (const unsigned char *) t,
-                                                  size ) );
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
-                                             MBEDTLS_ASN1_GENERALIZED_TIME ) );
+    if (t[0] < '2' || (t[0] == '2' && t[1] == '0' && t[2] < '5')) {
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
+                                                                (const unsigned char *) t + 2,
+                                                                size - 2));
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
+                                                         MBEDTLS_ASN1_UTC_TIME));
+    } else {
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
+                                                                (const unsigned char *) t,
+                                                                size));
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
+                                                         MBEDTLS_ASN1_GENERALIZED_TIME));
     }
 
-    return( (int) len );
+    return (int) len;
 }
 
-int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx,
-                               unsigned char *buf, size_t size,
-                               int (*f_rng)(void *, unsigned char *, size_t),
-                               void *p_rng )
+int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx,
+                              unsigned char *buf, size_t size,
+                              int (*f_rng)(void *, unsigned char *, size_t),
+                              void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const char *sig_oid;
     size_t sig_oid_len = 0;
     unsigned char *c, *c2;
-    unsigned char hash[64];
     unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE];
+    size_t hash_length = 0;
+    unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_algorithm_t psa_algorithm;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
     size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
     size_t len = 0;
     mbedtls_pk_type_t pk_alg;
@@ -345,17 +446,17 @@
 
     /* There's no direct way of extracting a signature algorithm
      * (represented as an element of mbedtls_pk_type_t) from a PK instance. */
-    if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) )
+    if (mbedtls_pk_can_do(ctx->issuer_key, MBEDTLS_PK_RSA)) {
         pk_alg = MBEDTLS_PK_RSA;
-    else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) )
+    } else if (mbedtls_pk_can_do(ctx->issuer_key, MBEDTLS_PK_ECDSA)) {
         pk_alg = MBEDTLS_PK_ECDSA;
-    else
-        return( MBEDTLS_ERR_X509_INVALID_ALG );
+    } else {
+        return MBEDTLS_ERR_X509_INVALID_ALG;
+    }
 
-    if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
-                                          &sig_oid, &sig_oid_len ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg,
+                                              &sig_oid, &sig_oid_len)) != 0) {
+        return ret;
     }
 
     /*
@@ -363,38 +464,37 @@
      */
 
     /* Only for v3 */
-    if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 )
-    {
-        MBEDTLS_ASN1_CHK_ADD( len,
-                              mbedtls_x509_write_extensions( &c,
-                                                      buf, ctx->extensions ) );
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
-        MBEDTLS_ASN1_CHK_ADD( len,
-                              mbedtls_asn1_write_tag( &c, buf,
-                                                      MBEDTLS_ASN1_CONSTRUCTED |
-                                                      MBEDTLS_ASN1_SEQUENCE ) );
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
-        MBEDTLS_ASN1_CHK_ADD( len,
-                              mbedtls_asn1_write_tag( &c, buf,
-                                               MBEDTLS_ASN1_CONTEXT_SPECIFIC |
-                                               MBEDTLS_ASN1_CONSTRUCTED | 3 ) );
+    if (ctx->version == MBEDTLS_X509_CRT_VERSION_3) {
+        MBEDTLS_ASN1_CHK_ADD(len,
+                             mbedtls_x509_write_extensions(&c,
+                                                           buf, ctx->extensions));
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
+        MBEDTLS_ASN1_CHK_ADD(len,
+                             mbedtls_asn1_write_tag(&c, buf,
+                                                    MBEDTLS_ASN1_CONSTRUCTED |
+                                                    MBEDTLS_ASN1_SEQUENCE));
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
+        MBEDTLS_ASN1_CHK_ADD(len,
+                             mbedtls_asn1_write_tag(&c, buf,
+                                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC |
+                                                    MBEDTLS_ASN1_CONSTRUCTED | 3));
     }
 
     /*
      *  SubjectPublicKeyInfo
      */
-    MBEDTLS_ASN1_CHK_ADD( pub_len,
-                          mbedtls_pk_write_pubkey_der( ctx->subject_key,
-                                                       buf, c - buf ) );
+    MBEDTLS_ASN1_CHK_ADD(pub_len,
+                         mbedtls_pk_write_pubkey_der(ctx->subject_key,
+                                                     buf, c - buf));
     c -= pub_len;
     len += pub_len;
 
     /*
      *  Subject  ::=  Name
      */
-    MBEDTLS_ASN1_CHK_ADD( len,
-                          mbedtls_x509_write_names( &c, buf,
-                                                    ctx->subject ) );
+    MBEDTLS_ASN1_CHK_ADD(len,
+                         mbedtls_x509_write_names(&c, buf,
+                                                  ctx->subject));
 
     /*
      *  Validity ::= SEQUENCE {
@@ -403,93 +503,126 @@
      */
     sub_len = 0;
 
-    MBEDTLS_ASN1_CHK_ADD( sub_len,
-                          x509_write_time( &c, buf, ctx->not_after,
-                                        MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
+    MBEDTLS_ASN1_CHK_ADD(sub_len,
+                         x509_write_time(&c, buf, ctx->not_after,
+                                         MBEDTLS_X509_RFC5280_UTC_TIME_LEN));
 
-    MBEDTLS_ASN1_CHK_ADD( sub_len,
-                          x509_write_time( &c, buf, ctx->not_before,
-                                        MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
+    MBEDTLS_ASN1_CHK_ADD(sub_len,
+                         x509_write_time(&c, buf, ctx->not_before,
+                                         MBEDTLS_X509_RFC5280_UTC_TIME_LEN));
 
     len += sub_len;
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, sub_len ) );
-    MBEDTLS_ASN1_CHK_ADD( len,
-                          mbedtls_asn1_write_tag( &c, buf,
-                                                  MBEDTLS_ASN1_CONSTRUCTED |
-                                                  MBEDTLS_ASN1_SEQUENCE ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, sub_len));
+    MBEDTLS_ASN1_CHK_ADD(len,
+                         mbedtls_asn1_write_tag(&c, buf,
+                                                MBEDTLS_ASN1_CONSTRUCTED |
+                                                MBEDTLS_ASN1_SEQUENCE));
 
     /*
      *  Issuer  ::=  Name
      */
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, buf,
-                                                         ctx->issuer ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf,
+                                                       ctx->issuer));
 
     /*
      *  Signature   ::=  AlgorithmIdentifier
      */
-    MBEDTLS_ASN1_CHK_ADD( len,
-                          mbedtls_asn1_write_algorithm_identifier( &c, buf,
-                                              sig_oid, strlen( sig_oid ), 0 ) );
+    MBEDTLS_ASN1_CHK_ADD(len,
+                         mbedtls_asn1_write_algorithm_identifier(&c, buf,
+                                                                 sig_oid, strlen(sig_oid), 0));
 
     /*
      *  Serial   ::=  INTEGER
+     *
+     * Written data is:
+     * - "ctx->serial_len" bytes for the raw serial buffer
+     *   - if MSb of "serial" is 1, then prepend an extra 0x00 byte
+     * - 1 byte for the length
+     * - 1 byte for the TAG
      */
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf,
-                                                       &ctx->serial ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf,
+                                                            ctx->serial, ctx->serial_len));
+    if (*c & 0x80) {
+        if (c - buf < 1) {
+            return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
+        }
+        *(--c) = 0x0;
+        len++;
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf,
+                                                         ctx->serial_len + 1));
+    } else {
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf,
+                                                         ctx->serial_len));
+    }
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf,
+                                                     MBEDTLS_ASN1_INTEGER));
 
     /*
      *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
      */
 
     /* Can be omitted for v1 */
-    if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 )
-    {
+    if (ctx->version != MBEDTLS_X509_CRT_VERSION_1) {
         sub_len = 0;
-        MBEDTLS_ASN1_CHK_ADD( sub_len,
-                              mbedtls_asn1_write_int( &c, buf, ctx->version ) );
+        MBEDTLS_ASN1_CHK_ADD(sub_len,
+                             mbedtls_asn1_write_int(&c, buf, ctx->version));
         len += sub_len;
-        MBEDTLS_ASN1_CHK_ADD( len,
-                              mbedtls_asn1_write_len( &c, buf, sub_len ) );
-        MBEDTLS_ASN1_CHK_ADD( len,
-                              mbedtls_asn1_write_tag( &c, buf,
-                                               MBEDTLS_ASN1_CONTEXT_SPECIFIC |
-                                               MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
+        MBEDTLS_ASN1_CHK_ADD(len,
+                             mbedtls_asn1_write_len(&c, buf, sub_len));
+        MBEDTLS_ASN1_CHK_ADD(len,
+                             mbedtls_asn1_write_tag(&c, buf,
+                                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC |
+                                                    MBEDTLS_ASN1_CONSTRUCTED | 0));
     }
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len,
-                mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
-                                                     MBEDTLS_ASN1_SEQUENCE ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
+    MBEDTLS_ASN1_CHK_ADD(len,
+                         mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
+                                                MBEDTLS_ASN1_SEQUENCE));
 
     /*
      * Make signature
      */
 
     /* Compute hash of CRT. */
-    if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c,
-                            len, hash ) ) != 0 )
-    {
-        return( ret );
-    }
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_algorithm = mbedtls_hash_info_psa_from_md(ctx->md_alg);
 
-    if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg,
-                                 hash, 0, sig, &sig_len,
-                                 f_rng, p_rng ) ) != 0 )
-    {
-        return( ret );
+    status = psa_hash_compute(psa_algorithm,
+                              c,
+                              len,
+                              hash,
+                              sizeof(hash),
+                              &hash_length);
+    if (status != PSA_SUCCESS) {
+        return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+    }
+#else
+    if ((ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c,
+                          len, hash)) != 0) {
+        return ret;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+
+    if ((ret = mbedtls_pk_sign(ctx->issuer_key, ctx->md_alg,
+                               hash, hash_length, sig, sizeof(sig), &sig_len,
+                               f_rng, p_rng)) != 0) {
+        return ret;
     }
 
     /* Move CRT to the front of the buffer to have space
      * for the signature. */
-    memmove( buf, c, len );
+    memmove(buf, c, len);
     c = buf + len;
 
     /* Add signature at the end of the buffer,
      * making sure that it doesn't underflow
      * into the CRT buffer. */
     c2 = buf + size;
-    MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, c,
-                                        sig_oid, sig_oid_len, sig, sig_len ) );
+    MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len, mbedtls_x509_write_sig(&c2, c,
+                                                                 sig_oid, sig_oid_len, sig,
+                                                                 sig_len));
 
     /*
      * Memory layout after this step:
@@ -500,43 +633,41 @@
 
     /* Move raw CRT to just before the signature. */
     c = c2 - len;
-    memmove( c, buf, len );
+    memmove(c, buf, len);
 
     len += sig_and_oid_len;
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf,
-                                                 MBEDTLS_ASN1_CONSTRUCTED |
-                                                 MBEDTLS_ASN1_SEQUENCE ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf,
+                                                     MBEDTLS_ASN1_CONSTRUCTED |
+                                                     MBEDTLS_ASN1_SEQUENCE));
 
-    return( (int) len );
+    return (int) len;
 }
 
 #define PEM_BEGIN_CRT           "-----BEGIN CERTIFICATE-----\n"
 #define PEM_END_CRT             "-----END CERTIFICATE-----\n"
 
 #if defined(MBEDTLS_PEM_WRITE_C)
-int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt,
-                               unsigned char *buf, size_t size,
-                               int (*f_rng)(void *, unsigned char *, size_t),
-                               void *p_rng )
+int mbedtls_x509write_crt_pem(mbedtls_x509write_cert *crt,
+                              unsigned char *buf, size_t size,
+                              int (*f_rng)(void *, unsigned char *, size_t),
+                              void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t olen;
 
-    if( ( ret = mbedtls_x509write_crt_der( crt, buf, size,
-                                   f_rng, p_rng ) ) < 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_x509write_crt_der(crt, buf, size,
+                                         f_rng, p_rng)) < 0) {
+        return ret;
     }
 
-    if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT,
-                                          buf + size - ret, ret,
-                                          buf, size, &olen ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CRT, PEM_END_CRT,
+                                        buf + size - ret, ret,
+                                        buf, size, &olen)) != 0) {
+        return ret;
     }
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_PEM_WRITE_C */
 
diff --git a/lib/libmbedtls/mbedtls/library/x509write_csr.c b/lib/libmbedtls/mbedtls/library/x509write_csr.c
index afda950..deb6617 100644
--- a/lib/libmbedtls/mbedtls/library/x509write_csr.c
+++ b/lib/libmbedtls/mbedtls/library/x509write_csr.c
@@ -26,6 +26,7 @@
 
 #if defined(MBEDTLS_X509_CSR_WRITE_C)
 
+#include "mbedtls/x509.h"
 #include "mbedtls/x509_csr.h"
 #include "mbedtls/asn1write.h"
 #include "mbedtls/error.h"
@@ -35,7 +36,8 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 #include "psa/crypto.h"
 #include "mbedtls/psa_util.h"
-#endif
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#include "hash_info.h"
 
 #include <string.h>
 #include <stdlib.h>
@@ -44,220 +46,314 @@
 #include "mbedtls/pem.h"
 #endif
 
-#if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc    calloc
-#define mbedtls_free      free
-#endif
 
-void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx )
+void mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx)
 {
-    memset( ctx, 0, sizeof( mbedtls_x509write_csr ) );
+    memset(ctx, 0, sizeof(mbedtls_x509write_csr));
 }
 
-void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx )
+void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx)
 {
-    mbedtls_asn1_free_named_data_list( &ctx->subject );
-    mbedtls_asn1_free_named_data_list( &ctx->extensions );
+    mbedtls_asn1_free_named_data_list(&ctx->subject);
+    mbedtls_asn1_free_named_data_list(&ctx->extensions);
 
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_csr ) );
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_csr));
 }
 
-void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg )
+void mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg)
 {
     ctx->md_alg = md_alg;
 }
 
-void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key )
+void mbedtls_x509write_csr_set_key(mbedtls_x509write_csr *ctx, mbedtls_pk_context *key)
 {
     ctx->key = key;
 }
 
-int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx,
-                                    const char *subject_name )
+int mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr *ctx,
+                                           const char *subject_name)
 {
-    return mbedtls_x509_string_to_names( &ctx->subject, subject_name );
+    return mbedtls_x509_string_to_names(&ctx->subject, subject_name);
 }
 
-int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx,
-                                 const char *oid, size_t oid_len,
-                                 const unsigned char *val, size_t val_len )
+int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx,
+                                        const char *oid, size_t oid_len,
+                                        int critical,
+                                        const unsigned char *val, size_t val_len)
 {
-    return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,
-                               0, val, val_len );
+    return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len,
+                                      critical, val, val_len);
 }
 
-int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage )
+int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx,
+                                                       const mbedtls_x509_san_list *san_list)
 {
-    unsigned char buf[4] = {0};
+    int ret = 0;
+    const mbedtls_x509_san_list *cur;
+    unsigned char *buf;
+    unsigned char *p;
+    size_t len;
+    size_t buflen = 0;
+
+    /* Determine the maximum size of the SubjectAltName list */
+    for (cur = san_list; cur != NULL; cur = cur->next) {
+        /* Calculate size of the required buffer */
+        switch (cur->node.type) {
+            case MBEDTLS_X509_SAN_DNS_NAME:
+            case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
+            case MBEDTLS_X509_SAN_IP_ADDRESS:
+                /* length of value for each name entry,
+                 * maximum 4 bytes for the length field,
+                 * 1 byte for the tag/type.
+                 */
+                buflen += cur->node.san.unstructured_name.len + 4 + 1;
+                break;
+
+            default:
+                /* Not supported - skip. */
+                break;
+        }
+    }
+
+    /* Add the extra length field and tag */
+    buflen += 4 + 1;
+
+    /* Allocate buffer */
+    buf = mbedtls_calloc(1, buflen);
+    if (buf == NULL) {
+        return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
+    }
+
+    mbedtls_platform_zeroize(buf, buflen);
+    p = buf + buflen;
+
+    /* Write ASN.1-based structure */
+    cur = san_list;
+    len = 0;
+    while (cur != NULL) {
+        switch (cur->node.type) {
+            case MBEDTLS_X509_SAN_DNS_NAME:
+            case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
+            case MBEDTLS_X509_SAN_IP_ADDRESS:
+            {
+                const unsigned char *unstructured_name =
+                    (const unsigned char *) cur->node.san.unstructured_name.p;
+                size_t unstructured_name_len = cur->node.san.unstructured_name.len;
+
+                MBEDTLS_ASN1_CHK_CLEANUP_ADD(len,
+                                             mbedtls_asn1_write_raw_buffer(
+                                                 &p, buf,
+                                                 unstructured_name, unstructured_name_len));
+                MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(
+                                                 &p, buf, unstructured_name_len));
+                MBEDTLS_ASN1_CHK_CLEANUP_ADD(len,
+                                             mbedtls_asn1_write_tag(
+                                                 &p, buf,
+                                                 MBEDTLS_ASN1_CONTEXT_SPECIFIC | cur->node.type));
+            }
+            break;
+            default:
+                /* Skip unsupported names. */
+                break;
+        }
+        cur = cur->next;
+    }
+
+    MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(&p, buf, len));
+    MBEDTLS_ASN1_CHK_CLEANUP_ADD(len,
+                                 mbedtls_asn1_write_tag(&p, buf,
+                                                        MBEDTLS_ASN1_CONSTRUCTED |
+                                                        MBEDTLS_ASN1_SEQUENCE));
+
+    ret = mbedtls_x509write_csr_set_extension(
+        ctx,
+        MBEDTLS_OID_SUBJECT_ALT_NAME,
+        MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME),
+        0,
+        buf + buflen - len,
+        len);
+
+    /* If we exceeded the allocated buffer it means that maximum size of the SubjectAltName list
+     * was incorrectly calculated and memory is corrupted. */
+    if (p < buf) {
+        ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+    }
+
+cleanup:
+    mbedtls_free(buf);
+    return ret;
+}
+
+int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage)
+{
+    unsigned char buf[4] = { 0 };
     unsigned char *c;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     c = buf + 4;
 
-    ret = mbedtls_asn1_write_named_bitstring( &c, buf, &key_usage, 8 );
-    if( ret < 3 || ret > 4 )
-        return( ret );
+    ret = mbedtls_asn1_write_named_bitstring(&c, buf, &key_usage, 8);
+    if (ret < 3 || ret > 4) {
+        return ret;
+    }
 
-    ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
-                                       MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
-                                       c, (size_t)ret );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_KEY_USAGE,
+                                              MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE),
+                                              0, c, (size_t) ret);
+    if (ret != 0) {
+        return ret;
+    }
 
-    return( 0 );
+    return 0;
 }
 
-int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx,
-                                    unsigned char ns_cert_type )
+int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx,
+                                           unsigned char ns_cert_type)
 {
-    unsigned char buf[4] = {0};
+    unsigned char buf[4] = { 0 };
     unsigned char *c;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     c = buf + 4;
 
-    ret = mbedtls_asn1_write_named_bitstring( &c, buf, &ns_cert_type, 8 );
-    if( ret < 3 || ret > 4 )
-        return( ret );
+    ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8);
+    if (ret < 3 || ret > 4) {
+        return ret;
+    }
 
-    ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
-                                       MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
-                                       c, (size_t)ret );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE,
+                                              MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE),
+                                              0, c, (size_t) ret);
+    if (ret != 0) {
+        return ret;
+    }
 
-    return( 0 );
+    return 0;
 }
 
-static int x509write_csr_der_internal( mbedtls_x509write_csr *ctx,
-                                 unsigned char *buf,
-                                 size_t size,
-                                 unsigned char *sig,
-                                 int (*f_rng)(void *, unsigned char *, size_t),
-                                 void *p_rng )
+static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx,
+                                      unsigned char *buf,
+                                      size_t size,
+                                      unsigned char *sig, size_t sig_size,
+                                      int (*f_rng)(void *, unsigned char *, size_t),
+                                      void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const char *sig_oid;
     size_t sig_oid_len = 0;
     unsigned char *c, *c2;
-    unsigned char hash[64];
+    unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
     size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
     size_t len = 0;
     mbedtls_pk_type_t pk_alg;
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT;
     size_t hash_len;
-    psa_algorithm_t hash_alg = mbedtls_psa_translate_md( ctx->md_alg );
+    psa_algorithm_t hash_alg = mbedtls_hash_info_psa_from_md(ctx->md_alg);
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
     /* Write the CSR backwards starting from the end of buf */
     c = buf + size;
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, buf,
-                                                           ctx->extensions ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_extensions(&c, buf,
+                                                            ctx->extensions));
 
-    if( len )
-    {
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
-        MBEDTLS_ASN1_CHK_ADD( len,
-            mbedtls_asn1_write_tag(
-                &c, buf,
-                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
+    if (len) {
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
+        MBEDTLS_ASN1_CHK_ADD(len,
+                             mbedtls_asn1_write_tag(
+                                 &c, buf,
+                                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
 
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
-        MBEDTLS_ASN1_CHK_ADD( len,
-            mbedtls_asn1_write_tag(
-                &c, buf,
-                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) );
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
+        MBEDTLS_ASN1_CHK_ADD(len,
+                             mbedtls_asn1_write_tag(
+                                 &c, buf,
+                                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET));
 
-        MBEDTLS_ASN1_CHK_ADD( len,
-            mbedtls_asn1_write_oid(
-                &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ,
-                MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) );
+        MBEDTLS_ASN1_CHK_ADD(len,
+                             mbedtls_asn1_write_oid(
+                                 &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ,
+                                 MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_EXT_REQ)));
 
-        MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
-        MBEDTLS_ASN1_CHK_ADD( len,
-            mbedtls_asn1_write_tag(
-                &c, buf,
-                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
+        MBEDTLS_ASN1_CHK_ADD(len,
+                             mbedtls_asn1_write_tag(
+                                 &c, buf,
+                                 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
     }
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len,
-        mbedtls_asn1_write_tag(
-            &c, buf,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
+    MBEDTLS_ASN1_CHK_ADD(len,
+                         mbedtls_asn1_write_tag(
+                             &c, buf,
+                             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC));
 
-    MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key,
-                                                              buf, c - buf ) );
+    MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_pk_write_pubkey_der(ctx->key,
+                                                              buf, c - buf));
     c -= pub_len;
     len += pub_len;
 
     /*
      *  Subject  ::=  Name
      */
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, buf,
-                                                         ctx->subject ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf,
+                                                       ctx->subject));
 
     /*
      *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
      */
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0));
 
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len,
-        mbedtls_asn1_write_tag(
-            &c, buf,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
+    MBEDTLS_ASN1_CHK_ADD(len,
+                         mbedtls_asn1_write_tag(
+                             &c, buf,
+                             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
 
     /*
      * Sign the written CSR data into the sig buffer
      * Note: hash errors can happen only after an internal error
      */
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( psa_hash_setup( &hash_operation, hash_alg ) != PSA_SUCCESS )
-        return( MBEDTLS_ERR_X509_FATAL_ERROR );
-
-    if( psa_hash_update( &hash_operation, c, len ) != PSA_SUCCESS )
-        return( MBEDTLS_ERR_X509_FATAL_ERROR );
-
-    if( psa_hash_finish( &hash_operation, hash, sizeof( hash ), &hash_len )
-        != PSA_SUCCESS )
-    {
-        return( MBEDTLS_ERR_X509_FATAL_ERROR );
+    if (psa_hash_compute(hash_alg,
+                         c,
+                         len,
+                         hash,
+                         sizeof(hash),
+                         &hash_len) != PSA_SUCCESS) {
+        return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
     }
 #else /* MBEDTLS_USE_PSA_CRYPTO */
-    ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash );
-    if( ret != 0 )
-        return( ret );
+    ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len, hash);
+    if (ret != 0) {
+        return ret;
+    }
 #endif
-    if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
-                                 f_rng, p_rng ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_pk_sign(ctx->key, ctx->md_alg, hash, 0,
+                               sig, sig_size, &sig_len,
+                               f_rng, p_rng)) != 0) {
+        return ret;
     }
 
-    if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_RSA ) )
+    if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_RSA)) {
         pk_alg = MBEDTLS_PK_RSA;
-    else if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_ECDSA ) )
+    } else if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_ECDSA)) {
         pk_alg = MBEDTLS_PK_ECDSA;
-    else
-        return( MBEDTLS_ERR_X509_INVALID_ALG );
+    } else {
+        return MBEDTLS_ERR_X509_INVALID_ALG;
+    }
 
-    if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
-                                              &sig_oid, &sig_oid_len ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg,
+                                              &sig_oid, &sig_oid_len)) != 0) {
+        return ret;
     }
 
     /*
      * Move the written CSR data to the start of buf to create space for
      * writing the signature into buf.
      */
-    memmove( buf, c, len );
+    memmove(buf, c, len);
 
     /*
      * Write sig and its OID into buf backwards from the end of buf.
@@ -265,76 +361,75 @@
      * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed.
      */
     c2 = buf + size;
-    MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len,
-        mbedtls_x509_write_sig( &c2, buf + len, sig_oid, sig_oid_len,
-                                sig, sig_len ) );
+    MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len,
+                         mbedtls_x509_write_sig(&c2, buf + len, sig_oid, sig_oid_len,
+                                                sig, sig_len));
 
     /*
      * Compact the space between the CSR data and signature by moving the
      * CSR data to the start of the signature.
      */
     c2 -= len;
-    memmove( c2, buf, len );
+    memmove(c2, buf, len);
 
     /* ASN encode the total size and tag the CSR data with it. */
     len += sig_and_oid_len;
-    MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) );
-    MBEDTLS_ASN1_CHK_ADD( len,
-        mbedtls_asn1_write_tag(
-            &c2, buf,
-            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c2, buf, len));
+    MBEDTLS_ASN1_CHK_ADD(len,
+                         mbedtls_asn1_write_tag(
+                             &c2, buf,
+                             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
 
     /* Zero the unused bytes at the start of buf */
-    memset( buf, 0, c2 - buf);
+    memset(buf, 0, c2 - buf);
 
-    return( (int) len );
+    return (int) len;
 }
 
-int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf,
-                               size_t size,
-                               int (*f_rng)(void *, unsigned char *, size_t),
-                               void *p_rng )
+int mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf,
+                              size_t size,
+                              int (*f_rng)(void *, unsigned char *, size_t),
+                              void *p_rng)
 {
     int ret;
     unsigned char *sig;
 
-    if( ( sig = mbedtls_calloc( 1, MBEDTLS_PK_SIGNATURE_MAX_SIZE ) ) == NULL )
-    {
-        return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+    if ((sig = mbedtls_calloc(1, MBEDTLS_PK_SIGNATURE_MAX_SIZE)) == NULL) {
+        return MBEDTLS_ERR_X509_ALLOC_FAILED;
     }
 
-    ret = x509write_csr_der_internal( ctx, buf, size, sig, f_rng, p_rng );
+    ret = x509write_csr_der_internal(ctx, buf, size,
+                                     sig, MBEDTLS_PK_SIGNATURE_MAX_SIZE,
+                                     f_rng, p_rng);
 
-    mbedtls_free( sig );
+    mbedtls_free(sig);
 
-    return( ret );
+    return ret;
 }
 
 #define PEM_BEGIN_CSR           "-----BEGIN CERTIFICATE REQUEST-----\n"
 #define PEM_END_CSR             "-----END CERTIFICATE REQUEST-----\n"
 
 #if defined(MBEDTLS_PEM_WRITE_C)
-int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,
-                       int (*f_rng)(void *, unsigned char *, size_t),
-                       void *p_rng )
+int mbedtls_x509write_csr_pem(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,
+                              int (*f_rng)(void *, unsigned char *, size_t),
+                              void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t olen = 0;
 
-    if( ( ret = mbedtls_x509write_csr_der( ctx, buf, size,
-                                   f_rng, p_rng ) ) < 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_x509write_csr_der(ctx, buf, size,
+                                         f_rng, p_rng)) < 0) {
+        return ret;
     }
 
-    if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR,
-                                  buf + size - ret,
-                                  ret, buf, size, &olen ) ) != 0 )
-    {
-        return( ret );
+    if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CSR, PEM_END_CSR,
+                                        buf + size - ret,
+                                        ret, buf, size, &olen)) != 0) {
+        return ret;
     }
 
-    return( 0 );
+    return 0;
 }
 #endif /* MBEDTLS_PEM_WRITE_C */
 
diff --git a/lib/libmbedtls/mbedtls/library/xtea.c b/lib/libmbedtls/mbedtls/library/xtea.c
deleted file mode 100644
index 77f6cb6..0000000
--- a/lib/libmbedtls/mbedtls/library/xtea.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- *  An 32-bit implementation of the XTEA algorithm
- *
- *  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.
- */
-
-#include "common.h"
-
-#if defined(MBEDTLS_XTEA_C)
-
-#include "mbedtls/xtea.h"
-#include "mbedtls/platform_util.h"
-
-#include <string.h>
-
-#if defined(MBEDTLS_SELF_TEST)
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
-#endif /* MBEDTLS_SELF_TEST */
-
-#if !defined(MBEDTLS_XTEA_ALT)
-
-void mbedtls_xtea_init( mbedtls_xtea_context *ctx )
-{
-    memset( ctx, 0, sizeof( mbedtls_xtea_context ) );
-}
-
-void mbedtls_xtea_free( mbedtls_xtea_context *ctx )
-{
-    if( ctx == NULL )
-        return;
-
-    mbedtls_platform_zeroize( ctx, sizeof( mbedtls_xtea_context ) );
-}
-
-/*
- * XTEA key schedule
- */
-void mbedtls_xtea_setup( mbedtls_xtea_context *ctx, const unsigned char key[16] )
-{
-    int i;
-
-    memset( ctx, 0, sizeof(mbedtls_xtea_context) );
-
-    for( i = 0; i < 4; i++ )
-    {
-        ctx->k[i] = MBEDTLS_GET_UINT32_BE( key, i << 2 );
-    }
-}
-
-/*
- * XTEA encrypt function
- */
-int mbedtls_xtea_crypt_ecb( mbedtls_xtea_context *ctx, int mode,
-                    const unsigned char input[8], unsigned char output[8])
-{
-    uint32_t *k, v0, v1, i;
-
-    k = ctx->k;
-
-    v0 = MBEDTLS_GET_UINT32_BE( input, 0 );
-    v1 = MBEDTLS_GET_UINT32_BE( input, 4 );
-
-    if( mode == MBEDTLS_XTEA_ENCRYPT )
-    {
-        uint32_t sum = 0, delta = 0x9E3779B9;
-
-        for( i = 0; i < 32; i++ )
-        {
-            v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
-            sum += delta;
-            v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
-        }
-    }
-    else /* MBEDTLS_XTEA_DECRYPT */
-    {
-        uint32_t delta = 0x9E3779B9, sum = delta * 32;
-
-        for( i = 0; i < 32; i++ )
-        {
-            v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
-            sum -= delta;
-            v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
-        }
-    }
-
-    MBEDTLS_PUT_UINT32_BE( v0, output, 0 );
-    MBEDTLS_PUT_UINT32_BE( v1, output, 4 );
-
-    return( 0 );
-}
-
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-/*
- * XTEA-CBC buffer encryption/decryption
- */
-int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, int mode, size_t length,
-                    unsigned char iv[8], const unsigned char *input,
-                    unsigned char *output)
-{
-    int i;
-    unsigned char temp[8];
-
-    if( length % 8 )
-        return( MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH );
-
-    if( mode == MBEDTLS_XTEA_DECRYPT )
-    {
-        while( length > 0 )
-        {
-            memcpy( temp, input, 8 );
-            mbedtls_xtea_crypt_ecb( ctx, mode, input, output );
-
-            for( i = 0; i < 8; i++ )
-                output[i] = (unsigned char)( output[i] ^ iv[i] );
-
-            memcpy( iv, temp, 8 );
-
-            input  += 8;
-            output += 8;
-            length -= 8;
-        }
-    }
-    else
-    {
-        while( length > 0 )
-        {
-            for( i = 0; i < 8; i++ )
-                output[i] = (unsigned char)( input[i] ^ iv[i] );
-
-            mbedtls_xtea_crypt_ecb( ctx, mode, output, output );
-            memcpy( iv, output, 8 );
-
-            input  += 8;
-            output += 8;
-            length -= 8;
-        }
-    }
-
-    return( 0 );
-}
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* !MBEDTLS_XTEA_ALT */
-
-#if defined(MBEDTLS_SELF_TEST)
-
-/*
- * XTEA tests vectors (non-official)
- */
-
-static const unsigned char xtea_test_key[6][16] =
-{
-   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
-     0x0c, 0x0d, 0x0e, 0x0f },
-   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
-     0x0c, 0x0d, 0x0e, 0x0f },
-   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
-     0x0c, 0x0d, 0x0e, 0x0f },
-   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-     0x00, 0x00, 0x00, 0x00 },
-   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-     0x00, 0x00, 0x00, 0x00 },
-   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-     0x00, 0x00, 0x00, 0x00 }
-};
-
-static const unsigned char xtea_test_pt[6][8] =
-{
-    { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
-    { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
-    { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f },
-    { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
-    { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
-    { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 }
-};
-
-static const unsigned char xtea_test_ct[6][8] =
-{
-    { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 },
-    { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 },
-    { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
-    { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 },
-    { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d },
-    { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }
-};
-
-/*
- * Checkup routine
- */
-int mbedtls_xtea_self_test( int verbose )
-{
-    int i, ret = 0;
-    unsigned char buf[8];
-    mbedtls_xtea_context ctx;
-
-    mbedtls_xtea_init( &ctx );
-    for( i = 0; i < 6; i++ )
-    {
-        if( verbose != 0 )
-            mbedtls_printf( "  XTEA test #%d: ", i + 1 );
-
-        memcpy( buf, xtea_test_pt[i], 8 );
-
-        mbedtls_xtea_setup( &ctx, xtea_test_key[i] );
-        mbedtls_xtea_crypt_ecb( &ctx, MBEDTLS_XTEA_ENCRYPT, buf, buf );
-
-        if( memcmp( buf, xtea_test_ct[i], 8 ) != 0 )
-        {
-            if( verbose != 0 )
-                mbedtls_printf( "failed\n" );
-
-            ret = 1;
-            goto exit;
-        }
-
-        if( verbose != 0 )
-            mbedtls_printf( "passed\n" );
-    }
-
-    if( verbose != 0 )
-        mbedtls_printf( "\n" );
-
-exit:
-    mbedtls_xtea_free( &ctx );
-
-    return( ret );
-}
-
-#endif /* MBEDTLS_SELF_TEST */
-
-#endif /* MBEDTLS_XTEA_C */