Browse Source

Switch the AES-CMAC implementation from wolfssl to mbedtls. (#75)

* Switch the AES-CMAC implementation from wolfssl to mbedtls
Don Porter 6 years ago
parent
commit
b20e34cf5f

+ 9 - 4
Pal/lib/api.h

@@ -42,9 +42,9 @@
 
 /* Libc functions */
 
-/* Libc String functions */
-int strnlen (const char *str, int maxlen);
-int strlen (const char *str);
+/* Libc String functions string.h/stdlib.h */
+size_t strnlen (const char *str, size_t maxlen);
+size_t strlen (const char *str);
 
 long strtol (const char *s, char **endptr, int base);
 int atoi (const char *nptr);
@@ -57,6 +57,11 @@ void * memmove (void *dstpp, void *srcpp, int len);
 void * memset (void *dstpp, int c, int len);
 int memcmp (const void *s1, const void *s2, int len);
 
+/* Libc memory allocation functions. stdlib.h. */
+void *malloc(size_t size);
+void free(void *ptr);
+void *calloc(size_t nmemb, size_t size);
+
 /* Some useful macro */
 /* force failure if str is not a static string */
 #define force_static(str)   ("" str "")
@@ -76,7 +81,7 @@ int memcmp (const void *s1, const void *s2, int len);
      memcpy((var), force_static(str), static_strlen(force_static(str)) + 1) + \
      static_strlen(force_static(str)))
 
-/* Libc printf functions */
+/* Libc printf functions. stdio.h/stdarg.h. */
 void fprintfmt (int (*_fputch)(void *, int, void *), void * f, void * putdat,
                 const char * fmt, ...);
 

+ 34 - 1
Pal/lib/crypto/adapters/mbedtls_adapter.c

@@ -16,8 +16,12 @@
 #include <stdint.h>
 #include "pal.h"
 #include "pal_crypto.h"
+#include "pal_error.h"
+#include "crypto/mbedtls/mbedtls/cmac.h"
 #include "crypto/mbedtls/mbedtls/sha256.h"
 
+#define BITS_PER_BYTE 8
+
 int lib_SHA256Init(LIB_SHA256_CONTEXT *context)
 {
     mbedtls_sha256_init(context);
@@ -31,7 +35,7 @@ int lib_SHA256Update(LIB_SHA256_CONTEXT *context, const uint8_t *data,
     /* For compatibility with other SHA256 providers, don't support
      * large lengths. */
     if (len > UINT32_MAX) {
-        return -1;
+        return -PAL_ERROR_INVAL;
     }
     mbedtls_sha256_update(context, data, len);
     return 0;
@@ -47,3 +51,32 @@ int lib_SHA256Final(LIB_SHA256_CONTEXT *context, uint8_t *output)
     return 0;
 }
 
+int lib_AESCMAC(const uint8_t *key, uint64_t key_len, const uint8_t *input,
+                uint64_t input_len, uint8_t *mac, uint64_t mac_len) {
+    mbedtls_cipher_type_t cipher;
+
+    switch (key_len) {
+    case 16:
+        cipher = MBEDTLS_CIPHER_AES_128_ECB;
+        break;
+    case 24:
+        cipher = MBEDTLS_CIPHER_AES_192_ECB;
+        break;
+    case 32:
+        cipher = MBEDTLS_CIPHER_AES_256_ECB;
+        break;
+    default:
+        return -PAL_ERROR_INVAL;
+    }
+
+    const mbedtls_cipher_info_t *cipher_info =
+        mbedtls_cipher_info_from_type(cipher);
+
+    if (mac_len < cipher_info->block_size) {
+        return -PAL_ERROR_INVAL;
+    }
+
+    return mbedtls_cipher_cmac(cipher_info,
+                               key, key_len * BITS_PER_BYTE,
+                               input, input_len, mac);
+}

+ 2 - 0
Pal/lib/crypto/adapters/mbedtls_dh.c

@@ -19,6 +19,8 @@
 #include "pal_crypto.h"
 #include "pal_error.h"
 #include "pal_debug.h"
+#include "assert.h"
+
 
 /* This is declared in pal_internal.h, but that can't be included here. */
 int _DkRandomBitsRead(void *buffer, int size);

+ 15 - 1
Pal/lib/crypto/adapters/wolfssl_adapter.c

@@ -16,7 +16,9 @@
 #include <stdint.h>
 #include "pal.h"
 #include "pal_crypto.h"
+#include "pal_error.h"
 #include "crypto/wolfssl/sha256.h"
+#include "crypto/wolfssl/cmac.h"
 
 int lib_SHA256Init(LIB_SHA256_CONTEXT *context)
 {
@@ -28,7 +30,7 @@ int lib_SHA256Update(LIB_SHA256_CONTEXT *context, const uint8_t *data,
 {
     /* uint64_t is a 64-bit value, but SHA256Update takes a 32-bit len. */
     if (len > UINT32_MAX) {
-        return -1;
+        return -PAL_ERROR_INVAL;
     }
     return SHA256Update(context, data, len);
 }
@@ -37,3 +39,15 @@ int lib_SHA256Final(LIB_SHA256_CONTEXT *context, uint8_t *output)
 {
     return SHA256Final(context, output);
 }
+
+int lib_AESCMAC(const uint8_t *key, uint64_t key_len, const uint8_t *input,
+                uint64_t input_len, uint8_t *mac, uint64_t mac_len)
+{
+    /* The old code only supports 128-bit AES CMAC, and length is a 32-bit
+     * value. */
+    if (key_len != 16 || input_len > INT32_MAX || mac_len < 16) {
+        return -PAL_ERROR_INVAL;
+    }
+    AES_CMAC((unsigned char *) key, (unsigned char *) input, input_len, mac);
+    return 0;
+}

+ 1492 - 0
Pal/lib/crypto/mbedtls/aes.c

@@ -0,0 +1,1492 @@
+/*
+ *  FIPS-197 compliant AES implementation
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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)
+ */
+/*
+ *  The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
+ *
+ *  http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
+ *  http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_AES_C)
+
+#include <string.h>
+
+#include "mbedtls/aes.h"
+#if defined(MBEDTLS_PADLOCK_C)
+#include "mbedtls/padlock.h"
+#endif
+#if defined(MBEDTLS_AESNI_C)
+#include "mbedtls/aesni.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)
+
+/* Implementation that should never be optimized out by the compiler */
+static void mbedtls_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * 32-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_UINT32_LE
+#define GET_UINT32_LE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ]       )             \
+        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 2] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 3] << 24 );            \
+}
+#endif
+
+#ifndef PUT_UINT32_LE
+#define PUT_UINT32_LE(n,b,i)                                    \
+{                                                               \
+    (b)[(i)    ] = (unsigned char) ( ( (n)       ) & 0xFF );    \
+    (b)[(i) + 1] = (unsigned char) ( ( (n) >>  8 ) & 0xFF );    \
+    (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF );    \
+    (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF );    \
+}
+#endif
+
+#if defined(MBEDTLS_PADLOCK_C) &&                      \
+    ( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) )
+static int aes_padlock_ace = -1;
+#endif
+
+#if defined(MBEDTLS_AES_ROM_TABLES)
+/*
+ * Forward S-box
+ */
+static const unsigned char FSb[256] =
+{
+    0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
+    0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
+    0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
+    0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
+    0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
+    0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+    0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
+    0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
+    0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
+    0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
+    0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
+    0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+    0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
+    0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
+    0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
+    0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
+    0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
+    0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+    0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
+    0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
+    0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
+    0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
+    0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
+    0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+    0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
+    0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
+    0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
+    0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
+    0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
+    0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+    0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
+    0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
+};
+
+/*
+ * Forward tables
+ */
+#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)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const uint32_t FT0[256] = { FT };
+#undef V
+
+#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
+static const uint32_t FT2[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const uint32_t FT3[256] = { FT };
+#undef V
+
+#undef FT
+
+/*
+ * Reverse S-box
+ */
+static const unsigned char RSb[256] =
+{
+    0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
+    0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
+    0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
+    0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
+    0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
+    0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+    0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
+    0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
+    0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
+    0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
+    0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
+    0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+    0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
+    0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
+    0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
+    0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
+    0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
+    0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+    0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
+    0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
+    0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
+    0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
+    0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
+    0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+    0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
+    0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
+    0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
+    0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
+    0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
+    0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+    0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
+    0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
+};
+
+/*
+ * Reverse tables
+ */
+#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)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const uint32_t RT0[256] = { RT };
+#undef V
+
+#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
+static const uint32_t RT2[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const uint32_t RT3[256] = { RT };
+#undef V
+
+#undef RT
+
+/*
+ * Round constants
+ */
+static const uint32_t RCON[10] =
+{
+    0x00000001, 0x00000002, 0x00000004, 0x00000008,
+    0x00000010, 0x00000020, 0x00000040, 0x00000080,
+    0x0000001B, 0x00000036
+};
+
+#else /* MBEDTLS_AES_ROM_TABLES */
+
+/*
+ * Forward S-box & tables
+ */
+static unsigned char FSb[256];
+static uint32_t FT0[256];
+static uint32_t FT1[256];
+static uint32_t FT2[256];
+static uint32_t FT3[256];
+
+/*
+ * Reverse S-box & tables
+ */
+static unsigned char RSb[256];
+static uint32_t RT0[256];
+static uint32_t RT1[256];
+static uint32_t RT2[256];
+static uint32_t RT3[256];
+
+/*
+ * Round constants
+ */
+static uint32_t RCON[10];
+
+/*
+ * 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 )
+
+static int aes_init_done = 0;
+
+static void aes_gen_tables( void )
+{
+    int i, x, y, z;
+    int pow[256];
+    int log[256];
+
+    /*
+     * compute pow and log tables over GF(2^8)
+     */
+    for( i = 0, x = 1; i < 256; i++ )
+    {
+        pow[i] = x;
+        log[x] = i;
+        x = ( x ^ XTIME( x ) ) & 0xFF;
+    }
+
+    /*
+     * calculate the round constants
+     */
+    for( i = 0, x = 1; i < 10; i++ )
+    {
+        RCON[i] = (uint32_t) x;
+        x = XTIME( x ) & 0xFF;
+    }
+
+    /*
+     * generate the forward and reverse S-boxes
+     */
+    FSb[0x00] = 0x63;
+    RSb[0x63] = 0x00;
+
+    for( i = 1; i < 256; i++ )
+    {
+        x = pow[255 - log[i]];
+
+        y  = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
+        x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
+        x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
+        x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF;
+        x ^= y ^ 0x63;
+
+        FSb[i] = (unsigned char) x;
+        RSb[x] = (unsigned char) i;
+    }
+
+    /*
+     * generate the forward and reverse tables
+     */
+    for( i = 0; i < 256; i++ )
+    {
+        x = FSb[i];
+        y = XTIME( x ) & 0xFF;
+        z =  ( y ^ x ) & 0xFF;
+
+        FT0[i] = ( (uint32_t) y       ) ^
+                 ( (uint32_t) x <<  8 ) ^
+                 ( (uint32_t) x << 16 ) ^
+                 ( (uint32_t) z << 24 );
+
+        FT1[i] = ROTL8( FT0[i] );
+        FT2[i] = ROTL8( FT1[i] );
+        FT3[i] = ROTL8( FT2[i] );
+
+        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 );
+
+        RT1[i] = ROTL8( RT0[i] );
+        RT2[i] = ROTL8( RT1[i] );
+        RT3[i] = ROTL8( RT2[i] );
+    }
+}
+
+#endif /* MBEDTLS_AES_ROM_TABLES */
+
+void mbedtls_aes_init( mbedtls_aes_context *ctx )
+{
+    memset( ctx, 0, sizeof( mbedtls_aes_context ) );
+}
+
+void mbedtls_aes_free( mbedtls_aes_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) );
+}
+
+/*
+ * 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 )
+{
+    unsigned int i;
+    uint32_t *RK;
+
+#if !defined(MBEDTLS_AES_ROM_TABLES)
+    if( aes_init_done == 0 )
+    {
+        aes_gen_tables();
+        aes_init_done = 1;
+
+    }
+#endif
+
+    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 );
+    }
+
+#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;
+
+#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 ) );
+#endif
+
+    for( i = 0; i < ( keybits >> 5 ); i++ )
+    {
+        GET_UINT32_LE( RK[i], key, i << 2 );
+    }
+
+    switch( ctx->nr )
+    {
+        case 10:
+
+            for( i = 0; i < 10; i++, RK += 4 )
+            {
+                RK[4]  = RK[0] ^ RCON[i] ^
+                ( (uint32_t) FSb[ ( RK[3] >>  8 ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( RK[3]       ) & 0xFF ] << 24 );
+
+                RK[5]  = RK[1] ^ RK[4];
+                RK[6]  = RK[2] ^ RK[5];
+                RK[7]  = RK[3] ^ RK[6];
+            }
+            break;
+
+        case 12:
+
+            for( i = 0; i < 8; i++, RK += 6 )
+            {
+                RK[6]  = RK[0] ^ RCON[i] ^
+                ( (uint32_t) FSb[ ( RK[5] >>  8 ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( RK[5]       ) & 0xFF ] << 24 );
+
+                RK[7]  = RK[1] ^ RK[6];
+                RK[8]  = RK[2] ^ RK[7];
+                RK[9]  = RK[3] ^ RK[8];
+                RK[10] = RK[4] ^ RK[9];
+                RK[11] = RK[5] ^ RK[10];
+            }
+            break;
+
+        case 14:
+
+            for( i = 0; i < 7; i++, RK += 8 )
+            {
+                RK[8]  = RK[0] ^ RCON[i] ^
+                ( (uint32_t) FSb[ ( RK[7] >>  8 ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( RK[7]       ) & 0xFF ] << 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[ ( RK[11]       ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( RK[11] >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
+
+                RK[13] = RK[5] ^ RK[12];
+                RK[14] = RK[6] ^ RK[13];
+                RK[15] = RK[7] ^ RK[14];
+            }
+            break;
+    }
+
+    return( 0 );
+}
+#endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */
+
+/*
+ * 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 i, j, ret;
+    mbedtls_aes_context cty;
+    uint32_t *RK;
+    uint32_t *SK;
+
+    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;
+
+    /* Also checks keybits */
+    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 );
+        goto exit;
+    }
+#endif
+
+    SK = cty.rk + 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++ = RT0[ FSb[ ( *SK       ) & 0xFF ] ] ^
+                    RT1[ FSb[ ( *SK >>  8 ) & 0xFF ] ] ^
+                    RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^
+                    RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];
+        }
+    }
+
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+    *RK++ = *SK++;
+
+exit:
+    mbedtls_aes_free( &cty );
+
+    return( ret );
+}
+#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */
+
+#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)     \
+{                                               \
+    X0 = *RK++ ^ FT0[ ( Y0       ) & 0xFF ] ^   \
+                 FT1[ ( Y1 >>  8 ) & 0xFF ] ^   \
+                 FT2[ ( Y2 >> 16 ) & 0xFF ] ^   \
+                 FT3[ ( Y3 >> 24 ) & 0xFF ];    \
+                                                \
+    X1 = *RK++ ^ FT0[ ( Y1       ) & 0xFF ] ^   \
+                 FT1[ ( Y2 >>  8 ) & 0xFF ] ^   \
+                 FT2[ ( Y3 >> 16 ) & 0xFF ] ^   \
+                 FT3[ ( Y0 >> 24 ) & 0xFF ];    \
+                                                \
+    X2 = *RK++ ^ FT0[ ( Y2       ) & 0xFF ] ^   \
+                 FT1[ ( Y3 >>  8 ) & 0xFF ] ^   \
+                 FT2[ ( Y0 >> 16 ) & 0xFF ] ^   \
+                 FT3[ ( Y1 >> 24 ) & 0xFF ];    \
+                                                \
+    X3 = *RK++ ^ FT0[ ( Y3       ) & 0xFF ] ^   \
+                 FT1[ ( Y0 >>  8 ) & 0xFF ] ^   \
+                 FT2[ ( Y1 >> 16 ) & 0xFF ] ^   \
+                 FT3[ ( Y2 >> 24 ) & 0xFF ];    \
+}
+
+#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)     \
+{                                               \
+    X0 = *RK++ ^ RT0[ ( Y0       ) & 0xFF ] ^   \
+                 RT1[ ( Y3 >>  8 ) & 0xFF ] ^   \
+                 RT2[ ( Y2 >> 16 ) & 0xFF ] ^   \
+                 RT3[ ( Y1 >> 24 ) & 0xFF ];    \
+                                                \
+    X1 = *RK++ ^ RT0[ ( Y1       ) & 0xFF ] ^   \
+                 RT1[ ( Y0 >>  8 ) & 0xFF ] ^   \
+                 RT2[ ( Y3 >> 16 ) & 0xFF ] ^   \
+                 RT3[ ( Y2 >> 24 ) & 0xFF ];    \
+                                                \
+    X2 = *RK++ ^ RT0[ ( Y2       ) & 0xFF ] ^   \
+                 RT1[ ( Y1 >>  8 ) & 0xFF ] ^   \
+                 RT2[ ( Y0 >> 16 ) & 0xFF ] ^   \
+                 RT3[ ( Y3 >> 24 ) & 0xFF ];    \
+                                                \
+    X3 = *RK++ ^ RT0[ ( Y3       ) & 0xFF ] ^   \
+                 RT1[ ( Y2 >>  8 ) & 0xFF ] ^   \
+                 RT2[ ( Y1 >> 16 ) & 0xFF ] ^   \
+                 RT3[ ( Y0 >> 24 ) & 0xFF ];    \
+}
+
+/*
+ * AES-ECB block encryption
+ */
+#if !defined(MBEDTLS_AES_ENCRYPT_ALT)
+void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
+                          const unsigned char input[16],
+                          unsigned char output[16] )
+{
+    int i;
+    uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+
+    RK = ctx->rk;
+
+    GET_UINT32_LE( X0, input,  0 ); X0 ^= *RK++;
+    GET_UINT32_LE( X1, input,  4 ); X1 ^= *RK++;
+    GET_UINT32_LE( X2, input,  8 ); X2 ^= *RK++;
+    GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;
+
+    for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
+    {
+        AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+        AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+    }
+
+    AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+    X0 = *RK++ ^ \
+            ( (uint32_t) FSb[ ( Y0       ) & 0xFF ]       ) ^
+            ( (uint32_t) FSb[ ( Y1 >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+    X1 = *RK++ ^ \
+            ( (uint32_t) FSb[ ( Y1       ) & 0xFF ]       ) ^
+            ( (uint32_t) FSb[ ( Y2 >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+
+    X2 = *RK++ ^ \
+            ( (uint32_t) FSb[ ( Y2       ) & 0xFF ]       ) ^
+            ( (uint32_t) FSb[ ( Y3 >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+    X3 = *RK++ ^ \
+            ( (uint32_t) FSb[ ( Y3       ) & 0xFF ]       ) ^
+            ( (uint32_t) FSb[ ( Y0 >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+
+    PUT_UINT32_LE( X0, output,  0 );
+    PUT_UINT32_LE( X1, output,  4 );
+    PUT_UINT32_LE( X2, output,  8 );
+    PUT_UINT32_LE( X3, output, 12 );
+}
+#endif /* !MBEDTLS_AES_ENCRYPT_ALT */
+
+/*
+ * AES-ECB block decryption
+ */
+#if !defined(MBEDTLS_AES_DECRYPT_ALT)
+void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
+                          const unsigned char input[16],
+                          unsigned char output[16] )
+{
+    int i;
+    uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+
+    RK = ctx->rk;
+
+    GET_UINT32_LE( X0, input,  0 ); X0 ^= *RK++;
+    GET_UINT32_LE( X1, input,  4 ); X1 ^= *RK++;
+    GET_UINT32_LE( X2, input,  8 ); X2 ^= *RK++;
+    GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;
+
+    for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
+    {
+        AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+        AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+    }
+
+    AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+    X0 = *RK++ ^ \
+            ( (uint32_t) RSb[ ( Y0       ) & 0xFF ]       ) ^
+            ( (uint32_t) RSb[ ( Y3 >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+    X1 = *RK++ ^ \
+            ( (uint32_t) RSb[ ( Y1       ) & 0xFF ]       ) ^
+            ( (uint32_t) RSb[ ( Y0 >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+
+    X2 = *RK++ ^ \
+            ( (uint32_t) RSb[ ( Y2       ) & 0xFF ]       ) ^
+            ( (uint32_t) RSb[ ( Y1 >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+    X3 = *RK++ ^ \
+            ( (uint32_t) RSb[ ( Y3       ) & 0xFF ]       ) ^
+            ( (uint32_t) RSb[ ( Y2 >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+
+    PUT_UINT32_LE( X0, output,  0 );
+    PUT_UINT32_LE( X1, output,  4 );
+    PUT_UINT32_LE( X2, output,  8 );
+    PUT_UINT32_LE( X3, output, 12 );
+}
+#endif /* !MBEDTLS_AES_DECRYPT_ALT */
+
+/*
+ * 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] )
+{
+#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 ) );
+#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
+        //
+    }
+#endif
+
+    if( mode == MBEDTLS_AES_ENCRYPT )
+        mbedtls_aes_encrypt( ctx, input, output );
+    else
+        mbedtls_aes_decrypt( ctx, input, output );
+
+    return( 0 );
+}
+
+#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 i;
+    unsigned char temp[16];
+
+    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 padlock data misaligned, we just fall back to
+        // unaccelerated mode
+        //
+    }
+#endif
+
+    if( mode == MBEDTLS_AES_DECRYPT )
+    {
+        while( length > 0 )
+        {
+            memcpy( temp, input, 16 );
+            mbedtls_aes_crypt_ecb( ctx, mode, input, output );
+
+            for( i = 0; i < 16; i++ )
+                output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+            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] );
+
+            mbedtls_aes_crypt_ecb( ctx, mode, output, output );
+            memcpy( iv, output, 16 );
+
+            input  += 16;
+            output += 16;
+            length -= 16;
+        }
+    }
+
+    return( 0 );
+}
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+/*
+ * 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 c;
+    size_t n = *iv_off;
+
+    if( mode == MBEDTLS_AES_DECRYPT )
+    {
+        while( length-- )
+        {
+            if( n == 0 )
+                mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+
+            c = *input++;
+            *output++ = (unsigned char)( c ^ iv[n] );
+            iv[n] = (unsigned char) c;
+
+            n = ( n + 1 ) & 0x0F;
+        }
+    }
+    else
+    {
+        while( length-- )
+        {
+            if( n == 0 )
+                mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+
+            iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
+
+            n = ( n + 1 ) & 0x0F;
+        }
+    }
+
+    *iv_off = n;
+
+    return( 0 );
+}
+
+/*
+ * 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 )
+{
+    unsigned char c;
+    unsigned char ov[17];
+
+    while( length-- )
+    {
+        memcpy( ov, iv, 16 );
+        mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+
+        if( mode == MBEDTLS_AES_DECRYPT )
+            ov[16] = *input;
+
+        c = *output++ = (unsigned char)( iv[0] ^ *input++ );
+
+        if( mode == MBEDTLS_AES_ENCRYPT )
+            ov[16] = c;
+
+        memcpy( iv, ov + 1, 16 );
+    }
+
+    return( 0 );
+}
+#endif /*MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+/*
+ * 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 c, i;
+    size_t n = *nc_off;
+
+    while( length-- )
+    {
+        if( n == 0 ) {
+            mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block );
+
+            for( i = 16; i > 0; i-- )
+                if( ++nonce_counter[i - 1] != 0 )
+                    break;
+        }
+        c = *input++;
+        *output++ = (unsigned char)( c ^ stream_block[n] );
+
+        n = ( n + 1 ) & 0x0F;
+    }
+
+    *nc_off = n;
+
+    return( 0 );
+}
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+
+#endif /* !MBEDTLS_AES_ALT */
+
+#if defined(MBEDTLS_SELF_TEST)
+/*
+ * AES test vectors from:
+ *
+ * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip
+ */
+static const unsigned char aes_test_ecb_dec[3][16] =
+{
+    { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58,
+      0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 },
+    { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2,
+      0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 },
+    { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D,
+      0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE }
+};
+
+static const unsigned char aes_test_ecb_enc[3][16] =
+{
+    { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73,
+      0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F },
+    { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11,
+      0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 },
+    { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D,
+      0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 }
+};
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+static const unsigned char aes_test_cbc_dec[3][16] =
+{
+    { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73,
+      0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 },
+    { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75,
+      0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B },
+    { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75,
+      0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 }
+};
+
+static const unsigned char aes_test_cbc_enc[3][16] =
+{
+    { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84,
+      0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D },
+    { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB,
+      0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 },
+    { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5,
+      0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 }
+};
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+/*
+ * AES-CFB128 test vectors from:
+ *
+ * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ */
+static const unsigned char aes_test_cfb128_key[3][32] =
+{
+    { 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 },
+    { 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 aes_test_cfb128_iv[16] =
+{
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+static const unsigned char aes_test_cfb128_pt[64] =
+{
+    0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+    0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
+    0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+    0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
+    0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+    0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
+    0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
+    0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
+};
+
+static const unsigned char aes_test_cfb128_ct[3][64] =
+{
+    { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
+      0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
+      0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F,
+      0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B,
+      0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40,
+      0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF,
+      0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E,
+      0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 },
+    { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
+      0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
+      0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21,
+      0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A,
+      0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1,
+      0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9,
+      0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0,
+      0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF },
+    { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,
+      0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,
+      0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8,
+      0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B,
+      0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92,
+      0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9,
+      0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8,
+      0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 }
+};
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+/*
+ * AES-CTR test vectors from:
+ *
+ * http://www.faqs.org/rfcs/rfc3686.html
+ */
+
+static const unsigned char aes_test_ctr_key[3][16] =
+{
+    { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
+      0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
+    { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7,
+      0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 },
+    { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8,
+      0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
+};
+
+static const unsigned char aes_test_ctr_nonce_counter[3][16] =
+{
+    { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
+    { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59,
+      0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 },
+    { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F,
+      0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
+};
+
+static const unsigned char aes_test_ctr_pt[3][48] =
+{
+    { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+      0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
+
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F },
+
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+      0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+      0x20, 0x21, 0x22, 0x23 }
+};
+
+static const unsigned char aes_test_ctr_ct[3][48] =
+{
+    { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79,
+      0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 },
+    { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9,
+      0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88,
+      0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8,
+      0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 },
+    { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9,
+      0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7,
+      0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36,
+      0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53,
+      0x25, 0xB2, 0x07, 0x2F }
+};
+
+static const int aes_test_ctr_len[3] =
+    { 16, 32, 36 };
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+
+/*
+ * Checkup routine
+ */
+int mbedtls_aes_self_test( int verbose )
+{
+    int ret = 0, i, j, u, v;
+    unsigned char key[32];
+    unsigned char buf[64];
+#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)
+    unsigned char iv[16];
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    unsigned char prv[16];
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB)
+    size_t offset;
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    int len;
+    unsigned char nonce_counter[16];
+    unsigned char stream_block[16];
+#endif
+    mbedtls_aes_context ctx;
+
+    memset( key, 0, 32 );
+    mbedtls_aes_init( &ctx );
+
+    /*
+     * ECB mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            mbedtls_printf( "  AES-ECB-%3d (%s): ", 128 + u * 64,
+                             ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+
+        memset( buf, 0, 16 );
+
+        if( v == MBEDTLS_AES_DECRYPT )
+        {
+            mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 );
+
+            for( j = 0; j < 10000; j++ )
+                mbedtls_aes_crypt_ecb( &ctx, v, buf, buf );
+
+            if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 )
+            {
+                if( verbose != 0 )
+                    mbedtls_printf( "failed\n" );
+
+                ret = 1;
+                goto exit;
+            }
+        }
+        else
+        {
+            mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+            for( j = 0; j < 10000; j++ )
+                mbedtls_aes_crypt_ecb( &ctx, v, buf, buf );
+
+            if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 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" );
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    /*
+     * CBC mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            mbedtls_printf( "  AES-CBC-%3d (%s): ", 128 + u * 64,
+                             ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+
+        memset( iv , 0, 16 );
+        memset( prv, 0, 16 );
+        memset( buf, 0, 16 );
+
+        if( v == MBEDTLS_AES_DECRYPT )
+        {
+            mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 );
+
+            for( j = 0; j < 10000; j++ )
+                mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
+
+            if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 )
+            {
+                if( verbose != 0 )
+                    mbedtls_printf( "failed\n" );
+
+                ret = 1;
+                goto exit;
+            }
+        }
+        else
+        {
+            mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+            for( j = 0; j < 10000; j++ )
+            {
+                unsigned char tmp[16];
+
+                mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
+
+                memcpy( tmp, prv, 16 );
+                memcpy( prv, buf, 16 );
+                memcpy( buf, tmp, 16 );
+            }
+
+            if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 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" );
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    /*
+     * CFB128 mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            mbedtls_printf( "  AES-CFB128-%3d (%s): ", 128 + u * 64,
+                             ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( iv,  aes_test_cfb128_iv, 16 );
+        memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 );
+
+        offset = 0;
+        mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 );
+
+        if( v == MBEDTLS_AES_DECRYPT )
+        {
+            memcpy( buf, aes_test_cfb128_ct[u], 64 );
+            mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
+
+            if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 )
+            {
+                if( verbose != 0 )
+                    mbedtls_printf( "failed\n" );
+
+                ret = 1;
+                goto exit;
+            }
+        }
+        else
+        {
+            memcpy( buf, aes_test_cfb128_pt, 64 );
+            mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
+
+            if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 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" );
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    /*
+     * CTR mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            mbedtls_printf( "  AES-CTR-128 (%s): ",
+                             ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 );
+        memcpy( key, aes_test_ctr_key[u], 16 );
+
+        offset = 0;
+        mbedtls_aes_setkey_enc( &ctx, key, 128 );
+
+        if( v == MBEDTLS_AES_DECRYPT )
+        {
+            len = aes_test_ctr_len[u];
+            memcpy( buf, aes_test_ctr_ct[u], len );
+
+            mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
+                           buf, buf );
+
+            if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 )
+            {
+                if( verbose != 0 )
+                    mbedtls_printf( "failed\n" );
+
+                ret = 1;
+                goto exit;
+            }
+        }
+        else
+        {
+            len = aes_test_ctr_len[u];
+            memcpy( buf, aes_test_ctr_pt[u], len );
+
+            mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
+                           buf, buf );
+
+            if( memcmp( buf, aes_test_ctr_ct[u], len ) != 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" );
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+
+    ret = 0;
+
+exit:
+    mbedtls_aes_free( &ctx );
+
+    return( ret );
+}
+
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_AES_C */

+ 469 - 0
Pal/lib/crypto/mbedtls/aesni.c

@@ -0,0 +1,469 @@
+/*
+ *  AES-NI support functions
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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)
+ */
+
+/*
+ * [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/
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_AESNI_C)
+
+#include "mbedtls/aesni.h"
+
+#include <string.h>
+
+#ifndef asm
+#define asm __asm
+#endif
+
+#if defined(MBEDTLS_HAVE_X86_64)
+
+/*
+ * AES-NI support detection routine
+ */
+int mbedtls_aesni_has_support( unsigned int what )
+{
+#if 0
+    static int done = 0;
+    static unsigned int c = 0;
+
+    if( ! done )
+    {
+        asm( "movl  $1, %%eax   \n\t"
+             "cpuid             \n\t"
+             : "=c" (c)
+             :
+             : "eax", "ebx", "edx" );
+        done = 1;
+    }
+
+    return( ( c & what ) != 0 );
+#else
+    /* CPUID not allowed within the enclave. Assume we have AES-NI. */
+    return 1;
+#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).
+ * Emit bytecode directly in order to support "old" version of gas.
+ *
+ * Opcodes from the Intel architecture reference manual, vol. 3.
+ * We always use registers, so we don't need prefixes for memory operands.
+ * 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 xmm0_xmm0   "0xC0"
+#define xmm0_xmm1   "0xC8"
+#define xmm0_xmm2   "0xD0"
+#define xmm0_xmm3   "0xD8"
+#define xmm0_xmm4   "0xE0"
+#define xmm1_xmm0   "0xC1"
+#define xmm1_xmm2   "0xD1"
+
+/*
+ * 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] )
+{
+    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
+         "subl      $1, %0          \n\t" // normal rounds = nr - 1
+         "test      %2, %2          \n\t" // mode?
+         "jz        2f              \n\t" // 0 = decrypt
+
+         "1:                        \n\t" // encryption loop
+         "movdqu    (%1), %%xmm1    \n\t" // load round key
+         AESENC     xmm1_xmm0      "\n\t" // 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
+         "jmp       3f              \n\t"
+
+         "2:                        \n\t" // decryption loop
+         "movdqu    (%1), %%xmm1    \n\t"
+         AESDEC     xmm1_xmm0      "\n\t" // 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
+
+         "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" );
+
+
+    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] )
+{
+    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++ )
+    {
+        aa[i] = a[15 - i];
+        bb[i] = b[15 - i];
+    }
+
+    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).
+          */
+         "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
+         "pxor %%xmm3, %%xmm4               \n\t" // e1+f1:e0+f0
+         "movdqa %%xmm4, %%xmm3             \n\t" // same
+         "psrldq $8, %%xmm4                 \n\t" // 0:e1+f1
+         "pslldq $8, %%xmm3                 \n\t" // e0+f0:0
+         "pxor %%xmm4, %%xmm2               \n\t" // d1:d0+e1+f1
+         "pxor %%xmm3, %%xmm1               \n\t" // c1+e0+f1:c0
+
+         /*
+          * Now shift the result one bit to the left,
+          * taking advantage of [CLMUL-WP] eq 27 (p. 20)
+          */
+         "movdqa %%xmm1, %%xmm3             \n\t" // r1:r0
+         "movdqa %%xmm2, %%xmm4             \n\t" // r3:r2
+         "psllq $1, %%xmm1                  \n\t" // r1<<1:r0<<1
+         "psllq $1, %%xmm2                  \n\t" // r3<<1:r2<<1
+         "psrlq $63, %%xmm3                 \n\t" // r1>>63:r0>>63
+         "psrlq $63, %%xmm4                 \n\t" // r3>>63:r2>>63
+         "movdqa %%xmm3, %%xmm5             \n\t" // r1>>63:r0>>63
+         "pslldq $8, %%xmm3                 \n\t" // r0>>63:0
+         "pslldq $8, %%xmm4                 \n\t" // r2>>63:0
+         "psrldq $8, %%xmm5                 \n\t" // 0:r1>>63
+         "por %%xmm3, %%xmm1                \n\t" // r1<<1|r0>>63:r0<<1
+         "por %%xmm4, %%xmm2                \n\t" // r3<<1|r2>>62:r2<<1
+         "por %%xmm5, %%xmm2                \n\t" // r3<<1|r2>>62:r2<<1|r1>>63
+
+         /*
+          * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1
+          * using [CLMUL-WP] algorithm 5 (p. 20).
+          * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted).
+          */
+         /* Step 2 (1) */
+         "movdqa %%xmm1, %%xmm3             \n\t" // x1:x0
+         "movdqa %%xmm1, %%xmm4             \n\t" // same
+         "movdqa %%xmm1, %%xmm5             \n\t" // same
+         "psllq $63, %%xmm3                 \n\t" // x1<<63:x0<<63 = stuff:a
+         "psllq $62, %%xmm4                 \n\t" // x1<<62:x0<<62 = stuff:b
+         "psllq $57, %%xmm5                 \n\t" // x1<<57:x0<<57 = stuff:c
+
+         /* Step 2 (2) */
+         "pxor %%xmm4, %%xmm3               \n\t" // stuff:a+b
+         "pxor %%xmm5, %%xmm3               \n\t" // stuff:a+b+c
+         "pslldq $8, %%xmm3                 \n\t" // a+b+c:0
+         "pxor %%xmm3, %%xmm1               \n\t" // x1+a+b+c:x0 = d:x0
+
+         /* Steps 3 and 4 */
+         "movdqa %%xmm1,%%xmm0              \n\t" // d:x0
+         "movdqa %%xmm1,%%xmm4              \n\t" // same
+         "movdqa %%xmm1,%%xmm5              \n\t" // same
+         "psrlq $1, %%xmm0                  \n\t" // e1:x0>>1 = e1:e0'
+         "psrlq $2, %%xmm4                  \n\t" // f1:x0>>2 = f1:f0'
+         "psrlq $7, %%xmm5                  \n\t" // g1:x0>>7 = g1:g0'
+         "pxor %%xmm4, %%xmm0               \n\t" // e1+f1:e0'+f0'
+         "pxor %%xmm5, %%xmm0               \n\t" // e1+f1+g1:e0'+f0'+g0'
+         // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing
+         // bits carried from d. Now get those\t bits back in.
+         "movdqa %%xmm1,%%xmm3              \n\t" // d:x0
+         "movdqa %%xmm1,%%xmm4              \n\t" // same
+         "movdqa %%xmm1,%%xmm5              \n\t" // same
+         "psllq $63, %%xmm3                 \n\t" // d<<63:stuff
+         "psllq $62, %%xmm4                 \n\t" // d<<62:stuff
+         "psllq $57, %%xmm5                 \n\t" // d<<57:stuff
+         "pxor %%xmm4, %%xmm3               \n\t" // d<<63+d<<62:stuff
+         "pxor %%xmm5, %%xmm3               \n\t" // missing bits of d:stuff
+         "psrldq $8, %%xmm3                 \n\t" // 0:missing bits of d
+         "pxor %%xmm3, %%xmm0               \n\t" // e1+f1+g1:e0+f0+g0
+         "pxor %%xmm1, %%xmm0               \n\t" // h1:h0
+         "pxor %%xmm2, %%xmm0               \n\t" // x3+h1:x2+h0
+
+         "movdqu %%xmm0, (%2)               \n\t" // done
+         :
+         : "r" (aa), "r" (bb), "r" (cc)
+         : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" );
+
+    /* Now byte-reverse the outputs */
+    for( i = 0; i < 16; i++ )
+        c[i] = 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 )
+{
+    unsigned char *ik = invkey;
+    const unsigned char *fk = fwdkey + 16 * nr;
+
+    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"
+             "movdqu %%xmm0, (%1)       \n\t"
+             :
+             : "r" (fk), "r" (ik)
+             : "memory", "xmm0" );
+
+    memcpy( ik, fk, 16 );
+}
+
+/*
+ * Key expansion, 128-bit case
+ */
+static void aesni_setkey_enc_128( unsigned char *rk,
+                                  const unsigned char *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
+
+         /*
+          * Finish generating the next round key.
+          *
+          * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff
+          * with X = rot( sub( r3 ) ) ^ RCON.
+          *
+          * On exit, xmm0 is r7:r6:r5:r4
+          * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3
+          * and those are written to the round key buffer.
+          */
+         "1:                                \n\t"
+         "pshufd $0xff, %%xmm1, %%xmm1      \n\t" // X:X:X:X
+         "pxor %%xmm0, %%xmm1               \n\t" // X+r3:X+r2:X+r1:r4
+         "pslldq $4, %%xmm0                 \n\t" // r2:r1:r0:0
+         "pxor %%xmm0, %%xmm1               \n\t" // X+r3+r2:X+r2+r1:r5:r4
+         "pslldq $4, %%xmm0                 \n\t" // etc
+         "pxor %%xmm0, %%xmm1               \n\t"
+         "pslldq $4, %%xmm0                 \n\t"
+         "pxor %%xmm1, %%xmm0               \n\t" // update xmm0 for next time!
+         "add $16, %0                       \n\t" // point to next round key
+         "movdqu %%xmm0, (%0)               \n\t" // write it
+         "ret                               \n\t"
+
+         /* 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"
+         :
+         : "r" (rk), "r" (key)
+         : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, 192-bit case
+ */
+static void aesni_setkey_enc_192( unsigned char *rk,
+                                  const unsigned char *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"
+         "movq %%xmm1, (%0)     \n\t"
+         "add $8, %0            \n\t"
+         "jmp 2f                \n\t" // skip auxiliary routine
+
+         /*
+          * Finish generating the next 6 quarter-keys.
+          *
+          * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4
+          * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON.
+          *
+          * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10
+          * and those are written to the round key buffer.
+          */
+         "1:                            \n\t"
+         "pshufd $0x55, %%xmm2, %%xmm2  \n\t" // X:X:X:X
+         "pxor %%xmm0, %%xmm2           \n\t" // X+r3:X+r2:X+r1:r4
+         "pslldq $4, %%xmm0             \n\t" // etc
+         "pxor %%xmm0, %%xmm2           \n\t"
+         "pslldq $4, %%xmm0             \n\t"
+         "pxor %%xmm0, %%xmm2           \n\t"
+         "pslldq $4, %%xmm0             \n\t"
+         "pxor %%xmm2, %%xmm0           \n\t" // update xmm0 = r9:r8:r7:r6
+         "movdqu %%xmm0, (%0)           \n\t"
+         "add $16, %0                   \n\t"
+         "pshufd $0xff, %%xmm0, %%xmm2  \n\t" // r9:r9:r9:r9
+         "pxor %%xmm1, %%xmm2           \n\t" // stuff:stuff:r9+r5:r10
+         "pslldq $4, %%xmm1             \n\t" // r2:r1:r0:0
+         "pxor %%xmm2, %%xmm1           \n\t" // xmm1 = stuff:stuff:r11:r10
+         "movq %%xmm1, (%0)             \n\t"
+         "add $8, %0                    \n\t"
+         "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"
+
+         :
+         : "r" (rk), "r" (key)
+         : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, 256-bit case
+ */
+static void aesni_setkey_enc_256( unsigned char *rk,
+                                  const unsigned char *key )
+{
+    asm( "movdqu (%1), %%xmm0           \n\t"
+         "movdqu %%xmm0, (%0)           \n\t"
+         "add $16, %0                   \n\t"
+         "movdqu 16(%1), %%xmm1         \n\t"
+         "movdqu %%xmm1, (%0)           \n\t"
+         "jmp 2f                        \n\t" // skip auxiliary routine
+
+         /*
+          * Finish generating the next two round keys.
+          *
+          * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and
+          * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON
+          *
+          * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12
+          * and those have been written to the output buffer.
+          */
+         "1:                                \n\t"
+         "pshufd $0xff, %%xmm2, %%xmm2      \n\t"
+         "pxor %%xmm0, %%xmm2               \n\t"
+         "pslldq $4, %%xmm0                 \n\t"
+         "pxor %%xmm0, %%xmm2               \n\t"
+         "pslldq $4, %%xmm0                 \n\t"
+         "pxor %%xmm0, %%xmm2               \n\t"
+         "pslldq $4, %%xmm0                 \n\t"
+         "pxor %%xmm2, %%xmm0               \n\t"
+         "add $16, %0                       \n\t"
+         "movdqu %%xmm0, (%0)               \n\t"
+
+         /* 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"
+         "pshufd $0xaa, %%xmm2, %%xmm2      \n\t"
+         "pxor %%xmm1, %%xmm2               \n\t"
+         "pslldq $4, %%xmm1                 \n\t"
+         "pxor %%xmm1, %%xmm2               \n\t"
+         "pslldq $4, %%xmm1                 \n\t"
+         "pxor %%xmm1, %%xmm2               \n\t"
+         "pslldq $4, %%xmm1                 \n\t"
+         "pxor %%xmm2, %%xmm1               \n\t"
+         "add $16, %0                       \n\t"
+         "movdqu %%xmm1, (%0)               \n\t"
+         "ret                               \n\t"
+
+         /*
+          * Main "loop" - Generating one more key than necessary,
+          * 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"
+         :
+         : "r" (rk), "r" (key)
+         : "memory", "cc", "0" );
+}
+
+/*
+ * Key expansion, wrapper
+ */
+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 );
+    }
+
+    return( 0 );
+}
+
+#endif /* MBEDTLS_HAVE_X86_64 */
+
+#endif /* MBEDTLS_AESNI_C */

+ 1 - 0
Pal/lib/crypto/mbedtls/bignum.c

@@ -49,6 +49,7 @@
 #if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
 #else
+#include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #define mbedtls_printf     printf

+ 919 - 0
Pal/lib/crypto/mbedtls/cipher.c

@@ -0,0 +1,919 @@
+/**
+ * \file cipher.c
+ *
+ * \brief Generic cipher wrapper for mbed TLS
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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)
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_CIPHER_C)
+
+#include "mbedtls/cipher.h"
+#include "mbedtls/cipher_internal.h"
+
+
+#if defined(MBEDTLS_GCM_C)
+#include "mbedtls/gcm.h"
+#endif
+
+#if defined(MBEDTLS_CCM_C)
+#include "mbedtls/ccm.h"
+#endif
+
+#if defined(MBEDTLS_CMAC_C)
+#include "mbedtls/cmac.h"
+#endif
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdlib.h>
+#include <string.h>
+#define mbedtls_calloc calloc
+#define mbedtls_free   free
+#endif
+
+#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
+#define MBEDTLS_CIPHER_MODE_STREAM
+#endif
+
+/* Implementation that should never be optimized out by the compiler */
+static void mbedtls_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
+}
+
+static int supported_init = 0;
+
+const int *mbedtls_cipher_list( void )
+{
+    const mbedtls_cipher_definition_t *def;
+    int *type;
+
+    if( ! supported_init )
+    {
+        def = mbedtls_cipher_definitions;
+        type = mbedtls_cipher_supported;
+
+        while( def->type != 0 )
+            *type++ = (*def++).type;
+
+        *type = 0;
+
+        supported_init = 1;
+    }
+
+    return( mbedtls_cipher_supported );
+}
+
+const mbedtls_cipher_info_t *mbedtls_cipher_info_from_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 );
+
+    return( NULL );
+}
+
+#if 0
+const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name )
+{
+    const mbedtls_cipher_definition_t *def;
+
+    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 );
+
+    return( NULL );
+}
+#endif
+
+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_definition_t *def;
+
+    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 );
+
+    return( NULL );
+}
+
+void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx )
+{
+    memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
+}
+
+void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+#if defined(MBEDTLS_CMAC_C)
+    if( ctx->cmac_ctx )
+    {
+       mbedtls_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 );
+
+    mbedtls_zeroize( ctx, sizeof(mbedtls_cipher_context_t) );
+}
+
+int mbedtls_cipher_setup( 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 );
+
+    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 );
+
+    ctx->cipher_info = cipher_info;
+
+#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
+    /*
+     * 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 );
+#else
+    (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE );
+#endif
+#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
+
+    return( 0 );
+}
+
+int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key,
+        int key_bitlen, const mbedtls_operation_t operation )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        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;
+    ctx->operation = operation;
+
+    /*
+     * For CFB and CTR mode always use the encryption key schedule
+     */
+    if( MBEDTLS_ENCRYPT == operation ||
+        MBEDTLS_MODE_CFB == 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 );
+    }
+
+    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 );
+}
+
+int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
+                   const unsigned char *iv, size_t iv_len )
+{
+    size_t actual_iv_size;
+
+    if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    /* avoid buffer overflow in ctx->iv */
+    if( iv_len > MBEDTLS_MAX_IV_LENGTH )
+        return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+
+    if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 )
+        actual_iv_size = iv_len;
+    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 );
+    }
+
+    memcpy( ctx->iv, iv, actual_iv_size );
+    ctx->iv_size = actual_iv_size;
+
+    return( 0 );
+}
+
+int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    ctx->unprocessed_len = 0;
+
+    return( 0 );
+}
+
+#if defined(MBEDTLS_GCM_C)
+int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
+                      const unsigned char *ad, size_t ad_len )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    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 );
+    }
+
+    return( 0 );
+}
+#endif /* MBEDTLS_GCM_C */
+
+int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
+                   size_t ilen, unsigned char *output, size_t *olen )
+{
+    int ret;
+    size_t block_size = 0;
+
+    if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
+    {
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    }
+
+    *olen = 0;
+    block_size = mbedtls_cipher_get_block_size( ctx );
+
+    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 );
+        }
+
+        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 );
+    }
+#endif
+
+    if ( 0 == block_size )
+    {
+        return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
+    }
+
+    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 )
+    {
+        size_t copy_len = 0;
+
+        /*
+         * If there is not enough data for a full block, cache it.
+         */
+        if( ( ctx->operation == MBEDTLS_DECRYPT &&
+                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 );
+        }
+
+        /*
+         * Process cached data first
+         */
+        if( 0 != ctx->unprocessed_len )
+        {
+            copy_len = block_size - ctx->unprocessed_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 );
+            }
+
+            *olen += block_size;
+            output += block_size;
+            ctx->unprocessed_len = 0;
+
+            input += copy_len;
+            ilen -= copy_len;
+        }
+
+        /*
+         * Cache final, incomplete block
+         */
+        if( 0 != ilen )
+        {
+            if( 0 == block_size )
+            {
+                return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
+            }
+
+            copy_len = ilen % block_size;
+            if( copy_len == 0 && ctx->operation == MBEDTLS_DECRYPT )
+                copy_len = block_size;
+
+            memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),
+                    copy_len );
+
+            ctx->unprocessed_len += copy_len;
+            ilen -= copy_len;
+        }
+
+        /*
+         * 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 );
+            }
+
+            *olen += ilen;
+        }
+
+        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 );
+        }
+
+        *olen = ilen;
+
+        return( 0 );
+    }
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#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 );
+        }
+
+        *olen = ilen;
+
+        return( 0 );
+    }
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+
+#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 );
+        }
+
+        *olen = ilen;
+
+        return( 0 );
+    }
+#endif /* MBEDTLS_CIPHER_MODE_STREAM */
+
+    return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+}
+
+#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
+#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
+/*
+ * 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 )
+{
+    size_t padding_len = output_len - data_len;
+    unsigned char 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 )
+{
+    size_t i, pad_idx;
+    unsigned char padding_len, bad = 0;
+
+    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;
+
+    /* Avoid logical || since it results in a branch */
+    bad |= padding_len > input_len;
+    bad |= padding_len == 0;
+
+    /* 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 );
+
+    return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
+}
+#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */
+
+#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)
+/*
+ * 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 )
+{
+    size_t padding_len = output_len - data_len;
+    unsigned char i = 0;
+
+    output[data_len] = 0x80;
+    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 )
+{
+    size_t i;
+    unsigned char done = 0, prev_done, bad;
+
+    if( NULL == input || NULL == data_len )
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    bad = 0xFF;
+    *data_len = 0;
+    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] ^ 0x80 ) | ( done == prev_done );
+    }
+
+    return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
+
+}
+#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */
+
+#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)
+/*
+ * 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 )
+{
+    size_t padding_len = output_len - data_len;
+    unsigned char i = 0;
+
+    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 )
+{
+    size_t i, pad_idx;
+    unsigned char padding_len, bad = 0;
+
+    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;
+
+    /* Avoid logical || since it results in a branch */
+    bad |= padding_len > input_len;
+    bad |= padding_len == 0;
+
+    /* 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 );
+
+    return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
+}
+#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */
+
+#if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
+/*
+ * Zero padding: fill with 00 ... 00
+ */
+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++ )
+        output[i] = 0x00;
+}
+
+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 );
+    }
+
+    return( 0 );
+}
+#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */
+
+/*
+ * No padding: don't pad :)
+ *
+ * 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 )
+{
+    if( NULL == input || NULL == data_len )
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    *data_len = input_len;
+
+    return( 0 );
+}
+#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
+
+int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
+                   unsigned char *output, size_t *olen )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    *olen = 0;
+
+    if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
+        MBEDTLS_MODE_CTR == ctx->cipher_info->mode ||
+        MBEDTLS_MODE_GCM == ctx->cipher_info->mode ||
+        MBEDTLS_MODE_STREAM == ctx->cipher_info->mode )
+    {
+        return( 0 );
+    }
+
+    if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode )
+    {
+        if( ctx->unprocessed_len != 0 )
+            return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
+
+        return( 0 );
+    }
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode )
+    {
+        int ret = 0;
+
+        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 );
+
+                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 )
+        {
+            /*
+             * 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 );
+
+            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 );
+        }
+
+        /* Set output size for decryption */
+        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 );
+    }
+#else
+    ((void) output);
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+    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 )
+{
+    if( NULL == ctx ||
+        MBEDTLS_MODE_CBC != ctx->cipher_info->mode )
+    {
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    }
+
+    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;
+#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;
+#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;
+#endif
+#if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
+    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;
+
+    default:
+        return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+    }
+
+    return( 0 );
+}
+#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
+
+#if defined(MBEDTLS_GCM_C)
+int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
+                      unsigned char *tag, size_t tag_len )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag )
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    if( MBEDTLS_ENCRYPT != ctx->operation )
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
+        return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len );
+
+    return( 0 );
+}
+
+int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
+                      const unsigned char *tag, size_t tag_len )
+{
+    int ret;
+
+    if( NULL == ctx || NULL == ctx->cipher_info ||
+        MBEDTLS_DECRYPT != ctx->operation )
+    {
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    }
+
+    if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
+    {
+        unsigned char check_tag[16];
+        size_t i;
+        int diff;
+
+        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,
+                                     check_tag, tag_len ) ) )
+        {
+            return( ret );
+        }
+
+        /* Check the tag in "constant-time" */
+        for( diff = 0, i = 0; i < tag_len; i++ )
+            diff |= tag[i] ^ check_tag[i];
+
+        if( diff != 0 )
+            return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
+
+        return( 0 );
+    }
+
+    return( 0 );
+}
+#endif /* MBEDTLS_GCM_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 ret;
+    size_t finish_olen;
+
+    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_update( ctx, input, ilen, output, olen ) ) != 0 )
+        return( ret );
+
+    if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 )
+        return( ret );
+
+    *olen += finish_olen;
+
+    return( 0 );
+}
+
+#if defined(MBEDTLS_CIPHER_MODE_AEAD)
+/*
+ * Packet-oriented encryption for AEAD modes
+ */
+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 )
+{
+#if defined(MBEDTLS_GCM_C)
+    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 ) );
+    }
+#endif /* MBEDTLS_GCM_C */
+#if defined(MBEDTLS_CCM_C)
+    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 ) );
+    }
+#endif /* MBEDTLS_CCM_C */
+
+    return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+}
+
+/*
+ * Packet-oriented decryption for AEAD modes
+ */
+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 )
+{
+#if defined(MBEDTLS_GCM_C)
+    if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
+    {
+        int ret;
+
+        *olen = ilen;
+        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 )
+            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+
+        return( ret );
+    }
+#endif /* MBEDTLS_GCM_C */
+#if defined(MBEDTLS_CCM_C)
+    if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode )
+    {
+        int ret;
+
+        *olen = ilen;
+        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 )
+            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
+
+        return( ret );
+    }
+#endif /* MBEDTLS_CCM_C */
+
+    return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+}
+#endif /* MBEDTLS_CIPHER_MODE_AEAD */
+
+#endif /* MBEDTLS_CIPHER_C */

+ 1451 - 0
Pal/lib/crypto/mbedtls/cipher_wrap.c

@@ -0,0 +1,1451 @@
+/**
+ * \file cipher_wrap.c
+ *
+ * \brief Generic cipher wrapper for mbed TLS
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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)
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_CIPHER_C)
+
+#include "mbedtls/cipher_internal.h"
+
+#if defined(MBEDTLS_AES_C)
+#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
+
+#if defined(MBEDTLS_DES_C)
+#include "mbedtls/des.h"
+#endif
+
+#if defined(MBEDTLS_BLOWFISH_C)
+#include "mbedtls/blowfish.h"
+#endif
+
+#if defined(MBEDTLS_GCM_C)
+#include "mbedtls/gcm.h"
+#endif
+
+#if defined(MBEDTLS_CCM_C)
+#include "mbedtls/ccm.h"
+#endif
+
+#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
+#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 )
+{
+    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_gcm_context ) );
+
+    if( ctx != NULL )
+        mbedtls_gcm_init( (mbedtls_gcm_context *) ctx );
+
+    return( ctx );
+}
+
+static void gcm_ctx_free( void *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 )
+{
+    void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ccm_context ) );
+
+    if( ctx != NULL )
+        mbedtls_ccm_init( (mbedtls_ccm_context *) ctx );
+
+    return( ctx );
+}
+
+static void ccm_ctx_free( void *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 )
+{
+    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 )
+{
+    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 )
+{
+    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_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 )
+{
+    return mbedtls_aes_crypt_ctr( (mbedtls_aes_context *) ctx, length, nc_off, nonce_counter,
+                          stream_block, input, output );
+}
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+
+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 );
+}
+
+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 );
+}
+
+static void * aes_ctx_alloc( void )
+{
+    mbedtls_aes_context *aes = mbedtls_calloc( 1, sizeof( mbedtls_aes_context ) );
+
+    if( aes == NULL )
+        return( NULL );
+
+    mbedtls_aes_init( aes );
+
+    return( aes );
+}
+
+static void aes_ctx_free( void *ctx )
+{
+    mbedtls_aes_free( (mbedtls_aes_context *) ctx );
+    mbedtls_free( ctx );
+}
+
+static const mbedtls_cipher_base_t aes_info = {
+    MBEDTLS_CIPHER_ID_AES,
+    aes_crypt_ecb_wrap,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    aes_crypt_cbc_wrap,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    aes_crypt_cfb128_wrap,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    aes_crypt_ctr_wrap,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    aes_setkey_enc_wrap,
+    aes_setkey_dec_wrap,
+    aes_ctx_alloc,
+    aes_ctx_free
+};
+
+static const mbedtls_cipher_info_t aes_128_ecb_info = {
+    MBEDTLS_CIPHER_AES_128_ECB,
+    MBEDTLS_MODE_ECB,
+    128,
+    "AES-128-ECB",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+static const mbedtls_cipher_info_t aes_192_ecb_info = {
+    MBEDTLS_CIPHER_AES_192_ECB,
+    MBEDTLS_MODE_ECB,
+    192,
+    "AES-192-ECB",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+static const mbedtls_cipher_info_t aes_256_ecb_info = {
+    MBEDTLS_CIPHER_AES_256_ECB,
+    MBEDTLS_MODE_ECB,
+    256,
+    "AES-256-ECB",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+static const mbedtls_cipher_info_t aes_128_cbc_info = {
+    MBEDTLS_CIPHER_AES_128_CBC,
+    MBEDTLS_MODE_CBC,
+    128,
+    "AES-128-CBC",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+static const mbedtls_cipher_info_t aes_192_cbc_info = {
+    MBEDTLS_CIPHER_AES_192_CBC,
+    MBEDTLS_MODE_CBC,
+    192,
+    "AES-192-CBC",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+static const mbedtls_cipher_info_t aes_256_cbc_info = {
+    MBEDTLS_CIPHER_AES_256_CBC,
+    MBEDTLS_MODE_CBC,
+    256,
+    "AES-256-CBC",
+    16,
+    0,
+    16,
+    &aes_info
+};
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+static const mbedtls_cipher_info_t aes_128_cfb128_info = {
+    MBEDTLS_CIPHER_AES_128_CFB128,
+    MBEDTLS_MODE_CFB,
+    128,
+    "AES-128-CFB128",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+static const mbedtls_cipher_info_t aes_192_cfb128_info = {
+    MBEDTLS_CIPHER_AES_192_CFB128,
+    MBEDTLS_MODE_CFB,
+    192,
+    "AES-192-CFB128",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+static const mbedtls_cipher_info_t aes_256_cfb128_info = {
+    MBEDTLS_CIPHER_AES_256_CFB128,
+    MBEDTLS_MODE_CFB,
+    256,
+    "AES-256-CFB128",
+    16,
+    0,
+    16,
+    &aes_info
+};
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+static const mbedtls_cipher_info_t aes_128_ctr_info = {
+    MBEDTLS_CIPHER_AES_128_CTR,
+    MBEDTLS_MODE_CTR,
+    128,
+    "AES-128-CTR",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+static const mbedtls_cipher_info_t aes_192_ctr_info = {
+    MBEDTLS_CIPHER_AES_192_CTR,
+    MBEDTLS_MODE_CTR,
+    192,
+    "AES-192-CTR",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+static const mbedtls_cipher_info_t aes_256_ctr_info = {
+    MBEDTLS_CIPHER_AES_256_CTR,
+    MBEDTLS_MODE_CTR,
+    256,
+    "AES-256-CTR",
+    16,
+    0,
+    16,
+    &aes_info
+};
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+
+#if defined(MBEDTLS_GCM_C)
+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 );
+}
+
+static const mbedtls_cipher_base_t gcm_aes_info = {
+    MBEDTLS_CIPHER_ID_AES,
+    NULL,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    gcm_aes_setkey_wrap,
+    gcm_aes_setkey_wrap,
+    gcm_ctx_alloc,
+    gcm_ctx_free,
+};
+
+static const mbedtls_cipher_info_t aes_128_gcm_info = {
+    MBEDTLS_CIPHER_AES_128_GCM,
+    MBEDTLS_MODE_GCM,
+    128,
+    "AES-128-GCM",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &gcm_aes_info
+};
+
+static const mbedtls_cipher_info_t aes_192_gcm_info = {
+    MBEDTLS_CIPHER_AES_192_GCM,
+    MBEDTLS_MODE_GCM,
+    192,
+    "AES-192-GCM",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &gcm_aes_info
+};
+
+static const mbedtls_cipher_info_t aes_256_gcm_info = {
+    MBEDTLS_CIPHER_AES_256_GCM,
+    MBEDTLS_MODE_GCM,
+    256,
+    "AES-256-GCM",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &gcm_aes_info
+};
+#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 )
+{
+    return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES,
+                     key, key_bitlen );
+}
+
+static const mbedtls_cipher_base_t ccm_aes_info = {
+    MBEDTLS_CIPHER_ID_AES,
+    NULL,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    ccm_aes_setkey_wrap,
+    ccm_aes_setkey_wrap,
+    ccm_ctx_alloc,
+    ccm_ctx_free,
+};
+
+static const mbedtls_cipher_info_t aes_128_ccm_info = {
+    MBEDTLS_CIPHER_AES_128_CCM,
+    MBEDTLS_MODE_CCM,
+    128,
+    "AES-128-CCM",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_aes_info
+};
+
+static const mbedtls_cipher_info_t aes_192_ccm_info = {
+    MBEDTLS_CIPHER_AES_192_CCM,
+    MBEDTLS_MODE_CCM,
+    192,
+    "AES-192-CCM",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_aes_info
+};
+
+static const mbedtls_cipher_info_t aes_256_ccm_info = {
+    MBEDTLS_CIPHER_AES_256_CCM,
+    MBEDTLS_MODE_CCM,
+    256,
+    "AES-256-CCM",
+    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 )
+{
+    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 )
+{
+    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 )
+{
+    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 )
+{
+    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 )
+{
+    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 )
+{
+    return mbedtls_camellia_setkey_enc( (mbedtls_camellia_context *) ctx, key, key_bitlen );
+}
+
+static void * camellia_ctx_alloc( void )
+{
+    mbedtls_camellia_context *ctx;
+    ctx = mbedtls_calloc( 1, sizeof( mbedtls_camellia_context ) );
+
+    if( ctx == NULL )
+        return( NULL );
+
+    mbedtls_camellia_init( ctx );
+
+    return( ctx );
+}
+
+static void camellia_ctx_free( void *ctx )
+{
+    mbedtls_camellia_free( (mbedtls_camellia_context *) ctx );
+    mbedtls_free( ctx );
+}
+
+static const mbedtls_cipher_base_t camellia_info = {
+    MBEDTLS_CIPHER_ID_CAMELLIA,
+    camellia_crypt_ecb_wrap,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    camellia_crypt_cbc_wrap,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    camellia_crypt_cfb128_wrap,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    camellia_crypt_ctr_wrap,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    camellia_setkey_enc_wrap,
+    camellia_setkey_dec_wrap,
+    camellia_ctx_alloc,
+    camellia_ctx_free
+};
+
+static const mbedtls_cipher_info_t camellia_128_ecb_info = {
+    MBEDTLS_CIPHER_CAMELLIA_128_ECB,
+    MBEDTLS_MODE_ECB,
+    128,
+    "CAMELLIA-128-ECB",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+static const mbedtls_cipher_info_t camellia_192_ecb_info = {
+    MBEDTLS_CIPHER_CAMELLIA_192_ECB,
+    MBEDTLS_MODE_ECB,
+    192,
+    "CAMELLIA-192-ECB",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+static const mbedtls_cipher_info_t camellia_256_ecb_info = {
+    MBEDTLS_CIPHER_CAMELLIA_256_ECB,
+    MBEDTLS_MODE_ECB,
+    256,
+    "CAMELLIA-256-ECB",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+static const mbedtls_cipher_info_t camellia_128_cbc_info = {
+    MBEDTLS_CIPHER_CAMELLIA_128_CBC,
+    MBEDTLS_MODE_CBC,
+    128,
+    "CAMELLIA-128-CBC",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+static const mbedtls_cipher_info_t camellia_192_cbc_info = {
+    MBEDTLS_CIPHER_CAMELLIA_192_CBC,
+    MBEDTLS_MODE_CBC,
+    192,
+    "CAMELLIA-192-CBC",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+static const mbedtls_cipher_info_t camellia_256_cbc_info = {
+    MBEDTLS_CIPHER_CAMELLIA_256_CBC,
+    MBEDTLS_MODE_CBC,
+    256,
+    "CAMELLIA-256-CBC",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+static const mbedtls_cipher_info_t camellia_128_cfb128_info = {
+    MBEDTLS_CIPHER_CAMELLIA_128_CFB128,
+    MBEDTLS_MODE_CFB,
+    128,
+    "CAMELLIA-128-CFB128",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+static const mbedtls_cipher_info_t camellia_192_cfb128_info = {
+    MBEDTLS_CIPHER_CAMELLIA_192_CFB128,
+    MBEDTLS_MODE_CFB,
+    192,
+    "CAMELLIA-192-CFB128",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+static const mbedtls_cipher_info_t camellia_256_cfb128_info = {
+    MBEDTLS_CIPHER_CAMELLIA_256_CFB128,
+    MBEDTLS_MODE_CFB,
+    256,
+    "CAMELLIA-256-CFB128",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+static const mbedtls_cipher_info_t camellia_128_ctr_info = {
+    MBEDTLS_CIPHER_CAMELLIA_128_CTR,
+    MBEDTLS_MODE_CTR,
+    128,
+    "CAMELLIA-128-CTR",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+static const mbedtls_cipher_info_t camellia_192_ctr_info = {
+    MBEDTLS_CIPHER_CAMELLIA_192_CTR,
+    MBEDTLS_MODE_CTR,
+    192,
+    "CAMELLIA-192-CTR",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+static const mbedtls_cipher_info_t camellia_256_ctr_info = {
+    MBEDTLS_CIPHER_CAMELLIA_256_CTR,
+    MBEDTLS_MODE_CTR,
+    256,
+    "CAMELLIA-256-CTR",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+#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 )
+{
+    return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA,
+                     key, key_bitlen );
+}
+
+static const mbedtls_cipher_base_t gcm_camellia_info = {
+    MBEDTLS_CIPHER_ID_CAMELLIA,
+    NULL,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    gcm_camellia_setkey_wrap,
+    gcm_camellia_setkey_wrap,
+    gcm_ctx_alloc,
+    gcm_ctx_free,
+};
+
+static const mbedtls_cipher_info_t camellia_128_gcm_info = {
+    MBEDTLS_CIPHER_CAMELLIA_128_GCM,
+    MBEDTLS_MODE_GCM,
+    128,
+    "CAMELLIA-128-GCM",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &gcm_camellia_info
+};
+
+static const mbedtls_cipher_info_t camellia_192_gcm_info = {
+    MBEDTLS_CIPHER_CAMELLIA_192_GCM,
+    MBEDTLS_MODE_GCM,
+    192,
+    "CAMELLIA-192-GCM",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &gcm_camellia_info
+};
+
+static const mbedtls_cipher_info_t camellia_256_gcm_info = {
+    MBEDTLS_CIPHER_CAMELLIA_256_GCM,
+    MBEDTLS_MODE_GCM,
+    256,
+    "CAMELLIA-256-GCM",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &gcm_camellia_info
+};
+#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 )
+{
+    return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA,
+                     key, key_bitlen );
+}
+
+static const mbedtls_cipher_base_t ccm_camellia_info = {
+    MBEDTLS_CIPHER_ID_CAMELLIA,
+    NULL,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    ccm_camellia_setkey_wrap,
+    ccm_camellia_setkey_wrap,
+    ccm_ctx_alloc,
+    ccm_ctx_free,
+};
+
+static const mbedtls_cipher_info_t camellia_128_ccm_info = {
+    MBEDTLS_CIPHER_CAMELLIA_128_CCM,
+    MBEDTLS_MODE_CCM,
+    128,
+    "CAMELLIA-128-CCM",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_camellia_info
+};
+
+static const mbedtls_cipher_info_t camellia_192_ccm_info = {
+    MBEDTLS_CIPHER_CAMELLIA_192_CCM,
+    MBEDTLS_MODE_CCM,
+    192,
+    "CAMELLIA-192-CCM",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_camellia_info
+};
+
+static const mbedtls_cipher_info_t camellia_256_ccm_info = {
+    MBEDTLS_CIPHER_CAMELLIA_256_CCM,
+    MBEDTLS_MODE_CCM,
+    256,
+    "CAMELLIA-256-CCM",
+    12,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    16,
+    &ccm_camellia_info
+};
+#endif /* MBEDTLS_CCM_C */
+
+#endif /* MBEDTLS_CAMELLIA_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 )
+{
+    ((void) operation);
+    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 )
+{
+    ((void) operation);
+    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 )
+{
+    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 )
+{
+    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 )
+{
+    ((void) key_bitlen);
+
+    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 )
+{
+    ((void) key_bitlen);
+
+    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 )
+{
+    ((void) key_bitlen);
+
+    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 )
+{
+    ((void) key_bitlen);
+
+    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 )
+{
+    ((void) key_bitlen);
+
+    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 )
+{
+    ((void) key_bitlen);
+
+    return mbedtls_des3_set3key_enc( (mbedtls_des3_context *) ctx, key );
+}
+
+static void * des_ctx_alloc( void )
+{
+    mbedtls_des_context *des = mbedtls_calloc( 1, sizeof( mbedtls_des_context ) );
+
+    if( des == NULL )
+        return( NULL );
+
+    mbedtls_des_init( des );
+
+    return( des );
+}
+
+static void des_ctx_free( void *ctx )
+{
+    mbedtls_des_free( (mbedtls_des_context *) ctx );
+    mbedtls_free( ctx );
+}
+
+static void * des3_ctx_alloc( void )
+{
+    mbedtls_des3_context *des3;
+    des3 = mbedtls_calloc( 1, sizeof( mbedtls_des3_context ) );
+
+    if( des3 == NULL )
+        return( NULL );
+
+    mbedtls_des3_init( des3 );
+
+    return( des3 );
+}
+
+static void des3_ctx_free( void *ctx )
+{
+    mbedtls_des3_free( (mbedtls_des3_context *) ctx );
+    mbedtls_free( ctx );
+}
+
+static const mbedtls_cipher_base_t des_info = {
+    MBEDTLS_CIPHER_ID_DES,
+    des_crypt_ecb_wrap,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    des_crypt_cbc_wrap,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    des_setkey_enc_wrap,
+    des_setkey_dec_wrap,
+    des_ctx_alloc,
+    des_ctx_free
+};
+
+static const mbedtls_cipher_info_t des_ecb_info = {
+    MBEDTLS_CIPHER_DES_ECB,
+    MBEDTLS_MODE_ECB,
+    MBEDTLS_KEY_LENGTH_DES,
+    "DES-ECB",
+    8,
+    0,
+    8,
+    &des_info
+};
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+static const mbedtls_cipher_info_t des_cbc_info = {
+    MBEDTLS_CIPHER_DES_CBC,
+    MBEDTLS_MODE_CBC,
+    MBEDTLS_KEY_LENGTH_DES,
+    "DES-CBC",
+    8,
+    0,
+    8,
+    &des_info
+};
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+static const mbedtls_cipher_base_t des_ede_info = {
+    MBEDTLS_CIPHER_ID_DES,
+    des3_crypt_ecb_wrap,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    des3_crypt_cbc_wrap,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    des3_set2key_enc_wrap,
+    des3_set2key_dec_wrap,
+    des3_ctx_alloc,
+    des3_ctx_free
+};
+
+static const mbedtls_cipher_info_t des_ede_ecb_info = {
+    MBEDTLS_CIPHER_DES_EDE_ECB,
+    MBEDTLS_MODE_ECB,
+    MBEDTLS_KEY_LENGTH_DES_EDE,
+    "DES-EDE-ECB",
+    8,
+    0,
+    8,
+    &des_ede_info
+};
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+static const mbedtls_cipher_info_t des_ede_cbc_info = {
+    MBEDTLS_CIPHER_DES_EDE_CBC,
+    MBEDTLS_MODE_CBC,
+    MBEDTLS_KEY_LENGTH_DES_EDE,
+    "DES-EDE-CBC",
+    8,
+    0,
+    8,
+    &des_ede_info
+};
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+static const mbedtls_cipher_base_t des_ede3_info = {
+    MBEDTLS_CIPHER_ID_3DES,
+    des3_crypt_ecb_wrap,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    des3_crypt_cbc_wrap,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    des3_set3key_enc_wrap,
+    des3_set3key_dec_wrap,
+    des3_ctx_alloc,
+    des3_ctx_free
+};
+
+static const mbedtls_cipher_info_t des_ede3_ecb_info = {
+    MBEDTLS_CIPHER_DES_EDE3_ECB,
+    MBEDTLS_MODE_ECB,
+    MBEDTLS_KEY_LENGTH_DES_EDE3,
+    "DES-EDE3-ECB",
+    8,
+    0,
+    8,
+    &des_ede3_info
+};
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+static const mbedtls_cipher_info_t des_ede3_cbc_info = {
+    MBEDTLS_CIPHER_DES_EDE3_CBC,
+    MBEDTLS_MODE_CBC,
+    MBEDTLS_KEY_LENGTH_DES_EDE3,
+    "DES-EDE3-CBC",
+    8,
+    0,
+    8,
+    &des_ede3_info
+};
+#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_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_CTR)
+    blowfish_crypt_ctr_wrap,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    blowfish_setkey_wrap,
+    blowfish_setkey_wrap,
+    blowfish_ctx_alloc,
+    blowfish_ctx_free
+};
+
+static const mbedtls_cipher_info_t blowfish_ecb_info = {
+    MBEDTLS_CIPHER_BLOWFISH_ECB,
+    MBEDTLS_MODE_ECB,
+    128,
+    "BLOWFISH-ECB",
+    8,
+    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_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_CTR)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+    arc4_crypt_stream_wrap,
+#endif
+    arc4_setkey_wrap,
+    arc4_setkey_wrap,
+    arc4_ctx_alloc,
+    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_CIPHER_NULL_CIPHER)
+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 );
+}
+
+static int null_setkey( void *ctx, const unsigned char *key,
+                        unsigned int key_bitlen )
+{
+    ((void) ctx);
+    ((void) key);
+    ((void) key_bitlen);
+
+    return( 0 );
+}
+
+static void * null_ctx_alloc( void )
+{
+    return( (void *) 1 );
+}
+
+static void null_ctx_free( void *ctx )
+{
+    ((void) ctx);
+}
+
+static const mbedtls_cipher_base_t null_base_info = {
+    MBEDTLS_CIPHER_ID_NULL,
+    NULL,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+    null_crypt_stream,
+#endif
+    null_setkey,
+    null_setkey,
+    null_ctx_alloc,
+    null_ctx_free
+};
+
+static const mbedtls_cipher_info_t null_cipher_info = {
+    MBEDTLS_CIPHER_NULL,
+    MBEDTLS_MODE_STREAM,
+    0,
+    "NULL",
+    0,
+    0,
+    1,
+    &null_base_info
+};
+#endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */
+
+const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] =
+{
+#if defined(MBEDTLS_AES_C)
+    { MBEDTLS_CIPHER_AES_128_ECB,          &aes_128_ecb_info },
+    { MBEDTLS_CIPHER_AES_192_ECB,          &aes_192_ecb_info },
+    { MBEDTLS_CIPHER_AES_256_ECB,          &aes_256_ecb_info },
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    { MBEDTLS_CIPHER_AES_128_CBC,          &aes_128_cbc_info },
+    { MBEDTLS_CIPHER_AES_192_CBC,          &aes_192_cbc_info },
+    { MBEDTLS_CIPHER_AES_256_CBC,          &aes_256_cbc_info },
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    { MBEDTLS_CIPHER_AES_128_CFB128,       &aes_128_cfb128_info },
+    { MBEDTLS_CIPHER_AES_192_CFB128,       &aes_192_cfb128_info },
+    { MBEDTLS_CIPHER_AES_256_CFB128,       &aes_256_cfb128_info },
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    { MBEDTLS_CIPHER_AES_128_CTR,          &aes_128_ctr_info },
+    { MBEDTLS_CIPHER_AES_192_CTR,          &aes_192_ctr_info },
+    { MBEDTLS_CIPHER_AES_256_CTR,          &aes_256_ctr_info },
+#endif
+#if defined(MBEDTLS_GCM_C)
+    { MBEDTLS_CIPHER_AES_128_GCM,          &aes_128_gcm_info },
+    { MBEDTLS_CIPHER_AES_192_GCM,          &aes_192_gcm_info },
+    { MBEDTLS_CIPHER_AES_256_GCM,          &aes_256_gcm_info },
+#endif
+#if defined(MBEDTLS_CCM_C)
+    { 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 },
+#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 },
+    { MBEDTLS_CIPHER_CAMELLIA_256_ECB,     &camellia_256_ecb_info },
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    { MBEDTLS_CIPHER_CAMELLIA_128_CBC,     &camellia_128_cbc_info },
+    { MBEDTLS_CIPHER_CAMELLIA_192_CBC,     &camellia_192_cbc_info },
+    { MBEDTLS_CIPHER_CAMELLIA_256_CBC,     &camellia_256_cbc_info },
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    { MBEDTLS_CIPHER_CAMELLIA_128_CFB128,  &camellia_128_cfb128_info },
+    { MBEDTLS_CIPHER_CAMELLIA_192_CFB128,  &camellia_192_cfb128_info },
+    { MBEDTLS_CIPHER_CAMELLIA_256_CFB128,  &camellia_256_cfb128_info },
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    { MBEDTLS_CIPHER_CAMELLIA_128_CTR,     &camellia_128_ctr_info },
+    { MBEDTLS_CIPHER_CAMELLIA_192_CTR,     &camellia_192_ctr_info },
+    { MBEDTLS_CIPHER_CAMELLIA_256_CTR,     &camellia_256_ctr_info },
+#endif
+#if defined(MBEDTLS_GCM_C)
+    { MBEDTLS_CIPHER_CAMELLIA_128_GCM,     &camellia_128_gcm_info },
+    { MBEDTLS_CIPHER_CAMELLIA_192_GCM,     &camellia_192_gcm_info },
+    { MBEDTLS_CIPHER_CAMELLIA_256_GCM,     &camellia_256_gcm_info },
+#endif
+#if defined(MBEDTLS_CCM_C)
+    { 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 },
+#endif
+#endif /* MBEDTLS_CAMELLIA_C */
+
+#if defined(MBEDTLS_DES_C)
+    { MBEDTLS_CIPHER_DES_ECB,              &des_ecb_info },
+    { MBEDTLS_CIPHER_DES_EDE_ECB,          &des_ede_ecb_info },
+    { MBEDTLS_CIPHER_DES_EDE3_ECB,         &des_ede3_ecb_info },
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    { MBEDTLS_CIPHER_DES_CBC,              &des_cbc_info },
+    { MBEDTLS_CIPHER_DES_EDE_CBC,          &des_ede_cbc_info },
+    { MBEDTLS_CIPHER_DES_EDE3_CBC,         &des_ede3_cbc_info },
+#endif
+#endif /* MBEDTLS_DES_C */
+
+#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
+    { MBEDTLS_CIPHER_NULL,                 &null_cipher_info },
+#endif /* MBEDTLS_CIPHER_NULL_CIPHER */
+
+    { MBEDTLS_CIPHER_NONE, NULL }
+};
+
+#define NUM_CIPHERS sizeof mbedtls_cipher_definitions / sizeof mbedtls_cipher_definitions[0]
+int mbedtls_cipher_supported[NUM_CIPHERS];
+
+#endif /* MBEDTLS_CIPHER_C */

+ 1073 - 0
Pal/lib/crypto/mbedtls/cmac.c

@@ -0,0 +1,1073 @@
+/*
+ * \file cmac.c
+ *
+ * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES
+ *
+ *  Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ *  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)
+ */
+
+/*
+ * References:
+ *
+ * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The
+ *      CMAC Mode for Authentication
+ *   http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf
+ *
+ * - RFC 4493 - The AES-CMAC Algorithm
+ *   https://tools.ietf.org/html/rfc4493
+ *
+ * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message
+ *      Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128)
+ *      Algorithm for the Internet Key Exchange Protocol (IKE)
+ *   https://tools.ietf.org/html/rfc4615
+ *
+ *   Additional test vectors: ISO/IEC 9797-1
+ *
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_CMAC_C)
+
+#include "mbedtls/cmac.h"
+
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <string.h>
+#include <stdlib.h>
+#define mbedtls_calloc     calloc
+#define mbedtls_free       free
+#if defined(MBEDTLS_SELF_TEST)
+#include <stdio.h>
+#define mbedtls_printf     printf
+#endif /* MBEDTLS_SELF_TEST */
+#endif /* MBEDTLS_PLATFORM_C */
+
+/* Implementation that should never be optimized out by the compiler */
+static void mbedtls_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * Multiplication by u in the Galois field of GF(2^n)
+ *
+ * As explained in NIST SP 800-38B, this can be computed:
+ *
+ *   If MSB(p) = 0, then p = (p << 1)
+ *   If MSB(p) = 1, then p = (p << 1) ^ R_n
+ *   with R_64 = 0x1B and  R_128 = 0x87
+ *
+ * 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 )
+{
+    const unsigned char R_128 = 0x87;
+    const unsigned char R_64 = 0x1B;
+    unsigned char R_n, mask;
+    unsigned char overflow = 0x00;
+    int i;
+
+    if( blocksize == MBEDTLS_AES_BLOCK_SIZE )
+    {
+        R_n = R_128;
+    }
+    else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE )
+    {
+        R_n = R_64;
+    }
+    else
+    {
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+    }
+
+    for( i = (int)blocksize - 1; i >= 0; i-- )
+    {
+        output[i] = input[i] << 1 | overflow;
+        overflow = input[i] >> 7;
+    }
+
+    /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
+     * using bit operations to avoid branches */
+
+    /* MSVC has a warning about unary minus on unsigned, but this is
+     * well-defined and precisely what we want to do here */
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4146 )
+#endif
+    mask = - ( input[0] >> 7 );
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+
+    output[ blocksize - 1 ] ^= R_n & mask;
+
+    return( 0 );
+}
+
+/*
+ * Generate subkeys
+ *
+ * - 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 )
+{
+    int ret;
+    unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX];
+    size_t olen, block_size;
+
+    mbedtls_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 )
+        goto exit;
+
+    /*
+     * Generate K1 and K2
+     */
+    if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 )
+        goto exit;
+
+    if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 )
+        goto exit;
+
+exit:
+    mbedtls_zeroize( L, sizeof( L ) );
+
+    return( ret );
+}
+
+static void cmac_xor_block( unsigned char *output, const unsigned char *input1,
+                            const unsigned char *input2,
+                            const size_t block_size )
+{
+    size_t index;
+
+    for( index = 0; index < block_size; index++ )
+        output[ index ] = input1[ index ] ^ input2[ index ];
+}
+
+/*
+ * Create padded last block from (partial) last block.
+ *
+ * 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 )
+{
+    size_t j;
+
+    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 )
+            padded_block[j] = 0x80;
+        else
+            padded_block[j] = 0x00;
+    }
+}
+
+int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx,
+                                const unsigned char *key, size_t keybits )
+{
+    mbedtls_cipher_type_t type;
+    mbedtls_cmac_context_t *cmac_ctx;
+    int retval;
+
+    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 );
+
+    type = ctx->cipher_info->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 );
+    }
+
+    /* 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 );
+
+    ctx->cmac_ctx = cmac_ctx;
+
+    mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) );
+
+    return 0;
+}
+
+int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx,
+                                const unsigned char *input, size_t ilen )
+{
+    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 );
+
+    cmac_ctx = ctx->cmac_ctx;
+    block_size = ctx->cipher_info->block_size;
+    state = ctx->cmac_ctx->state;
+
+    /* 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 );
+
+        cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size );
+
+        if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
+                                           &olen ) ) != 0 )
+        {
+           goto exit;
+        }
+
+        input += block_size - cmac_ctx->unprocessed_len;
+        ilen -= block_size - cmac_ctx->unprocessed_len;
+        cmac_ctx->unprocessed_len = 0;
+    }
+
+    /* n is the number of blocks including any final partial block */
+    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 );
+
+        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 );
+        cmac_ctx->unprocessed_len += ilen;
+    }
+
+exit:
+    return( ret );
+}
+
+int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx,
+                                unsigned char *output )
+{
+    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];
+    unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX];
+    int ret;
+    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 );
+
+    cmac_ctx = ctx->cmac_ctx;
+    block_size = ctx->cipher_info->block_size;
+    state = cmac_ctx->state;
+
+    mbedtls_zeroize( K1, sizeof( K1 ) );
+    mbedtls_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
+    {
+        /* Last block is complete block */
+        cmac_xor_block( 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 )
+    {
+        goto exit;
+    }
+
+    memcpy( output, state, block_size );
+
+exit:
+    /* Wipe the generated keys on the stack, and any other transients to avoid
+     * side channel leakage */
+    mbedtls_zeroize( K1, sizeof( K1 ) );
+    mbedtls_zeroize( K2, sizeof( K2 ) );
+
+    cmac_ctx->unprocessed_len = 0;
+    mbedtls_zeroize( cmac_ctx->unprocessed_block,
+                     sizeof( cmac_ctx->unprocessed_block ) );
+
+    mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX );
+    return( ret );
+}
+
+int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *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 );
+
+    cmac_ctx = ctx->cmac_ctx;
+
+    /* Reset the internal state */
+    cmac_ctx->unprocessed_len = 0;
+    mbedtls_zeroize( cmac_ctx->unprocessed_block,
+                     sizeof( cmac_ctx->unprocessed_block ) );
+    mbedtls_zeroize( cmac_ctx->state,
+                     sizeof( cmac_ctx->state ) );
+
+    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 )
+{
+    mbedtls_cipher_context_t ctx;
+    int ret;
+
+    if( cipher_info == NULL || key == NULL || input == NULL || output == NULL )
+        return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+    mbedtls_cipher_init( &ctx );
+
+    if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
+        goto exit;
+
+    ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen );
+    if( ret != 0 )
+        goto exit;
+
+    ret = mbedtls_cipher_cmac_update( &ctx, input, ilen );
+    if( ret != 0 )
+        goto exit;
+
+    ret = mbedtls_cipher_cmac_finish( &ctx, output );
+
+exit:
+    mbedtls_cipher_free( &ctx );
+
+    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 )
+{
+    int ret;
+    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 );
+
+    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 )
+    {
+        /* Use key as is */
+        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 )
+            goto exit;
+    }
+
+    ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len,
+                               output );
+
+exit:
+    mbedtls_zeroize( int_key, sizeof( int_key ) );
+
+    return( ret );
+}
+#endif /* MBEDTLS_AES_C */
+
+#if defined(MBEDTLS_SELF_TEST)
+/*
+ * CMAC test data for SP800-38B
+ * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf
+ * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf
+ *
+ * AES-CMAC-PRF-128 test data from RFC 4615
+ * https://tools.ietf.org/html/rfc4615#page-4
+ */
+
+#define NB_CMAC_TESTS_PER_KEY 4
+#define NB_PRF_TESTS 3
+
+#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
+/* All CMAC test inputs are truncated from the same 64 byte buffer. */
+static const unsigned char test_message[] = {
+    /* PT */
+    0x6b, 0xc1, 0xbe, 0xe2,     0x2e, 0x40, 0x9f, 0x96,
+    0xe9, 0x3d, 0x7e, 0x11,     0x73, 0x93, 0x17, 0x2a,
+    0xae, 0x2d, 0x8a, 0x57,     0x1e, 0x03, 0xac, 0x9c,
+    0x9e, 0xb7, 0x6f, 0xac,     0x45, 0xaf, 0x8e, 0x51,
+    0x30, 0xc8, 0x1c, 0x46,     0xa3, 0x5c, 0xe4, 0x11,
+    0xe5, 0xfb, 0xc1, 0x19,     0x1a, 0x0a, 0x52, 0xef,
+    0xf6, 0x9f, 0x24, 0x45,     0xdf, 0x4f, 0x9b, 0x17,
+    0xad, 0x2b, 0x41, 0x7b,     0xe6, 0x6c, 0x37, 0x10
+};
+#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */
+
+#if defined(MBEDTLS_AES_C)
+/* Truncation point of message for AES CMAC tests  */
+static const  unsigned int  aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
+    /* Mlen */
+    0,
+    16,
+    20,
+    64
+};
+
+/* CMAC-AES128 Test Data */
+static const unsigned char aes_128_key[16] = {
+    0x2b, 0x7e, 0x15, 0x16,     0x28, 0xae, 0xd2, 0xa6,
+    0xab, 0xf7, 0x15, 0x88,     0x09, 0xcf, 0x4f, 0x3c
+};
+static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
+    {
+        /* K1 */
+        0xfb, 0xee, 0xd6, 0x18,     0x35, 0x71, 0x33, 0x66,
+        0x7c, 0x85, 0xe0, 0x8f,     0x72, 0x36, 0xa8, 0xde
+    },
+    {
+        /* K2 */
+        0xf7, 0xdd, 0xac, 0x30,     0x6a, 0xe2, 0x66, 0xcc,
+        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] = {
+    {
+        /* Example #1 */
+        0xbb, 0x1d, 0x69, 0x29,     0xe9, 0x59, 0x37, 0x28,
+        0x7f, 0xa3, 0x7d, 0x12,     0x9b, 0x75, 0x67, 0x46
+    },
+    {
+        /* Example #2 */
+        0x07, 0x0a, 0x16, 0xb4,     0x6b, 0x4d, 0x41, 0x44,
+        0xf7, 0x9b, 0xdd, 0x9d,     0xd0, 0x4a, 0x28, 0x7c
+    },
+    {
+        /* Example #3 */
+        0x7d, 0x85, 0x44, 0x9e,     0xa6, 0xea, 0x19, 0xc8,
+        0x23, 0xa7, 0xbf, 0x78,     0x83, 0x7d, 0xfa, 0xde
+    },
+    {
+        /* Example #4 */
+        0x51, 0xf0, 0xbe, 0xbf,     0x7e, 0x3b, 0x9d, 0x92,
+        0xfc, 0x49, 0x74, 0x17,     0x79, 0x36, 0x3c, 0xfe
+    }
+};
+
+/* CMAC-AES192 Test Data */
+static const unsigned char aes_192_key[24] = {
+    0x8e, 0x73, 0xb0, 0xf7,     0xda, 0x0e, 0x64, 0x52,
+    0xc8, 0x10, 0xf3, 0x2b,     0x80, 0x90, 0x79, 0xe5,
+    0x62, 0xf8, 0xea, 0xd2,     0x52, 0x2c, 0x6b, 0x7b
+};
+static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
+    {
+        /* K1 */
+        0x44, 0x8a, 0x5b, 0x1c,     0x93, 0x51, 0x4b, 0x27,
+        0x3e, 0xe6, 0x43, 0x9d,     0xd4, 0xda, 0xa2, 0x96
+    },
+    {
+        /* K2 */
+        0x89, 0x14, 0xb6, 0x39,     0x26, 0xa2, 0x96, 0x4e,
+        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] = {
+    {
+        /* Example #1 */
+        0xd1, 0x7d, 0xdf, 0x46,     0xad, 0xaa, 0xcd, 0xe5,
+        0x31, 0xca, 0xc4, 0x83,     0xde, 0x7a, 0x93, 0x67
+    },
+    {
+        /* Example #2 */
+        0x9e, 0x99, 0xa7, 0xbf,     0x31, 0xe7, 0x10, 0x90,
+        0x06, 0x62, 0xf6, 0x5e,     0x61, 0x7c, 0x51, 0x84
+    },
+    {
+        /* Example #3 */
+        0x3d, 0x75, 0xc1, 0x94,     0xed, 0x96, 0x07, 0x04,
+        0x44, 0xa9, 0xfa, 0x7e,     0xc7, 0x40, 0xec, 0xf8
+    },
+    {
+        /* Example #4 */
+        0xa1, 0xd5, 0xdf, 0x0e,     0xed, 0x79, 0x0f, 0x79,
+        0x4d, 0x77, 0x58, 0x96,     0x59, 0xf3, 0x9a, 0x11
+    }
+};
+
+/* CMAC-AES256 Test Data */
+static const unsigned char aes_256_key[32] = {
+    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 aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
+    {
+        /* K1 */
+        0xca, 0xd1, 0xed, 0x03,     0x29, 0x9e, 0xed, 0xac,
+        0x2e, 0x9a, 0x99, 0x80,     0x86, 0x21, 0x50, 0x2f
+    },
+    {
+        /* K2 */
+        0x95, 0xa3, 0xda, 0x06,     0x53, 0x3d, 0xdb, 0x58,
+        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] = {
+    {
+        /* Example #1 */
+        0x02, 0x89, 0x62, 0xf6,     0x1b, 0x7b, 0xf8, 0x9e,
+        0xfc, 0x6b, 0x55, 0x1f,     0x46, 0x67, 0xd9, 0x83
+    },
+    {
+        /* Example #2 */
+        0x28, 0xa7, 0x02, 0x3f,     0x45, 0x2e, 0x8f, 0x82,
+        0xbd, 0x4b, 0xf2, 0x8d,     0x8c, 0x37, 0xc3, 0x5c
+    },
+    {
+        /* Example #3 */
+        0x15, 0x67, 0x27, 0xdc,     0x08, 0x78, 0x94, 0x4a,
+        0x02, 0x3c, 0x1f, 0xe0,     0x3b, 0xad, 0x6d, 0x93
+    },
+    {
+        /* Example #4 */
+        0xe1, 0x99, 0x21, 0x90,     0x54, 0x9f, 0x6e, 0xd5,
+        0x69, 0x6a, 0x2c, 0x05,     0x6c, 0x31, 0x54, 0x10
+    }
+};
+#endif /* MBEDTLS_AES_C */
+
+#if defined(MBEDTLS_DES_C)
+/* Truncation point of message for 3DES CMAC tests  */
+static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
+    0,
+    16,
+    20,
+    32
+};
+
+/* CMAC-TDES (Generation) - 2 Key Test Data */
+static const unsigned char des3_2key_key[24] = {
+    /* Key1 */
+    0x01, 0x23, 0x45, 0x67,     0x89, 0xab, 0xcd, 0xef,
+    /* Key2 */
+    0x23, 0x45, 0x67, 0x89,     0xab, 0xcd, 0xEF, 0x01,
+    /* Key3 */
+    0x01, 0x23, 0x45, 0x67,     0x89, 0xab, 0xcd, 0xef
+};
+static const unsigned char des3_2key_subkeys[2][8] = {
+    {
+        /* K1 */
+        0x0d, 0xd2, 0xcb, 0x7a,     0x3d, 0x88, 0x88, 0xd9
+    },
+    {
+        /* K2 */
+        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] = {
+    {
+        /* Sample #1 */
+        0x79, 0xce, 0x52, 0xa7,     0xf7, 0x86, 0xa9, 0x60
+    },
+    {
+        /* Sample #2 */
+        0xcc, 0x18, 0xa0, 0xb7,     0x9a, 0xf2, 0x41, 0x3b
+    },
+    {
+        /* Sample #3 */
+        0xc0, 0x6d, 0x37, 0x7e,     0xcd, 0x10, 0x19, 0x69
+    },
+    {
+        /* 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] = {
+    /* Key1 */
+    0x01, 0x23, 0x45, 0x67,     0x89, 0xaa, 0xcd, 0xef,
+    /* Key2 */
+    0x23, 0x45, 0x67, 0x89,     0xab, 0xcd, 0xef, 0x01,
+    /* Key3 */
+    0x45, 0x67, 0x89, 0xab,     0xcd, 0xef, 0x01, 0x23
+};
+static const unsigned char des3_3key_subkeys[2][8] = {
+    {
+        /* K1 */
+        0x9d, 0x74, 0xe7, 0x39,     0x33, 0x17, 0x96, 0xc0
+    },
+    {
+        /* K2 */
+        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] = {
+    {
+        /* Sample #1 */
+        0x7d, 0xb0, 0xd3, 0x7d,     0xf9, 0x36, 0xc5, 0x50
+    },
+    {
+        /* Sample #2 */
+        0x30, 0x23, 0x9c, 0xf1,     0xf5, 0x2e, 0x66, 0x09
+    },
+    {
+        /* Sample #3 */
+        0x6c, 0x9f, 0x3e, 0xe4,     0x92, 0x3f, 0x6b, 0xe2
+    },
+    {
+        /* Sample #4 */
+        0x99, 0x42, 0x9b, 0xd0,     0xbF, 0x79, 0x04, 0xe5
+    }
+};
+
+#endif /* MBEDTLS_DES_C */
+
+#if defined(MBEDTLS_AES_C)
+/* AES AES-CMAC-PRF-128 Test Data */
+static const unsigned char PRFK[] = {
+    /* Key */
+    0x00, 0x01, 0x02, 0x03,     0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0a, 0x0b,     0x0c, 0x0d, 0x0e, 0x0f,
+    0xed, 0xcb
+};
+
+/* Sizes in bytes */
+static const size_t PRFKlen[NB_PRF_TESTS] = {
+    18,
+    16,
+    10
+};
+
+/* Message */
+static const unsigned char PRFM[] = {
+    0x00, 0x01, 0x02, 0x03,     0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0a, 0x0b,     0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13
+};
+
+static const unsigned char PRFT[NB_PRF_TESTS][16] = {
+    {
+        0x84, 0xa3, 0x48, 0xa4,     0xa4, 0x5d, 0x23, 0x5b,
+        0xab, 0xff, 0xfc, 0x0d,     0x2b, 0x4d, 0xa0, 0x9a
+    },
+    {
+        0x98, 0x0a, 0xe8, 0x7b,     0x5f, 0x4c, 0x9c, 0x52,
+        0x14, 0xf5, 0xb6, 0xa8,     0x45, 0x5e, 0x4c, 0x2d
+    },
+    {
+        0x29, 0x0d, 0x9e, 0x11,     0x2e, 0xdb, 0x09, 0xee,
+        0x14, 0x1f, 0xcf, 0x64,     0xc0, 0xb7, 0x2f, 0x3d
+    }
+};
+#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 )
+{
+    int i, ret;
+    mbedtls_cipher_context_t ctx;
+    const mbedtls_cipher_info_t *cipher_info;
+    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 )
+    {
+        /* Failing at this point must be due to a build issue */
+        return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+    }
+
+    for( i = 0; i < num_tests; i++ )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "  %s CMAC subkey #%u: ", testname, i + 1 );
+
+        mbedtls_cipher_init( &ctx );
+
+        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( 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" );
+
+            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" );
+
+            goto cleanup;
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+
+        mbedtls_cipher_free( &ctx );
+    }
+
+    goto exit;
+
+cleanup:
+    mbedtls_cipher_free( &ctx );
+
+exit:
+    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 )
+{
+    const mbedtls_cipher_info_t *cipher_info;
+    int i, ret;
+    unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX];
+
+    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 #%u: ", testname, i + 1 );
+
+        if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages,
+                                         message_lengths[i], output ) ) != 0 )
+        {
+            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" );
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+
+exit:
+    return( ret );
+}
+
+#if defined(MBEDTLS_AES_C)
+static int test_aes128_cmac_prf( int verbose )
+{
+    int i;
+    int ret;
+    unsigned char output[MBEDTLS_AES_BLOCK_SIZE];
+
+    for( i = 0; i < NB_PRF_TESTS; i++ )
+    {
+        mbedtls_printf( "  AES CMAC 128 PRF #%u: ", 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" );
+
+            return( ret );
+        }
+        else if( verbose != 0 )
+        {
+            mbedtls_printf( "passed\n" );
+        }
+    }
+    return( ret );
+}
+#endif /* MBEDTLS_AES_C */
+
+int mbedtls_cmac_self_test( int verbose )
+{
+    int ret;
+
+#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_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_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_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_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_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 );
+#endif /* MBEDTLS_AES_C */
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_CMAC_C */

+ 1 - 0
Pal/lib/crypto/mbedtls/dhm.c

@@ -48,6 +48,7 @@
 #if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
 #else
+#include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
 #define mbedtls_printf     printf

+ 297 - 0
Pal/lib/crypto/mbedtls/mbedtls/aes.h

@@ -0,0 +1,297 @@
+/**
+ * \file aes.h
+ *
+ * \brief AES block cipher
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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)
+ */
+#ifndef MBEDTLS_AES_H
+#define MBEDTLS_AES_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+/* padlock.c and aesni.c rely on these values! */
+#define MBEDTLS_AES_ENCRYPT     1
+#define MBEDTLS_AES_DECRYPT     0
+
+#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH                -0x0020  /**< Invalid key length. */
+#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH              -0x0022  /**< Invalid data input length. */
+
+#if !defined(MBEDTLS_AES_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          AES context structure
+ *
+ * \note           buf is able to hold 32 extra bytes, which can be used:
+ *                 - for alignment purposes if VIA padlock is used, and/or
+ *                 - to simplify key expansion in the 256-bit case by
+ *                 generating an extra round key
+ */
+typedef struct
+{
+    int nr;                     /*!<  number of rounds  */
+    uint32_t *rk;               /*!<  AES round keys    */
+    uint32_t buf[68];           /*!<  unaligned data    */
+}
+mbedtls_aes_context;
+
+/**
+ * \brief          Initialize AES context
+ *
+ * \param ctx      AES context to be initialized
+ */
+void mbedtls_aes_init( mbedtls_aes_context *ctx );
+
+/**
+ * \brief          Clear AES context
+ *
+ * \param ctx      AES context to be cleared
+ */
+void mbedtls_aes_free( mbedtls_aes_context *ctx );
+
+/**
+ * \brief          AES key schedule (encryption)
+ *
+ * \param ctx      AES context to be initialized
+ * \param key      encryption key
+ * \param keybits  must be 128, 192 or 256
+ *
+ * \return         0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
+ */
+int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
+                    unsigned int keybits );
+
+/**
+ * \brief          AES key schedule (decryption)
+ *
+ * \param ctx      AES context to be initialized
+ * \param key      decryption key
+ * \param keybits  must be 128, 192 or 256
+ *
+ * \return         0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
+ */
+int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
+                    unsigned int keybits );
+
+/**
+ * \brief          AES-ECB block encryption/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 if successful
+ */
+int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
+                    int mode,
+                    const unsigned char input[16],
+                    unsigned char output[16] );
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+/**
+ * \brief          AES-CBC buffer encryption/decryption
+ *                 Length should be a multiple of the block
+ *                 size (16 bytes)
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \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 successful, or MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
+ */
+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 );
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+/**
+ * \brief          AES-CFB128 buffer encryption/decryption.
+ *
+ * Note: Due to the nature of CFB you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \param ctx      AES context
+ * \param mode     MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
+ * \param length   length of the input data
+ * \param iv_off   offset in IV (updated after use)
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ *
+ * \return         0 if successful
+ */
+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 );
+
+/**
+ * \brief          AES-CFB8 buffer encryption/decryption.
+ *
+ * Note: Due to the nature of CFB you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
+ *
+ * \note           Upon exit, the content of the IV is updated so that you can
+ *                 call the function same function again on the following
+ *                 block(s) of data and get the same result as if it was
+ *                 encrypted in one call. This allows a "streaming" usage.
+ *                 If on the other hand you need to retain the contents of the
+ *                 IV, you should either save it manually or use the cipher
+ *                 module instead.
+ *
+ * \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 successful
+ */
+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 );
+#endif /*MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+/**
+ * \brief               AES-CTR buffer encryption/decryption
+ *
+ * Warning: You have to keep the maximum use of your counter in mind!
+ *
+ * Note: Due to the nature of CTR you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
+ *
+ * \param ctx           AES context
+ * \param length        The length of the data
+ * \param nc_off        The offset in the current stream_block (for resuming
+ *                      within current cipher stream). The offset pointer to
+ *                      should be 0 at the start of a stream.
+ * \param nonce_counter The 128-bit nonce and counter.
+ * \param stream_block  The saved stream-block for resuming. Is overwritten
+ *                      by the function.
+ * \param input         The input data stream
+ * \param output        The output data stream
+ *
+ * \return         0 if successful
+ */
+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 );
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+
+/**
+ * \brief           Internal AES block encryption function
+ *                  (Only exposed to allow overriding it,
+ *                  see MBEDTLS_AES_ENCRYPT_ALT)
+ *
+ * \param ctx       AES context
+ * \param input     Plaintext block
+ * \param output    Output (ciphertext) block
+ */
+void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
+                          const unsigned char input[16],
+                          unsigned char output[16] );
+
+/**
+ * \brief           Internal AES block decryption function
+ *                  (Only exposed to allow overriding it,
+ *                  see MBEDTLS_AES_DECRYPT_ALT)
+ *
+ * \param ctx       AES context
+ * \param input     Ciphertext block
+ * \param output    Output (plaintext) block
+ */
+void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
+                          const unsigned char input[16],
+                          unsigned char output[16] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else  /* MBEDTLS_AES_ALT */
+#include "aes_alt.h"
+#endif /* MBEDTLS_AES_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int mbedtls_aes_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* aes.h */

+ 111 - 0
Pal/lib/crypto/mbedtls/mbedtls/aesni.h

@@ -0,0 +1,111 @@
+/**
+ * \file aesni.h
+ *
+ * \brief AES-NI for hardware AES acceleration on some Intel processors
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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)
+ */
+#ifndef MBEDTLS_AESNI_H
+#define MBEDTLS_AESNI_H
+
+#include "aes.h"
+
+#define MBEDTLS_AESNI_AES      0x02000000u
+#define MBEDTLS_AESNI_CLMUL    0x00000002u
+
+#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_HAVE_X86_64)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          AES-NI features detection routine
+ *
+ * \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          AES-NI AES-ECB block en(de)cryption
+ *
+ * \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          GCM multiplication: c = a * b in GF(2^128)
+ *
+ * \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           Compute decryption round keys from 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_aesni_inverse_key( unsigned char *invkey,
+                        const unsigned char *fwdkey, int nr );
+
+/**
+ * \brief           Perform 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_aesni_setkey_enc( unsigned char *rk,
+                      const unsigned char *key,
+                      size_t bits );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_HAVE_X86_64 */
+
+#endif /* MBEDTLS_AESNI_H */

+ 711 - 0
Pal/lib/crypto/mbedtls/mbedtls/cipher.h

@@ -0,0 +1,711 @@
+/**
+ * \file cipher.h
+ *
+ * \brief Generic cipher wrapper.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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)
+ */
+
+#ifndef MBEDTLS_CIPHER_H
+#define MBEDTLS_CIPHER_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)
+#define MBEDTLS_CIPHER_MODE_AEAD
+#endif
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#define MBEDTLS_CIPHER_MODE_WITH_PADDING
+#endif
+
+#if defined(MBEDTLS_ARC4_C)
+#define MBEDTLS_CIPHER_MODE_STREAM
+#endif
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE            -0x6080  /**< The selected feature is not available. */
+#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA                 -0x6100  /**< Bad input parameters to function. */
+#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED                   -0x6180  /**< Failed to allocate memory. */
+#define MBEDTLS_ERR_CIPHER_INVALID_PADDING                -0x6200  /**< Input data contains invalid padding and is rejected. */
+#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED            -0x6280  /**< Decryption of block requires a full block. */
+#define MBEDTLS_ERR_CIPHER_AUTH_FAILED                    -0x6300  /**< Authentication failed (for AEAD modes). */
+#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT              -0x6380  /**< The context is invalid, eg because it was free()ed. */
+
+#define MBEDTLS_CIPHER_VARIABLE_IV_LEN     0x01    /**< Cipher accepts IVs of variable length */
+#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN    0x02    /**< Cipher accepts keys of variable length */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    MBEDTLS_CIPHER_ID_NONE = 0,
+    MBEDTLS_CIPHER_ID_NULL,
+    MBEDTLS_CIPHER_ID_AES,
+    MBEDTLS_CIPHER_ID_DES,
+    MBEDTLS_CIPHER_ID_3DES,
+    MBEDTLS_CIPHER_ID_CAMELLIA,
+    MBEDTLS_CIPHER_ID_BLOWFISH,
+    MBEDTLS_CIPHER_ID_ARC4,
+} mbedtls_cipher_id_t;
+
+typedef enum {
+    MBEDTLS_CIPHER_NONE = 0,
+    MBEDTLS_CIPHER_NULL,
+    MBEDTLS_CIPHER_AES_128_ECB,
+    MBEDTLS_CIPHER_AES_192_ECB,
+    MBEDTLS_CIPHER_AES_256_ECB,
+    MBEDTLS_CIPHER_AES_128_CBC,
+    MBEDTLS_CIPHER_AES_192_CBC,
+    MBEDTLS_CIPHER_AES_256_CBC,
+    MBEDTLS_CIPHER_AES_128_CFB128,
+    MBEDTLS_CIPHER_AES_192_CFB128,
+    MBEDTLS_CIPHER_AES_256_CFB128,
+    MBEDTLS_CIPHER_AES_128_CTR,
+    MBEDTLS_CIPHER_AES_192_CTR,
+    MBEDTLS_CIPHER_AES_256_CTR,
+    MBEDTLS_CIPHER_AES_128_GCM,
+    MBEDTLS_CIPHER_AES_192_GCM,
+    MBEDTLS_CIPHER_AES_256_GCM,
+    MBEDTLS_CIPHER_CAMELLIA_128_ECB,
+    MBEDTLS_CIPHER_CAMELLIA_192_ECB,
+    MBEDTLS_CIPHER_CAMELLIA_256_ECB,
+    MBEDTLS_CIPHER_CAMELLIA_128_CBC,
+    MBEDTLS_CIPHER_CAMELLIA_192_CBC,
+    MBEDTLS_CIPHER_CAMELLIA_256_CBC,
+    MBEDTLS_CIPHER_CAMELLIA_128_CFB128,
+    MBEDTLS_CIPHER_CAMELLIA_192_CFB128,
+    MBEDTLS_CIPHER_CAMELLIA_256_CFB128,
+    MBEDTLS_CIPHER_CAMELLIA_128_CTR,
+    MBEDTLS_CIPHER_CAMELLIA_192_CTR,
+    MBEDTLS_CIPHER_CAMELLIA_256_CTR,
+    MBEDTLS_CIPHER_CAMELLIA_128_GCM,
+    MBEDTLS_CIPHER_CAMELLIA_192_GCM,
+    MBEDTLS_CIPHER_CAMELLIA_256_GCM,
+    MBEDTLS_CIPHER_DES_ECB,
+    MBEDTLS_CIPHER_DES_CBC,
+    MBEDTLS_CIPHER_DES_EDE_ECB,
+    MBEDTLS_CIPHER_DES_EDE_CBC,
+    MBEDTLS_CIPHER_DES_EDE3_ECB,
+    MBEDTLS_CIPHER_DES_EDE3_CBC,
+    MBEDTLS_CIPHER_BLOWFISH_ECB,
+    MBEDTLS_CIPHER_BLOWFISH_CBC,
+    MBEDTLS_CIPHER_BLOWFISH_CFB64,
+    MBEDTLS_CIPHER_BLOWFISH_CTR,
+    MBEDTLS_CIPHER_ARC4_128,
+    MBEDTLS_CIPHER_AES_128_CCM,
+    MBEDTLS_CIPHER_AES_192_CCM,
+    MBEDTLS_CIPHER_AES_256_CCM,
+    MBEDTLS_CIPHER_CAMELLIA_128_CCM,
+    MBEDTLS_CIPHER_CAMELLIA_192_CCM,
+    MBEDTLS_CIPHER_CAMELLIA_256_CCM,
+} mbedtls_cipher_type_t;
+
+typedef enum {
+    MBEDTLS_MODE_NONE = 0,
+    MBEDTLS_MODE_ECB,
+    MBEDTLS_MODE_CBC,
+    MBEDTLS_MODE_CFB,
+    MBEDTLS_MODE_OFB, /* Unused! */
+    MBEDTLS_MODE_CTR,
+    MBEDTLS_MODE_GCM,
+    MBEDTLS_MODE_STREAM,
+    MBEDTLS_MODE_CCM,
+} mbedtls_cipher_mode_t;
+
+typedef enum {
+    MBEDTLS_PADDING_PKCS7 = 0,     /**< PKCS7 padding (default)        */
+    MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding         */
+    MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding             */
+    MBEDTLS_PADDING_ZEROS,         /**< zero padding (not reversible!) */
+    MBEDTLS_PADDING_NONE,          /**< never pad (full blocks only)   */
+} mbedtls_cipher_padding_t;
+
+typedef enum {
+    MBEDTLS_OPERATION_NONE = -1,
+    MBEDTLS_DECRYPT = 0,
+    MBEDTLS_ENCRYPT,
+} mbedtls_operation_t;
+
+enum {
+    /** Undefined key length */
+    MBEDTLS_KEY_LENGTH_NONE = 0,
+    /** Key length, in bits (including parity), for DES keys */
+    MBEDTLS_KEY_LENGTH_DES  = 64,
+    /** Key length, in bits (including parity), for DES in two key EDE */
+    MBEDTLS_KEY_LENGTH_DES_EDE = 128,
+    /** Key length, in bits (including parity), for DES in three-key EDE */
+    MBEDTLS_KEY_LENGTH_DES_EDE3 = 192,
+};
+
+/** Maximum length of any IV, in bytes */
+#define MBEDTLS_MAX_IV_LENGTH      16
+/** Maximum block size of any cipher, in bytes */
+#define MBEDTLS_MAX_BLOCK_LENGTH   16
+
+/**
+ * Base cipher information (opaque struct).
+ */
+typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t;
+
+/**
+ * CMAC context (opaque struct).
+ */
+typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t;
+
+/**
+ * Cipher information. Allows cipher functions to be called in a generic way.
+ */
+typedef struct {
+    /** Full cipher identifier (e.g. MBEDTLS_CIPHER_AES_256_CBC) */
+    mbedtls_cipher_type_t type;
+
+    /** Cipher mode (e.g. MBEDTLS_MODE_CBC) */
+    mbedtls_cipher_mode_t mode;
+
+    /** Cipher key length, in bits (default length for variable sized ciphers)
+     *  (Includes parity bits for ciphers like DES) */
+    unsigned int key_bitlen;
+
+    /** Name of the cipher */
+    const char * name;
+
+    /** IV/NONCE size, in bytes.
+     *  For cipher that accept many sizes: recommended size */
+    unsigned int iv_size;
+
+    /** Flags for variable IV size, variable key size, etc. */
+    int flags;
+
+    /** block size, in bytes */
+    unsigned int block_size;
+
+    /** Base cipher information and functions */
+    const mbedtls_cipher_base_t *base;
+
+} mbedtls_cipher_info_t;
+
+/**
+ * Generic cipher context.
+ */
+typedef struct {
+    /** Information about the associated cipher */
+    const mbedtls_cipher_info_t *cipher_info;
+
+    /** Key length to use */
+    int key_bitlen;
+
+    /** Operation that the context's key has been initialised for */
+    mbedtls_operation_t operation;
+
+#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
+    /** Padding functions to use, if relevant for cipher mode */
+    void (*add_padding)( unsigned char *output, size_t olen, size_t data_len );
+    int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len );
+#endif
+
+    /** Buffer for data that hasn't been encrypted yet */
+    unsigned char unprocessed_data[MBEDTLS_MAX_BLOCK_LENGTH];
+
+    /** Number of bytes that still need processing */
+    size_t unprocessed_len;
+
+    /** Current IV or NONCE_COUNTER for CTR-mode */
+    unsigned char iv[MBEDTLS_MAX_IV_LENGTH];
+
+    /** IV size in bytes (for ciphers with variable-length IVs) */
+    size_t iv_size;
+
+    /** Cipher-specific context */
+    void *cipher_ctx;
+
+#if defined(MBEDTLS_CMAC_C)
+    /** CMAC Specific context */
+    mbedtls_cmac_context_t *cmac_ctx;
+#endif
+} mbedtls_cipher_context_t;
+
+/**
+ * \brief Returns the list of ciphers supported by the generic cipher module.
+ *
+ * \return              a statically allocated array of ciphers, the last entry
+ *                      is 0.
+ */
+const int *mbedtls_cipher_list( void );
+
+/**
+ * \brief               Returns the cipher information structure associated
+ *                      with the given cipher name.
+ *
+ * \param cipher_name   Name of the cipher to search for.
+ *
+ * \return              the cipher information structure associated with the
+ *                      given cipher_name, or NULL if not found.
+ */
+#if 0
+const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name );
+#endif
+
+/**
+ * \brief               Returns the cipher information structure associated
+ *                      with the given cipher type.
+ *
+ * \param cipher_type   Type of the cipher to search for.
+ *
+ * \return              the cipher information structure associated with the
+ *                      given cipher_type, or NULL if not found.
+ */
+const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type );
+
+/**
+ * \brief               Returns the cipher information structure associated
+ *                      with the given cipher id, key size and mode.
+ *
+ * \param cipher_id     Id of the cipher to search for
+ *                      (e.g. MBEDTLS_CIPHER_ID_AES)
+ * \param key_bitlen    Length of the key in bits
+ * \param mode          Cipher mode (e.g. MBEDTLS_MODE_CBC)
+ *
+ * \return              the cipher information structure associated with the
+ *                      given cipher_type, or NULL if not found.
+ */
+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 );
+
+/**
+ * \brief               Initialize a cipher_context (as NONE)
+ */
+void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx );
+
+/**
+ * \brief               Free and clear the cipher-specific context of ctx.
+ *                      Freeing ctx itself remains the responsibility of the
+ *                      caller.
+ */
+void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx );
+
+/**
+ * \brief               Initialises and fills the cipher context structure with
+ *                      the appropriate values.
+ *
+ * \note                Currently also clears structure. In future versions you
+ *                      will be required to call mbedtls_cipher_init() on the structure
+ *                      first.
+ *
+ * \param ctx           context to initialise. May not be NULL.
+ * \param cipher_info   cipher to use.
+ *
+ * \return              0 on success,
+ *                      MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on parameter failure,
+ *                      MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the
+ *                      cipher-specific context failed.
+ */
+int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info );
+
+/**
+ * \brief               Returns the block size of the given cipher.
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              size of the cipher's blocks, or 0 if ctx has not been
+ *                      initialised.
+ */
+static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return 0;
+
+    return ctx->cipher_info->block_size;
+}
+
+/**
+ * \brief               Returns the mode of operation for the cipher.
+ *                      (e.g. MBEDTLS_MODE_CBC)
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              mode of operation, or MBEDTLS_MODE_NONE if ctx
+ *                      has not been initialised.
+ */
+static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtls_cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return MBEDTLS_MODE_NONE;
+
+    return ctx->cipher_info->mode;
+}
+
+/**
+ * \brief               Returns the size of the cipher's IV/NONCE in bytes.
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              If IV has not been set yet: (recommended) IV size
+ *                      (0 for ciphers not using IV/NONCE).
+ *                      If IV has already been set: actual size.
+ */
+static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return 0;
+
+    if( ctx->iv_size != 0 )
+        return (int) ctx->iv_size;
+
+    return (int) ctx->cipher_info->iv_size;
+}
+
+/**
+ * \brief               Returns the type of the given cipher.
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              type of the cipher, or MBEDTLS_CIPHER_NONE if ctx has
+ *                      not been initialised.
+ */
+static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return MBEDTLS_CIPHER_NONE;
+
+    return ctx->cipher_info->type;
+}
+
+/**
+ * \brief               Returns the name of the given cipher, as a string.
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              name of the cipher, or NULL if ctx was not initialised.
+ */
+static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return 0;
+
+    return ctx->cipher_info->name;
+}
+
+/**
+ * \brief               Returns the key length of the cipher.
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              cipher's key length, in bits, or
+ *                      MBEDTLS_KEY_LENGTH_NONE if ctx has not been
+ *                      initialised.
+ */
+static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return MBEDTLS_KEY_LENGTH_NONE;
+
+    return (int) ctx->cipher_info->key_bitlen;
+}
+
+/**
+ * \brief               Returns the operation of the given cipher.
+ *
+ * \param ctx           cipher's context. Must have been initialised.
+ *
+ * \return              operation (MBEDTLS_ENCRYPT or MBEDTLS_DECRYPT),
+ *                      or MBEDTLS_OPERATION_NONE if ctx has not been
+ *                      initialised.
+ */
+static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_cipher_context_t *ctx )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return MBEDTLS_OPERATION_NONE;
+
+    return ctx->operation;
+}
+
+/**
+ * \brief               Set the key to use with the given context.
+ *
+ * \param ctx           generic cipher context. May not be NULL. Must have been
+ *                      initialised using cipher_context_from_type or
+ *                      cipher_context_from_string.
+ * \param key           The key to use.
+ * \param key_bitlen    key length to use, in bits.
+ * \param operation     Operation that the key will be used for, either
+ *                      MBEDTLS_ENCRYPT or MBEDTLS_DECRYPT.
+ *
+ * \returns             0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if
+ *                      parameter verification fails or a cipher specific
+ *                      error code.
+ */
+int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key,
+                   int key_bitlen, const mbedtls_operation_t operation );
+
+#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
+/**
+ * \brief               Set padding mode, for cipher modes that use padding.
+ *                      (Default: PKCS7 padding.)
+ *
+ * \param ctx           generic cipher context
+ * \param mode          padding mode
+ *
+ * \returns             0 on success, MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE
+ *                      if selected padding mode is not supported, or
+ *                      MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode
+ *                      does not support padding.
+ */
+int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode );
+#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
+
+/**
+ * \brief               Set the initialization vector (IV) or nonce
+ *
+ * \param ctx           generic cipher context
+ * \param iv            IV to use (or NONCE_COUNTER for CTR-mode ciphers)
+ * \param iv_len        IV length for ciphers with variable-size IV;
+ *                      discarded by ciphers with fixed-size IV.
+ *
+ * \returns             0 on success, or MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+ *
+ * \note                Some ciphers don't use IVs nor NONCE. For these
+ *                      ciphers, this function has no effect.
+ */
+int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
+                   const unsigned char *iv, size_t iv_len );
+
+/**
+ * \brief               Finish preparation of the given context
+ *
+ * \param ctx           generic cipher context
+ *
+ * \returns             0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
+ *                      if parameter verification fails.
+ */
+int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx );
+
+#if defined(MBEDTLS_GCM_C)
+/**
+ * \brief               Add additional data (for AEAD ciphers).
+ *                      Currently only supported with GCM.
+ *                      Must be called exactly once, after mbedtls_cipher_reset().
+ *
+ * \param ctx           generic cipher context
+ * \param ad            Additional data to use.
+ * \param ad_len        Length of ad.
+ *
+ * \return              0 on success, or a specific error code.
+ */
+int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
+                      const unsigned char *ad, size_t ad_len );
+#endif /* MBEDTLS_GCM_C */
+
+/**
+ * \brief               Generic cipher update function. Encrypts/decrypts
+ *                      using the given cipher context. Writes as many block
+ *                      size'd blocks of data as possible to output. Any data
+ *                      that cannot be written immediately will either be added
+ *                      to the next block, or flushed when cipher_final is
+ *                      called.
+ *                      Exception: for MBEDTLS_MODE_ECB, expects single block
+ *                                 in size (e.g. 16 bytes for AES)
+ *
+ * \param ctx           generic cipher context
+ * \param input         buffer holding the input data
+ * \param ilen          length of the input data
+ * \param output        buffer for the output data. Should be able to hold at
+ *                      least ilen + block_size. Cannot be the same buffer as
+ *                      input!
+ * \param olen          length of the output data, will be filled with the
+ *                      actual number of bytes written.
+ *
+ * \returns             0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if
+ *                      parameter verification fails,
+ *                      MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an
+ *                      unsupported mode for a cipher or a cipher specific
+ *                      error code.
+ *
+ * \note                If the underlying cipher is GCM, all calls to this
+ *                      function, except the last one before mbedtls_cipher_finish(),
+ *                      must have ilen a multiple of the block size.
+ */
+int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
+                   size_t ilen, unsigned char *output, size_t *olen );
+
+/**
+ * \brief               Generic cipher finalisation function. If data still
+ *                      needs to be flushed from an incomplete block, data
+ *                      contained within it will be padded with the size of
+ *                      the last block, and written to the output buffer.
+ *
+ * \param ctx           Generic cipher context
+ * \param output        buffer to write data to. Needs block_size available.
+ * \param olen          length of the data written to the output buffer.
+ *
+ * \returns             0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if
+ *                      parameter verification fails,
+ *                      MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption
+ *                      expected a full block but was not provided one,
+ *                      MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding
+ *                      while decrypting or a cipher specific error code.
+ */
+int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
+                   unsigned char *output, size_t *olen );
+
+#if defined(MBEDTLS_GCM_C)
+/**
+ * \brief               Write tag for AEAD ciphers.
+ *                      Currently only supported with GCM.
+ *                      Must be called after mbedtls_cipher_finish().
+ *
+ * \param ctx           Generic cipher context
+ * \param tag           buffer to write the tag
+ * \param tag_len       Length of the tag to write
+ *
+ * \return              0 on success, or a specific error code.
+ */
+int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
+                      unsigned char *tag, size_t tag_len );
+
+/**
+ * \brief               Check tag for AEAD ciphers.
+ *                      Currently only supported with GCM.
+ *                      Must be called after mbedtls_cipher_finish().
+ *
+ * \param ctx           Generic cipher context
+ * \param tag           Buffer holding the tag
+ * \param tag_len       Length of the tag to check
+ *
+ * \return              0 on success, or a specific error code.
+ */
+int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
+                      const unsigned char *tag, size_t tag_len );
+#endif /* MBEDTLS_GCM_C */
+
+/**
+ * \brief               Generic all-in-one encryption/decryption
+ *                      (for all ciphers except AEAD constructs).
+ *
+ * \param ctx           generic cipher context
+ * \param iv            IV to use (or NONCE_COUNTER for CTR-mode ciphers)
+ * \param iv_len        IV length for ciphers with variable-size IV;
+ *                      discarded by ciphers with fixed-size IV.
+ * \param input         buffer holding the input data
+ * \param ilen          length of the input data
+ * \param output        buffer for the output data. Should be able to hold at
+ *                      least ilen + block_size. Cannot be the same buffer as
+ *                      input!
+ * \param olen          length of the output data, will be filled with the
+ *                      actual number of bytes written.
+ *
+ * \note                Some ciphers don't use IVs nor NONCE. For these
+ *                      ciphers, use iv = NULL and iv_len = 0.
+ *
+ * \returns             0 on success, or
+ *                      MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or
+ *                      MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption
+ *                      expected a full block but was not provided one, or
+ *                      MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding
+ *                      while decrypting, or
+ *                      a cipher specific error code.
+ */
+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 );
+
+#if defined(MBEDTLS_CIPHER_MODE_AEAD)
+/**
+ * \brief               Generic autenticated encryption (AEAD ciphers).
+ *
+ * \param ctx           generic cipher context
+ * \param iv            IV to use (or NONCE_COUNTER for CTR-mode ciphers)
+ * \param iv_len        IV length for ciphers with variable-size IV;
+ *                      discarded by ciphers with fixed-size IV.
+ * \param ad            Additional data to authenticate.
+ * \param ad_len        Length of ad.
+ * \param input         buffer holding the input data
+ * \param ilen          length of the input data
+ * \param output        buffer for the output data.
+ *                      Should be able to hold at least ilen.
+ * \param olen          length of the output data, will be filled with the
+ *                      actual number of bytes written.
+ * \param tag           buffer for the authentication tag
+ * \param tag_len       desired tag length
+ *
+ * \returns             0 on success, or
+ *                      MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or
+ *                      a cipher specific error code.
+ */
+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 );
+
+/**
+ * \brief               Generic autenticated decryption (AEAD ciphers).
+ *
+ * \param ctx           generic cipher context
+ * \param iv            IV to use (or NONCE_COUNTER for CTR-mode ciphers)
+ * \param iv_len        IV length for ciphers with variable-size IV;
+ *                      discarded by ciphers with fixed-size IV.
+ * \param ad            Additional data to be authenticated.
+ * \param ad_len        Length of ad.
+ * \param input         buffer holding the input data
+ * \param ilen          length of the input data
+ * \param output        buffer for the output data.
+ *                      Should be able to hold at least ilen.
+ * \param olen          length of the output data, will be filled with the
+ *                      actual number of bytes written.
+ * \param tag           buffer holding the authentication tag
+ * \param tag_len       length of the authentication tag
+ *
+ * \returns             0 on success, or
+ *                      MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or
+ *                      MBEDTLS_ERR_CIPHER_AUTH_FAILED if data isn't authentic,
+ *                      or a cipher specific error code.
+ *
+ * \note                If the data is not authentic, then the output buffer
+ *                      is zeroed out to prevent the unauthentic plaintext to
+ *                      be used by mistake, making this interface safer.
+ */
+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 );
+#endif /* MBEDTLS_CIPHER_MODE_AEAD */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_CIPHER_H */

+ 109 - 0
Pal/lib/crypto/mbedtls/mbedtls/cipher_internal.h

@@ -0,0 +1,109 @@
+/**
+ * \file cipher_internal.h
+ *
+ * \brief Cipher wrappers.
+ *
+ * \author Adriaan de Jong <dejong@fox-it.com>
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  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)
+ */
+#ifndef MBEDTLS_CIPHER_WRAP_H
+#define MBEDTLS_CIPHER_WRAP_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include "cipher.h"
+
+#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_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_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 );
+
+    /** 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;
+
+extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[];
+
+extern int mbedtls_cipher_supported[];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_CIPHER_WRAP_H */

+ 170 - 0
Pal/lib/crypto/mbedtls/mbedtls/cmac.h

@@ -0,0 +1,170 @@
+/**
+ * \file cmac.h
+ *
+ * \brief Cipher-based Message Authentication Code (CMAC) Mode for
+ *        Authentication
+ *
+ *  Copyright (C) 2015-2016, ARM Limited, All Rights Reserved
+ *  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)
+ */
+#ifndef MBEDTLS_CMAC_H
+#define MBEDTLS_CMAC_H
+
+#include "cipher.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MBEDTLS_AES_BLOCK_SIZE          16
+#define MBEDTLS_DES3_BLOCK_SIZE         8
+
+#if defined(MBEDTLS_AES_C)
+#define MBEDTLS_CIPHER_BLKSIZE_MAX      16  /* longest used by CMAC is AES */
+#else
+#define MBEDTLS_CIPHER_BLKSIZE_MAX      8   /* longest used by CMAC is 3DES */
+#endif
+
+/**
+ * CMAC context structure - Contains internal state information only
+ */
+struct mbedtls_cmac_context_t
+{
+    /** Internal state of the CMAC algorithm  */
+    unsigned char       state[MBEDTLS_CIPHER_BLKSIZE_MAX];
+
+    /** Unprocessed data - either data that was not block aligned and is still
+     *  pending to be processed, or the final block */
+    unsigned char       unprocessed_block[MBEDTLS_CIPHER_BLKSIZE_MAX];
+
+    /** Length of data pending to be processed */
+    size_t              unprocessed_len;
+};
+
+/**
+ * \brief               Set the CMAC key and prepare to authenticate the input
+ *                      data.
+ *                      Should be called with an initialized cipher context.
+ *
+ * \param ctx           Cipher context. This should be a cipher context,
+ *                      initialized to be one of the following types:
+ *                      MBEDTLS_CIPHER_AES_128_ECB, MBEDTLS_CIPHER_AES_192_ECB,
+ *                      MBEDTLS_CIPHER_AES_256_ECB or
+ *                      MBEDTLS_CIPHER_DES_EDE3_ECB.
+ * \param key           CMAC key
+ * \param keybits       length of the CMAC key in bits
+ *                      (must be acceptable by the cipher)
+ *
+ * \return              0 if successful, or a cipher specific error code
+ */
+int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx,
+                                const unsigned char *key, size_t keybits );
+
+/**
+ * \brief               Generic CMAC process buffer.
+ *                      Called between mbedtls_cipher_cmac_starts() or
+ *                      mbedtls_cipher_cmac_reset() and
+ *                      mbedtls_cipher_cmac_finish().
+ *                      May be called repeatedly.
+ *
+ * \param ctx           CMAC context
+ * \param input         buffer holding the  data
+ * \param ilen          length of the input data
+ *
+ * \returns             0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter
+ *                      verification fails.
+ */
+int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx,
+                                const unsigned char *input, size_t ilen );
+
+/**
+ * \brief               Output CMAC.
+ *                      Called after mbedtls_cipher_cmac_update().
+ *                      Usually followed by mbedtls_cipher_cmac_reset(), then
+ *                      mbedtls_cipher_cmac_starts(), or mbedtls_cipher_free().
+ *
+ * \param ctx           CMAC context
+ * \param output        Generic CMAC checksum result
+ *
+ * \returns             0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter
+ *                      verification fails.
+ */
+int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx,
+                                unsigned char *output );
+
+/**
+ * \brief               Prepare to authenticate a new message with the same key.
+ *                      Called after mbedtls_cipher_cmac_finish() and before
+ *                      mbedtls_cipher_cmac_update().
+ *
+ * \param ctx           CMAC context to be reset
+ *
+ * \returns             0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter
+ *                      verification fails.
+ */
+int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx );
+
+/**
+ * \brief               Output = Generic_CMAC( cmac key, input buffer )
+ *
+ * \param cipher_info   message digest info
+ * \param key           CMAC key
+ * \param keylen        length of the CMAC key in bits
+ * \param input         buffer holding the  data
+ * \param ilen          length of the input data
+ * \param output        Generic CMAC-result
+ *
+ * \returns             0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter
+ *                      verification fails.
+ */
+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 );
+
+#if defined(MBEDTLS_AES_C)
+/**
+ * \brief           AES-CMAC-128-PRF
+ *                  Implementation of (AES-CMAC-PRF-128), as defined in RFC 4615
+ *
+ * \param key       PRF key
+ * \param key_len   PRF key length in bytes
+ * \param input     buffer holding the input data
+ * \param in_len    length of the input data in bytes
+ * \param output    buffer holding the generated pseudorandom output (16 bytes)
+ *
+ * \return          0 if successful
+ */
+int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len,
+                              const unsigned char *input, size_t in_len,
+                              unsigned char output[16] );
+#endif /* MBEDTLS_AES_C */
+
+#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) )
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int mbedtls_cmac_self_test( int verbose );
+#endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_CMAC_H */

+ 8 - 0
Pal/lib/crypto/mbedtls/mbedtls/config.h

@@ -18,6 +18,14 @@
 #ifndef MBEDTLS_CONFIG_H
 #define MBEDTLS_CONFIG_H
 
+#define MBEDTLS_AES_C
+#define MBEDTLS_AESNI_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_CMAC_C
+#define MBEDTLS_DHM_C
+#define MBEDTLS_HAVE_ASM
+#define MBEDTLS_HAVE_X86_64
 #define MBEDTLS_BIGNUM_C
 #define MBEDTLS_DHM_C
 #define MBEDTLS_SHA256_C

+ 1 - 0
Pal/lib/crypto/mbedtls/mbedtls/platform.h

@@ -18,6 +18,7 @@
 #ifndef MBEDTLS_PLATFORM_H
 #define MBEDTLS_PLATFORM_H
 
+/* For standard library apis. */
 #include "api.h"
 
 void * malloc(size_t size);

+ 0 - 3
Pal/lib/crypto/rsa.c

@@ -30,9 +30,6 @@ int _DkRandomBitsRead (void  *buffer, int size);
 int DkRandomBitsRead (void  *buffer, int size);
 #endif
 
-void * malloc (int size);
-void free (void * mem);
-
 #define XMALLOC malloc
 #define XFREE   free
 

+ 1 - 1
Pal/lib/crypto/aes.c → Pal/lib/crypto/wolfssl/aes.c

@@ -23,7 +23,7 @@
  */
 
 #include "aes.h"
-#include "error-crypt.h"
+#include "crypto/error-crypt.h"
 #include "api.h"
 
 #define XMEMSET memset

+ 0 - 0
Pal/lib/crypto/aes.h → Pal/lib/crypto/wolfssl/aes.h


+ 0 - 0
Pal/lib/crypto/aes_ni.S → Pal/lib/crypto/wolfssl/aes_ni.S


+ 0 - 0
Pal/lib/crypto/cmac.c → Pal/lib/crypto/wolfssl/cmac.c


+ 0 - 0
Pal/lib/crypto/cmac.h → Pal/lib/crypto/wolfssl/cmac.h


+ 13 - 1
Pal/lib/pal_crypto.h

@@ -25,14 +25,18 @@
 #define PAL_CRYPTO_H
 
 /* These cryptosystems are still unconditionally provided by WolfSSL. */
-#include "crypto/cmac.h"
 #include "crypto/rsa.h"
 
 #define SHA256_DIGEST_LEN 32
 
+#define AES_CMAC_KEY_LEN    16
+#define AES_CMAC_DIGEST_LEN 32
+
 #ifdef CRYPTO_USE_WOLFSSL
 #define CRYPTO_PROVIDER_SPECIFIED
 
+#include "crypto/wolfssl/cmac.h"
+#include "crypto/wolfssl/aes.h"
 #include "crypto/wolfssl/sha256.h"
 #include "crypto/wolfssl/dh.h"
 typedef SHA256 LIB_SHA256_CONTEXT;
@@ -49,6 +53,10 @@ typedef struct {
 #ifdef CRYPTO_USE_MBEDTLS
 #define CRYPTO_PROVIDER_SPECIFIED
 
+#include "crypto/mbedtls/mbedtls/cmac.h"
+typedef struct AES LIB_AES_CONTEXT;
+
+#include "crypto/mbedtls/mbedtls/dhm.h"
 #include "crypto/mbedtls/mbedtls/sha256.h"
 typedef mbedtls_sha256_context LIB_SHA256_CONTEXT;
 
@@ -76,4 +84,8 @@ int lib_DhCalcSecret(LIB_DH_CONTEXT *context, uint8_t *peer, uint64_t peer_size,
                      uint8_t *secret, uint64_t *secret_size);
 void lib_DhFinal(LIB_DH_CONTEXT *context);
 
+/* AES-CMAC */
+int lib_AESCMAC(const uint8_t *key, uint64_t key_len, const uint8_t *input,
+                uint64_t input_len, uint8_t *mac, uint64_t mac_len);
+
 #endif

+ 2 - 2
Pal/lib/string/strlen.c

@@ -25,7 +25,7 @@
 
 /* Find the length of S, but scan at most MAXLEN characters.  If no
    '\0' terminator is found in that many characters, return MAXLEN.  */
-int strnlen (const char *str, int maxlen)
+size_t strnlen (const char *str, size_t maxlen)
 {
   const char *char_ptr, *end_ptr = str + maxlen;
   const unsigned long int *longword_ptr;
@@ -155,7 +155,7 @@ int strnlen (const char *str, int maxlen)
   return char_ptr - str;
 }
 
-int strlen (const char *str)
+size_t strlen (const char *str)
 {
   return strnlen(str, -1);
 }

+ 16 - 16
Pal/src/host/Linux-SGX/db_process.c

@@ -160,10 +160,10 @@ static int check_child_mrenclave (sgx_arch_hash_t * mrenclave,
     struct proc_attestation_data check_data;
     memset(&check_data, 0, sizeof(struct proc_attestation_data));
 
-    AES_CMAC((void *) &param->mac_key,
-             remote_state->enclave_keyhash,
-             sizeof(remote_state->enclave_keyhash),
-             check_data.keyhash_mac);
+    lib_AESCMAC((void *) &param->mac_key, AES_CMAC_KEY_LEN,
+                remote_state->enclave_keyhash,
+                sizeof(remote_state->enclave_keyhash),
+                check_data.keyhash_mac, sizeof check_data.keyhash_mac);
 
     if (memcmp(data, &check_data, sizeof(struct proc_attestation_data)))
         return 1;
@@ -231,10 +231,10 @@ int _DkProcessCreate (PAL_HANDLE * handle, const char * uri,
     struct proc_attestation_data data;
     memset(&data, 0, sizeof(struct proc_attestation_data));
 
-    AES_CMAC((void *) &param.mac_key,
-             pal_enclave_state.enclave_keyhash,
-             sizeof(pal_enclave_state.enclave_keyhash),
-             data.keyhash_mac);
+    lib_AESCMAC((void *) &param.mac_key, AES_CMAC_KEY_LEN,
+                pal_enclave_state.enclave_keyhash,
+                sizeof(pal_enclave_state.enclave_keyhash),
+                data.keyhash_mac, sizeof data.keyhash_mac);
 
     SGX_DBG(DBG_P|DBG_S, "Attestation data: %s\n", hex2str(data.keyhash_mac));
 
@@ -264,10 +264,10 @@ static int check_parent_mrenclave (sgx_arch_hash_t * mrenclave,
     struct proc_attestation_data check_data;
     memset(&check_data, 0, sizeof(struct proc_attestation_data));
 
-    AES_CMAC((void *) &param->mac_key,
-             remote_state->enclave_keyhash,
-             sizeof(remote_state->enclave_keyhash),
-             check_data.keyhash_mac);
+    lib_AESCMAC((void *) &param->mac_key, AES_CMAC_KEY_LEN,
+                remote_state->enclave_keyhash,
+                sizeof(remote_state->enclave_keyhash),
+                check_data.keyhash_mac, sizeof check_data.keyhash_mac);
 
     if (memcmp(data, &check_data, sizeof(struct proc_attestation_data)))
         return 1;
@@ -300,10 +300,10 @@ int init_child_process (PAL_HANDLE * parent_handle)
     struct proc_attestation_data data;
     memset(&data, 0, sizeof(struct proc_attestation_data));
 
-    AES_CMAC((void *) &param.mac_key,
-             pal_enclave_state.enclave_keyhash,
-             sizeof(pal_enclave_state.enclave_keyhash),
-             data.keyhash_mac);
+    lib_AESCMAC((void *) &param.mac_key, AES_CMAC_KEY_LEN,
+                pal_enclave_state.enclave_keyhash,
+                sizeof(pal_enclave_state.enclave_keyhash),
+                data.keyhash_mac, sizeof data.keyhash_mac);
 
     SGX_DBG(DBG_P|DBG_S, "Attestation data: %s\n", hex2str(data.keyhash_mac));
 

+ 7 - 4
Pal/src/host/Linux-SGX/enclave_framework.c

@@ -221,7 +221,8 @@ int load_trusted_file (PAL_HANDLE file, sgx_stub_t ** stubptr,
         if (ret < 0)
             goto unmap;
 
-        AES_CMAC((void *) &enclave_key, umem, mapping_size, (uint8_t *) s);
+        lib_AESCMAC((void *) &enclave_key, AES_CMAC_KEY_LEN, umem,
+                    mapping_size, (uint8_t *) s, sizeof *s);
 
         /* update the file checksum */
         ret = lib_SHA256Update(&sha, umem, mapping_size);
@@ -292,9 +293,11 @@ int verify_trusted_file (const char * uri, void * mem,
         if (checking_size > total_size - checking)
             checking_size = total_size - checking;
 
-        uint8_t hash[256/8]; // AES_CMAC hash size is 256 bits
-        AES_CMAC((void *) &enclave_key, mem + checking - offset,
-                 checking_size, hash);
+        uint8_t hash[AES_CMAC_DIGEST_LEN];
+        lib_AESCMAC((void *) &enclave_key,
+                    AES_CMAC_KEY_LEN,
+                    mem + checking - offset, checking_size,
+                    hash, sizeof(hash));
 
         if (memcmp(s, hash, sizeof(sgx_stub_t))) {
             SGX_DBG(DBG_E, "Accesing file:%s is denied. "

+ 1 - 1
Pal/src/security/Linux/internal.h

@@ -24,7 +24,7 @@
 #define ERRNO_P INTERNAL_SYSCALL_ERRNO_P
 
 int printf (const char * fmt, ...);
-void * malloc (int size);
+void * malloc (size_t size);
 void free (void * mem);
 
 #endif /* __INTERNAL_H__ */

+ 1 - 1
Pal/src/security/Linux/main.c

@@ -34,7 +34,7 @@ static char mem_pool[POOL_SIZE];
 static char *bump = mem_pool;
 static char *mem_pool_end = &mem_pool[POOL_SIZE];
 
-void * malloc (int size)
+void * malloc (size_t size)
 {
     void * addr = (void *) bump;