You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by st...@apache.org on 2016/09/28 00:44:01 UTC

[35/51] [abbrv] [partial] incubator-mynewt-core git commit: directory re-org, part 1

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/crypto/mbedtls/src/cmac.c
----------------------------------------------------------------------
diff --git a/crypto/mbedtls/src/cmac.c b/crypto/mbedtls/src/cmac.c
new file mode 100644
index 0000000..23b8044
--- /dev/null
+++ b/crypto/mbedtls/src/cmac.c
@@ -0,0 +1,529 @@
+/*
+ *  NIST SP800-38B compliant CMAC 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)
+ */
+
+/*
+ * Definition of CMAC:
+ * http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
+ * RFC 4493 "The AES-CMAC Algorithm"
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_CMAC_C)
+
+#include "mbedtls/cmac.h"
+
+#include <string.h>
+
+#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#define mbedtls_printf printf
+#endif /* MBEDTLS_PLATFORM_C */
+#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
+
+/* Implementation that should never be optimized out by the compiler */
+static void mbedtls_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * Initialize context
+ */
+void mbedtls_cmac_init( mbedtls_cmac_context *ctx )
+{
+    memset( ctx, 0, sizeof( mbedtls_cmac_context ) );
+}
+
+/*
+ * Multiply by u in GF(2^128)
+ *
+ * As explained in the paper, this can be achieved as
+ * If MSB(p) = 0, then p = (p << 1)
+ * If MSB(p) = 1, then p = (p << 1) ^ Rb
+ * with Rb = 0x87
+ *
+ * Input and output MUST not point to the same buffer
+ */
+static void cmac_multiply_by_u( unsigned char *output,
+                                const unsigned char *input )
+{
+    const unsigned char Rb = 0x87; /* block size 16 only */
+    unsigned char mask;
+    unsigned char overflow = 0;
+    int i;
+
+    for( i = 15; 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[15] ^= Rb & mask;
+}
+
+/*
+ * Generate subkeys
+ */
+static int cmac_generate_subkeys( mbedtls_cmac_context *ctx )
+{
+    int ret;
+    unsigned char L[16];
+    size_t olen;
+
+    /* Calculate Ek(0) */
+    memset( L, 0, 16 );
+    if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx,
+                                       L, 16, L, &olen ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    /*
+     * Generate K1 and K2
+     */
+    cmac_multiply_by_u( ctx->K1, L );
+    cmac_multiply_by_u( ctx->K2, ctx->K1 );
+
+    mbedtls_zeroize( L, sizeof( L ) );
+
+    return( 0 );
+}
+
+/*
+ * Set key and prepare context for use
+ */
+int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx,
+                         mbedtls_cipher_id_t cipher,
+                         const unsigned char *key,
+                         unsigned int keybits )
+{
+    int ret;
+    const mbedtls_cipher_info_t *cipher_info;
+
+    cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
+                                                   MBEDTLS_MODE_ECB );
+    if( cipher_info == NULL )
+        return( MBEDTLS_ERR_CMAC_BAD_INPUT );
+
+    if( cipher_info->block_size != 16 )
+        return( MBEDTLS_ERR_CMAC_BAD_INPUT );
+
+    mbedtls_cipher_free( &ctx->cipher_ctx );
+
+    if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
+        return( ret );
+
+    if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
+                                       MBEDTLS_ENCRYPT ) ) != 0 )
+    {
+        return( ret );
+    }
+
+    return( cmac_generate_subkeys( ctx ) );
+}
+
+/*
+ * Free context
+ */
+void mbedtls_cmac_free( mbedtls_cmac_context *ctx )
+{
+    mbedtls_cipher_free( &ctx->cipher_ctx );
+    mbedtls_zeroize( ctx, sizeof( mbedtls_cmac_context ) );
+}
+
+/*
+ * 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[16],
+                      const unsigned char *last_block,
+                      size_t length )
+{
+    size_t j;
+
+    for( j = 0; j < 16; j++ )
+    {
+        if( j < length )
+            padded_block[j] = last_block[j];
+        else if( j == length )
+            padded_block[j] = 0x80;
+        else
+            padded_block[j] = 0x00;
+    }
+}
+
+/*
+ * XOR 128-bit
+ * Here, macro results in smaller compiled code than static inline function
+ */
+#define XOR_128( o, i1, i2 )                                                \
+    for( i = 0; i < 16; i++ )                                               \
+        ( o )[i] = ( i1 )[i] ^ ( i2 )[i];
+
+/*
+ * Update the CMAC state using an input block x
+ */
+#define UPDATE_CMAC( x )                                                    \
+do {                                                                        \
+    XOR_128( state, ( x ), state );                                         \
+    if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx,                    \
+                                       state, 16, state, &olen ) ) != 0 )   \
+        return( ret );                                                      \
+} while( 0 )
+
+/*
+ * Generate tag on complete message
+ */
+int mbedtls_cmac_generate( mbedtls_cmac_context *ctx,
+                           const unsigned char *input, size_t in_len,
+                           unsigned char *tag, size_t tag_len )
+
+{
+    unsigned char state[16];
+    unsigned char M_last[16];
+    int     n, i, j, ret, needs_padding;
+    size_t olen;
+
+    /*
+     * Check in_len requirements: SP800-38B A
+     * 4 is a worst case bottom limit
+     */
+    if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
+        return( MBEDTLS_ERR_CMAC_BAD_INPUT );
+
+    if( in_len == 0 )
+        needs_padding = 1;
+    else
+        needs_padding = in_len % 16 != 0;
+
+    n = in_len / 16 + needs_padding;
+
+    /* Calculate last block */
+    if( needs_padding )
+    {
+        cmac_pad( M_last, input + 16 * ( n - 1 ), in_len % 16 );
+        XOR_128( M_last, M_last, ctx->K2 );
+    }
+    else
+    {
+        /* Last block is complete block */
+        XOR_128( M_last, input + 16 * ( n - 1 ), ctx->K1 );
+    }
+
+    memset( state, 0, 16 );
+
+    for( j = 0; j < n - 1; j++ )
+        UPDATE_CMAC( input + 16 * j );
+
+    UPDATE_CMAC( M_last );
+
+    memcpy( tag, state, 16 );
+
+    return( 0 );
+}
+
+#undef XOR_128
+#undef UPDATE_CMAC
+
+/*
+ * Verify tag on complete message
+ */
+int mbedtls_cmac_verify( mbedtls_cmac_context *ctx,
+                         const unsigned char *input, size_t in_len,
+                         const unsigned char *tag, size_t tag_len )
+{
+    int ret;
+    unsigned char check_tag[16];
+    unsigned char i;
+    int diff;
+
+    if( ( ret = mbedtls_cmac_generate( ctx, input, in_len,
+                                       check_tag, tag_len ) ) != 0 )
+    {
+        return ret;
+    }
+
+    /* Check tag in "constant-time" */
+    for( diff = 0, i = 0; i < tag_len; i++ )
+        diff |= tag[i] ^ check_tag[i];
+
+    if( diff != 0 )
+        return( MBEDTLS_ERR_CMAC_VERIFY_FAILED );
+
+    return( 0 );
+}
+
+/*
+ * PRF based on CMAC with AES-128
+ * TODO: add reference to the standard
+ * TODO: do we need to take a cmac_context as an argument here?
+ */
+int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx,
+                              const unsigned char *key, size_t key_length,
+                              const unsigned char *input, size_t in_len,
+                              unsigned char *tag )
+{
+    int ret;
+    unsigned char zero_key[16];
+    unsigned char int_key[16];
+
+    if( key_length == 16 )
+    {
+        /* Use key as is */
+        memcpy( int_key, key, 16 );
+    }
+    else
+    {
+        mbedtls_cmac_context zero_ctx;
+
+        /* Key is AES_CMAC(0, key) */
+        mbedtls_cmac_init( &zero_ctx );
+        memset( zero_key, 0, 16 );
+        ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES,
+                                   zero_key, 8 * sizeof zero_key );
+        if( ret != 0 )
+            return( ret );
+
+        ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 );
+        if( ret != 0 )
+            return( ret );
+    }
+
+    ret = mbedtls_cmac_setkey( ctx, MBEDTLS_CIPHER_ID_AES,
+                               int_key, 8 * sizeof int_key );
+    if( ret != 0 )
+        return( ret );
+
+    mbedtls_zeroize( int_key, sizeof( int_key ) );
+
+    return( mbedtls_cmac_generate( ctx, input, in_len, tag, 16 ) );
+}
+
+#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
+/*
+ * Examples 1 to 4 from SP800-38B corrected Appendix D.1
+ * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
+ */
+
+#define NB_CMAC_TESTS 4
+#define NB_PRF_TESTS 3
+
+/* Key */
+static const unsigned char key[] = {
+    0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+    0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+};
+
+/* Assume we don't need to test Ek0 as this is a function of the cipher */
+
+/* Subkey K1 */
+static const unsigned char K1[] = {
+    0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
+    0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
+};
+
+/* Subkey K2 */
+static const unsigned char K2[] = {
+    0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
+    0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
+};
+
+/* All Messages */
+static const unsigned char M[] = {
+    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 T[NB_CMAC_TESTS][16] = {
+    {
+        0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
+        0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
+    },
+    {
+        0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
+        0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
+    },
+    {
+        0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
+        0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
+    },
+    {
+        0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
+        0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
+    }
+};
+
+/* Sizes in bytes */
+static const size_t Mlen[NB_CMAC_TESTS] = {
+    0,
+    16,
+    40,
+    64
+};
+
+/* PRF K */
+static const unsigned char PRFK[] = {
+    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
+};
+
+/* PRF M */
+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
+    }
+};
+
+
+int mbedtls_cmac_self_test( int verbose )
+{
+    mbedtls_cmac_context ctx;
+    unsigned char tag[16];
+    int i;
+    int ret;
+
+    mbedtls_cmac_init( &ctx );
+
+    if( mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "  CMAC: setup failed\n" );
+
+        return( 1 );
+    }
+
+    if( ( memcmp( ctx.K1, K1, 16 ) != 0 ) ||
+        ( memcmp( ctx.K2, K2, 16 ) != 0 ) )
+    {
+        if( verbose != 0 )
+            mbedtls_printf( "  CMAC: subkey generation failed\n" );
+
+        return( 1 );
+    }
+
+    for( i = 0; i < NB_CMAC_TESTS; i++ )
+    {
+        mbedtls_printf( "  AES-128-CMAC #%u: ", i );
+
+        ret = mbedtls_cmac_generate( &ctx, M, Mlen[i], tag, 16 );
+        if( ret != 0 ||
+            memcmp( tag, T[i], 16 ) != 0 )
+        {
+            if( verbose != 0 )
+                mbedtls_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        ret = mbedtls_cmac_verify( &ctx, M, Mlen[i], T[i], 16 );
+        if( ret != 0 )
+        {
+            if( verbose != 0 )
+                mbedtls_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+
+    for( i = 0; i < NB_PRF_TESTS; i++ )
+    {
+        mbedtls_printf( "  AES-CMAC-128-PRF #%u: ", i );
+
+        mbedtls_aes_cmac_prf_128( &ctx, PRFK, PRFKlen[i], PRFM, 20, tag );
+
+        if( ret != 0 ||
+            memcmp( tag, PRFT[i], 16 ) != 0 )
+        {
+            if( verbose != 0 )
+                mbedtls_printf( "failed\n" );
+
+            return( 1 );
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+
+    mbedtls_cmac_free( &ctx );
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+
+    return( 0 );
+}
+
+#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
+
+#endif /* MBEDTLS_CMAC_C */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/crypto/mbedtls/src/ctr_drbg.c
----------------------------------------------------------------------
diff --git a/crypto/mbedtls/src/ctr_drbg.c b/crypto/mbedtls/src/ctr_drbg.c
new file mode 100644
index 0000000..aefddfa
--- /dev/null
+++ b/crypto/mbedtls/src/ctr_drbg.c
@@ -0,0 +1,593 @@
+/*
+ *  CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
+ *
+ *  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 NIST SP 800-90 DRBGs are described in the following publucation.
+ *
+ *  http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_CTR_DRBG_C)
+
+#include "mbedtls/ctr_drbg.h"
+
+#include <string.h>
+
+#if defined(MBEDTLS_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(MBEDTLS_SELF_TEST)
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#define mbedtls_printf printf
+#endif /* MBEDTLS_PLATFORM_C */
+#endif /* MBEDTLS_SELF_TEST */
+
+/* Implementation that should never be optimized out by the compiler */
+static void mbedtls_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * CTR_DRBG context initialization
+ */
+void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
+{
+    memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_init( &ctx->mutex );
+#endif
+}
+
+/*
+ * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
+ * tests to succeed (which require known length fixed entropy)
+ */
+int mbedtls_ctr_drbg_seed_entropy_len(
+                   mbedtls_ctr_drbg_context *ctx,
+                   int (*f_entropy)(void *, unsigned char *, size_t),
+                   void *p_entropy,
+                   const unsigned char *custom,
+                   size_t len,
+                   size_t entropy_len )
+{
+    int ret;
+    unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
+
+    memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
+
+    mbedtls_aes_init( &ctx->aes_ctx );
+
+    ctx->f_entropy = f_entropy;
+    ctx->p_entropy = p_entropy;
+
+    ctx->entropy_len = entropy_len;
+    ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
+
+    /*
+     * Initialize with an empty key
+     */
+    mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS );
+
+    if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
+                   int (*f_entropy)(void *, unsigned char *, size_t),
+                   void *p_entropy,
+                   const unsigned char *custom,
+                   size_t len )
+{
+    return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len,
+                                       MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
+}
+
+void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_free( &ctx->mutex );
+#endif
+    mbedtls_aes_free( &ctx->aes_ctx );
+    mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
+}
+
+void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
+{
+    ctx->prediction_resistance = resistance;
+}
+
+void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
+{
+    ctx->entropy_len = len;
+}
+
+void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
+{
+    ctx->reseed_interval = interval;
+}
+
+static int block_cipher_df( unsigned char *output,
+                            const unsigned char *data, size_t data_len )
+{
+    unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
+    unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
+    unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
+    unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
+    unsigned char *p, *iv;
+    mbedtls_aes_context aes_ctx;
+
+    int i, j;
+    size_t buf_len, use_len;
+
+    if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
+        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+
+    memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
+    mbedtls_aes_init( &aes_ctx );
+
+    /*
+     * Construct IV (16 bytes) and S in buffer
+     * IV = Counter (in 32-bits) padded to 16 with zeroes
+     * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
+     *     data || 0x80
+     *     (Total is padded to a multiple of 16-bytes with zeroes)
+     */
+    p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
+    *p++ = ( data_len >> 24 ) & 0xff;
+    *p++ = ( data_len >> 16 ) & 0xff;
+    *p++ = ( data_len >> 8  ) & 0xff;
+    *p++ = ( data_len       ) & 0xff;
+    p += 3;
+    *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
+    memcpy( p, data, data_len );
+    p[data_len] = 0x80;
+
+    buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
+
+    for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
+        key[i] = i;
+
+    mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS );
+
+    /*
+     * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
+     */
+    for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
+    {
+        p = buf;
+        memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
+        use_len = buf_len;
+
+        while( use_len > 0 )
+        {
+            for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
+                chain[i] ^= p[i];
+            p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
+            use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
+                       MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
+
+            mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain );
+        }
+
+        memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
+
+        /*
+         * Update IV
+         */
+        buf[3]++;
+    }
+
+    /*
+     * Do final encryption with reduced data
+     */
+    mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS );
+    iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
+    p = output;
+
+    for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
+    {
+        mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+        memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
+        p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
+    }
+
+    mbedtls_aes_free( &aes_ctx );
+
+    return( 0 );
+}
+
+static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
+                              const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
+{
+    unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
+    unsigned char *p = tmp;
+    int i, j;
+
+    memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
+
+    for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
+    {
+        /*
+         * Increase counter
+         */
+        for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
+            if( ++ctx->counter[i - 1] != 0 )
+                break;
+
+        /*
+         * Crypt counter block
+         */
+        mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p );
+
+        p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
+    }
+
+    for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
+        tmp[i] ^= data[i];
+
+    /*
+     * Update key and counter
+     */
+    mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS );
+    memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
+
+    return( 0 );
+}
+
+void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
+                      const unsigned char *additional, size_t add_len )
+{
+    unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
+
+    if( add_len > 0 )
+    {
+        /* MAX_INPUT would be more logical here, but we have to match
+         * block_cipher_df()'s limits since we can't propagate errors */
+        if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
+            add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
+
+        block_cipher_df( add_input, additional, add_len );
+        ctr_drbg_update_internal( ctx, add_input );
+    }
+}
+
+int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
+                     const unsigned char *additional, size_t len )
+{
+    unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
+    size_t seedlen = 0;
+
+    if( ctx->entropy_len + len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
+        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+
+    memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
+
+    /*
+     * Gather entropy_len bytes of entropy to seed state
+     */
+    if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
+                             ctx->entropy_len ) )
+    {
+        return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
+    }
+
+    seedlen += ctx->entropy_len;
+
+    /*
+     * Add additional data
+     */
+    if( additional && len )
+    {
+        memcpy( seed + seedlen, additional, len );
+        seedlen += len;
+    }
+
+    /*
+     * Reduce to 384 bits
+     */
+    block_cipher_df( seed, seed, seedlen );
+
+    /*
+     * Update state
+     */
+    ctr_drbg_update_internal( ctx, seed );
+    ctx->reseed_counter = 1;
+
+    return( 0 );
+}
+
+int mbedtls_ctr_drbg_random_with_add( void *p_rng,
+                              unsigned char *output, size_t output_len,
+                              const unsigned char *additional, size_t add_len )
+{
+    int ret = 0;
+    mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
+    unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
+    unsigned char *p = output;
+    unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
+    int i;
+    size_t use_len;
+
+    if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
+        return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
+
+    if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
+        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+
+    memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
+
+    if( ctx->reseed_counter > ctx->reseed_interval ||
+        ctx->prediction_resistance )
+    {
+        if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
+            return( ret );
+
+        add_len = 0;
+    }
+
+    if( add_len > 0 )
+    {
+        block_cipher_df( add_input, additional, add_len );
+        ctr_drbg_update_internal( ctx, add_input );
+    }
+
+    while( output_len > 0 )
+    {
+        /*
+         * Increase counter
+         */
+        for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
+            if( ++ctx->counter[i - 1] != 0 )
+                break;
+
+        /*
+         * Crypt counter block
+         */
+        mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp );
+
+        use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
+                                                       output_len;
+        /*
+         * Copy random block to destination
+         */
+        memcpy( p, tmp, use_len );
+        p += use_len;
+        output_len -= use_len;
+    }
+
+    ctr_drbg_update_internal( ctx, add_input );
+
+    ctx->reseed_counter++;
+
+    return( 0 );
+}
+
+int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
+{
+    int ret;
+    mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
+
+#if defined(MBEDTLS_THREADING_C)
+    if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
+        return( ret );
+#endif
+
+    ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
+
+#if defined(MBEDTLS_THREADING_C)
+    if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
+        return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+    return( ret );
+}
+
+#if defined(MBEDTLS_FS_IO)
+int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
+{
+    int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
+    FILE *f;
+    unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
+
+    if( ( f = fopen( path, "wb" ) ) == NULL )
+        return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
+
+    if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
+        goto exit;
+
+    if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
+    {
+        ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
+        goto exit;
+    }
+
+    ret = 0;
+
+exit:
+    fclose( f );
+    return( ret );
+}
+
+int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
+{
+    FILE *f;
+    size_t n;
+    unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
+
+    fseek( f, 0, SEEK_END );
+    n = (size_t) ftell( f );
+    fseek( f, 0, SEEK_SET );
+
+    if( n > MBEDTLS_CTR_DRBG_MAX_INPUT )
+    {
+        fclose( f );
+        return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+    }
+
+    if( fread( buf, 1, n, f ) != n )
+    {
+        fclose( f );
+        return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
+    }
+
+    fclose( f );
+
+    mbedtls_ctr_drbg_update( ctx, buf, n );
+
+    return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
+}
+#endif /* MBEDTLS_FS_IO */
+
+#if defined(MBEDTLS_SELF_TEST)
+
+static const unsigned char entropy_source_pr[96] =
+    { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
+      0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
+      0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
+      0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
+      0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
+      0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
+      0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
+      0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
+      0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
+      0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
+      0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
+      0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
+
+static const unsigned char entropy_source_nopr[64] =
+    { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
+      0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
+      0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
+      0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
+      0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
+      0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
+      0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
+      0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
+
+static const unsigned char nonce_pers_pr[16] =
+    { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
+      0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
+
+static const unsigned char nonce_pers_nopr[16] =
+    { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
+      0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
+
+static const unsigned char result_pr[16] =
+    { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
+      0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
+
+static const unsigned char result_nopr[16] =
+    { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
+      0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
+
+static size_t test_offset;
+static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
+                                       size_t len )
+{
+    const unsigned char *p = data;
+    memcpy( buf, p + test_offset, len );
+    test_offset += len;
+    return( 0 );
+}
+
+#define CHK( c )    if( (c) != 0 )                          \
+                    {                                       \
+                        if( verbose != 0 )                  \
+                            mbedtls_printf( "failed\n" );  \
+                        return( 1 );                        \
+                    }
+
+/*
+ * Checkup routine
+ */
+int mbedtls_ctr_drbg_self_test( int verbose )
+{
+    mbedtls_ctr_drbg_context ctx;
+    unsigned char buf[16];
+
+    mbedtls_ctr_drbg_init( &ctx );
+
+    /*
+     * Based on a NIST CTR_DRBG test vector (PR = True)
+     */
+    if( verbose != 0 )
+        mbedtls_printf( "  CTR_DRBG (PR = TRUE) : " );
+
+    test_offset = 0;
+    CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
+                                (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
+    mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
+    CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
+    CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
+    CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
+
+    mbedtls_ctr_drbg_free( &ctx );
+
+    if( verbose != 0 )
+        mbedtls_printf( "passed\n" );
+
+    /*
+     * Based on a NIST CTR_DRBG test vector (PR = FALSE)
+     */
+    if( verbose != 0 )
+        mbedtls_printf( "  CTR_DRBG (PR = FALSE): " );
+
+    mbedtls_ctr_drbg_init( &ctx );
+
+    test_offset = 0;
+    CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
+                            (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
+    CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
+    CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
+    CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
+    CHK( memcmp( buf, result_nopr, 16 ) );
+
+    mbedtls_ctr_drbg_free( &ctx );
+
+    if( verbose != 0 )
+        mbedtls_printf( "passed\n" );
+
+    if( verbose != 0 )
+            mbedtls_printf( "\n" );
+
+    return( 0 );
+}
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_CTR_DRBG_C */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/crypto/mbedtls/src/debug.c
----------------------------------------------------------------------
diff --git a/crypto/mbedtls/src/debug.c b/crypto/mbedtls/src/debug.c
new file mode 100644
index 0000000..4752ab1
--- /dev/null
+++ b/crypto/mbedtls/src/debug.c
@@ -0,0 +1,367 @@
+/*
+ *  Debugging routines
+ *
+ *  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_DEBUG_C)
+
+#include "mbedtls/debug.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdlib.h>
+#define mbedtls_calloc      calloc
+#define mbedtls_free        free
+#define mbedtls_snprintf    snprintf
+#endif
+
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
+#define DEBUG_BUF_SIZE      512
+
+static int debug_threshold = 0;
+
+void mbedtls_debug_set_threshold( int threshold )
+{
+    debug_threshold = threshold;
+}
+
+/*
+ * All calls to f_dbg must be made via this function
+ */
+static inline void debug_send_line( const mbedtls_ssl_context *ssl, int level,
+                                    const char *file, int line,
+                                    const char *str )
+{
+    /*
+     * If in a threaded environment, we need a thread identifier.
+     * Since there is no portable way to get one, use the address of the ssl
+     * context instead, as it shouldn't be shared between threads.
+     */
+#if defined(MBEDTLS_THREADING_C)
+    char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */
+    mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", ssl, str );
+    ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, idstr );
+#else
+    ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str );
+#endif
+}
+
+void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level,
+                              const char *file, int line,
+                              const char *format, ... )
+{
+    va_list argp;
+    char str[DEBUG_BUF_SIZE];
+    int ret;
+
+    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
+        return;
+
+    va_start( argp, format );
+#if defined(_WIN32)
+#if defined(_TRUNCATE)
+    ret = _vsnprintf_s( str, DEBUG_BUF_SIZE, _TRUNCATE, format, argp );
+#else
+    ret = _vsnprintf( str, DEBUG_BUF_SIZE, format, argp );
+    if( ret < 0 || (size_t) ret == DEBUG_BUF_SIZE )
+    {
+        str[DEBUG_BUF_SIZE-1] = '\0';
+        ret = -1;
+    }
+#endif
+#else
+    ret = vsnprintf( str, DEBUG_BUF_SIZE, format, argp );
+#endif
+    va_end( argp );
+
+    if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 )
+    {
+        str[ret]     = '\n';
+        str[ret + 1] = '\0';
+    }
+
+    debug_send_line( ssl, level, file, line, str );
+}
+
+void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, int ret )
+{
+    char str[DEBUG_BUF_SIZE];
+
+    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
+        return;
+
+    /*
+     * With non-blocking I/O and examples that just retry immediately,
+     * the logs would be quickly flooded with WANT_READ, so ignore that.
+     * Don't ignore WANT_WRITE however, since is is usually rare.
+     */
+    if( ret == MBEDTLS_ERR_SSL_WANT_READ )
+        return;
+
+    mbedtls_snprintf( str, sizeof( str ), "%s() returned %d (-0x%04x)\n",
+              text, ret, -ret );
+
+    debug_send_line( ssl, level, file, line, str );
+}
+
+void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level,
+                      const char *file, int line, const char *text,
+                      const unsigned char *buf, size_t len )
+{
+    char str[DEBUG_BUF_SIZE];
+    char txt[17];
+    size_t i, idx = 0;
+
+    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
+        return;
+
+    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "dumping '%s' (%u bytes)\n",
+              text, (unsigned int) len );
+
+    debug_send_line( ssl, level, file, line, str );
+
+    idx = 0;
+    memset( txt, 0, sizeof( txt ) );
+    for( i = 0; i < len; i++ )
+    {
+        if( i >= 4096 )
+            break;
+
+        if( i % 16 == 0 )
+        {
+            if( i > 0 )
+            {
+                mbedtls_snprintf( str + idx, sizeof( str ) - idx, "  %s\n", txt );
+                debug_send_line( ssl, level, file, line, str );
+
+                idx = 0;
+                memset( txt, 0, sizeof( txt ) );
+            }
+
+            idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "%04x: ",
+                             (unsigned int) i );
+
+        }
+
+        idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x",
+                         (unsigned int) buf[i] );
+        txt[i % 16] = ( buf[i] > 31 && buf[i] < 127 ) ? buf[i] : '.' ;
+    }
+
+    if( len > 0 )
+    {
+        for( /* i = i */; i % 16 != 0; i++ )
+            idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "   " );
+
+        mbedtls_snprintf( str + idx, sizeof( str ) - idx, "  %s\n", txt );
+        debug_send_line( ssl, level, file, line, str );
+    }
+}
+
+#if defined(MBEDTLS_ECP_C)
+void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, const mbedtls_ecp_point *X )
+{
+    char str[DEBUG_BUF_SIZE];
+
+    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold )
+        return;
+
+    mbedtls_snprintf( str, sizeof( str ), "%s(X)", text );
+    mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->X );
+
+    mbedtls_snprintf( str, sizeof( str ), "%s(Y)", text );
+    mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->Y );
+}
+#endif /* MBEDTLS_ECP_C */
+
+#if defined(MBEDTLS_BIGNUM_C)
+void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, const mbedtls_mpi *X )
+{
+    char str[DEBUG_BUF_SIZE];
+    int j, k, zeros = 1;
+    size_t i, n, idx = 0;
+
+    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || X == NULL || level > debug_threshold )
+        return;
+
+    for( n = X->n - 1; n > 0; n-- )
+        if( X->p[n] != 0 )
+            break;
+
+    for( j = ( sizeof(mbedtls_mpi_uint) << 3 ) - 1; j >= 0; j-- )
+        if( ( ( X->p[n] >> j ) & 1 ) != 0 )
+            break;
+
+    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "value of '%s' (%d bits) is:\n",
+              text, (int) ( ( n * ( sizeof(mbedtls_mpi_uint) << 3 ) ) + j + 1 ) );
+
+    debug_send_line( ssl, level, file, line, str );
+
+    idx = 0;
+    for( i = n + 1, j = 0; i > 0; i-- )
+    {
+        if( zeros && X->p[i - 1] == 0 )
+            continue;
+
+        for( k = sizeof( mbedtls_mpi_uint ) - 1; k >= 0; k-- )
+        {
+            if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 )
+                continue;
+            else
+                zeros = 0;
+
+            if( j % 16 == 0 )
+            {
+                if( j > 0 )
+                {
+                    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
+                    debug_send_line( ssl, level, file, line, str );
+                    idx = 0;
+                }
+            }
+
+            idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", (unsigned int)
+                             ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF );
+
+            j++;
+        }
+
+    }
+
+    if( zeros == 1 )
+        idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " 00" );
+
+    mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" );
+    debug_send_line( ssl, level, file, line, str );
+}
+#endif /* MBEDTLS_BIGNUM_C */
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+static void debug_print_pk( const mbedtls_ssl_context *ssl, int level,
+                            const char *file, int line,
+                            const char *text, const mbedtls_pk_context *pk )
+{
+    size_t i;
+    mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS];
+    char name[16];
+
+    memset( items, 0, sizeof( items ) );
+
+    if( mbedtls_pk_debug( pk, items ) != 0 )
+    {
+        debug_send_line( ssl, level, file, line,
+                          "invalid PK context\n" );
+        return;
+    }
+
+    for( i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++ )
+    {
+        if( items[i].type == MBEDTLS_PK_DEBUG_NONE )
+            return;
+
+        mbedtls_snprintf( name, sizeof( name ), "%s%s", text, items[i].name );
+        name[sizeof( name ) - 1] = '\0';
+
+        if( items[i].type == MBEDTLS_PK_DEBUG_MPI )
+            mbedtls_debug_print_mpi( ssl, level, file, line, name, items[i].value );
+        else
+#if defined(MBEDTLS_ECP_C)
+        if( items[i].type == MBEDTLS_PK_DEBUG_ECP )
+            mbedtls_debug_print_ecp( ssl, level, file, line, name, items[i].value );
+        else
+#endif
+            debug_send_line( ssl, level, file, line,
+                              "should not happen\n" );
+    }
+}
+
+static void debug_print_line_by_line( const mbedtls_ssl_context *ssl, int level,
+                                      const char *file, int line, const char *text )
+{
+    char str[DEBUG_BUF_SIZE];
+    const char *start, *cur;
+
+    start = text;
+    for( cur = text; *cur != '\0'; cur++ )
+    {
+        if( *cur == '\n' )
+        {
+            size_t len = cur - start + 1;
+            if( len > DEBUG_BUF_SIZE - 1 )
+                len = DEBUG_BUF_SIZE - 1;
+
+            memcpy( str, start, len );
+            str[len] = '\0';
+
+            debug_send_line( ssl, level, file, line, str );
+
+            start = cur + 1;
+        }
+    }
+}
+
+void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level,
+                      const char *file, int line,
+                      const char *text, const mbedtls_x509_crt *crt )
+{
+    char str[DEBUG_BUF_SIZE];
+    int i = 0;
+
+    if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || crt == NULL || level > debug_threshold )
+        return;
+
+    while( crt != NULL )
+    {
+        char buf[1024];
+
+        mbedtls_snprintf( str, sizeof( str ), "%s #%d:\n", text, ++i );
+        debug_send_line( ssl, level, file, line, str );
+
+        mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt );
+        debug_print_line_by_line( ssl, level, file, line, buf );
+
+        debug_print_pk( ssl, level, file, line, "crt->", &crt->pk );
+
+        crt = crt->next;
+    }
+}
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+#endif /* MBEDTLS_DEBUG_C */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/crypto/mbedtls/src/des.c
----------------------------------------------------------------------
diff --git a/crypto/mbedtls/src/des.c b/crypto/mbedtls/src/des.c
new file mode 100644
index 0000000..61f214a
--- /dev/null
+++ b/crypto/mbedtls/src/des.c
@@ -0,0 +1,1061 @@
+/*
+ *  FIPS-46-3 compliant Triple-DES 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)
+ */
+/*
+ *  DES, on which TDES is based, was originally designed by Horst Feistel
+ *  at IBM in 1974, and was adopted as a standard by NIST (formerly NBS).
+ *
+ *  http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_DES_C)
+
+#include "mbedtls/des.h"
+
+#include <string.h>
+
+#if defined(MBEDTLS_SELF_TEST)
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#define mbedtls_printf printf
+#endif /* MBEDTLS_PLATFORM_C */
+#endif /* MBEDTLS_SELF_TEST */
+
+#if !defined(MBEDTLS_DES_ALT)
+
+/* Implementation that should never be optimized out by the compiler */
+static void mbedtls_zeroize( void *v, size_t n ) {
+    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
+        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 3]       );            \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+/*
+ * Expanded DES S-boxes
+ */
+static const uint32_t SB1[64] =
+{
+    0x01010400, 0x00000000, 0x00010000, 0x01010404,
+    0x01010004, 0x00010404, 0x00000004, 0x00010000,
+    0x00000400, 0x01010400, 0x01010404, 0x00000400,
+    0x01000404, 0x01010004, 0x01000000, 0x00000004,
+    0x00000404, 0x01000400, 0x01000400, 0x00010400,
+    0x00010400, 0x01010000, 0x01010000, 0x01000404,
+    0x00010004, 0x01000004, 0x01000004, 0x00010004,
+    0x00000000, 0x00000404, 0x00010404, 0x01000000,
+    0x00010000, 0x01010404, 0x00000004, 0x01010000,
+    0x01010400, 0x01000000, 0x01000000, 0x00000400,
+    0x01010004, 0x00010000, 0x00010400, 0x01000004,
+    0x00000400, 0x00000004, 0x01000404, 0x00010404,
+    0x01010404, 0x00010004, 0x01010000, 0x01000404,
+    0x01000004, 0x00000404, 0x00010404, 0x01010400,
+    0x00000404, 0x01000400, 0x01000400, 0x00000000,
+    0x00010004, 0x00010400, 0x00000000, 0x01010004
+};
+
+static const uint32_t SB2[64] =
+{
+    0x80108020, 0x80008000, 0x00008000, 0x00108020,
+    0x00100000, 0x00000020, 0x80100020, 0x80008020,
+    0x80000020, 0x80108020, 0x80108000, 0x80000000,
+    0x80008000, 0x00100000, 0x00000020, 0x80100020,
+    0x00108000, 0x00100020, 0x80008020, 0x00000000,
+    0x80000000, 0x00008000, 0x00108020, 0x80100000,
+    0x00100020, 0x80000020, 0x00000000, 0x00108000,
+    0x00008020, 0x80108000, 0x80100000, 0x00008020,
+    0x00000000, 0x00108020, 0x80100020, 0x00100000,
+    0x80008020, 0x80100000, 0x80108000, 0x00008000,
+    0x80100000, 0x80008000, 0x00000020, 0x80108020,
+    0x00108020, 0x00000020, 0x00008000, 0x80000000,
+    0x00008020, 0x80108000, 0x00100000, 0x80000020,
+    0x00100020, 0x80008020, 0x80000020, 0x00100020,
+    0x00108000, 0x00000000, 0x80008000, 0x00008020,
+    0x80000000, 0x80100020, 0x80108020, 0x00108000
+};
+
+static const uint32_t SB3[64] =
+{
+    0x00000208, 0x08020200, 0x00000000, 0x08020008,
+    0x08000200, 0x00000000, 0x00020208, 0x08000200,
+    0x00020008, 0x08000008, 0x08000008, 0x00020000,
+    0x08020208, 0x00020008, 0x08020000, 0x00000208,
+    0x08000000, 0x00000008, 0x08020200, 0x00000200,
+    0x00020200, 0x08020000, 0x08020008, 0x00020208,
+    0x08000208, 0x00020200, 0x00020000, 0x08000208,
+    0x00000008, 0x08020208, 0x00000200, 0x08000000,
+    0x08020200, 0x08000000, 0x00020008, 0x00000208,
+    0x00020000, 0x08020200, 0x08000200, 0x00000000,
+    0x00000200, 0x00020008, 0x08020208, 0x08000200,
+    0x08000008, 0x00000200, 0x00000000, 0x08020008,
+    0x08000208, 0x00020000, 0x08000000, 0x08020208,
+    0x00000008, 0x00020208, 0x00020200, 0x08000008,
+    0x08020000, 0x08000208, 0x00000208, 0x08020000,
+    0x00020208, 0x00000008, 0x08020008, 0x00020200
+};
+
+static const uint32_t SB4[64] =
+{
+    0x00802001, 0x00002081, 0x00002081, 0x00000080,
+    0x00802080, 0x00800081, 0x00800001, 0x00002001,
+    0x00000000, 0x00802000, 0x00802000, 0x00802081,
+    0x00000081, 0x00000000, 0x00800080, 0x00800001,
+    0x00000001, 0x00002000, 0x00800000, 0x00802001,
+    0x00000080, 0x00800000, 0x00002001, 0x00002080,
+    0x00800081, 0x00000001, 0x00002080, 0x00800080,
+    0x00002000, 0x00802080, 0x00802081, 0x00000081,
+    0x00800080, 0x00800001, 0x00802000, 0x00802081,
+    0x00000081, 0x00000000, 0x00000000, 0x00802000,
+    0x00002080, 0x00800080, 0x00800081, 0x00000001,
+    0x00802001, 0x00002081, 0x00002081, 0x00000080,
+    0x00802081, 0x00000081, 0x00000001, 0x00002000,
+    0x00800001, 0x00002001, 0x00802080, 0x00800081,
+    0x00002001, 0x00002080, 0x00800000, 0x00802001,
+    0x00000080, 0x00800000, 0x00002000, 0x00802080
+};
+
+static const uint32_t SB5[64] =
+{
+    0x00000100, 0x02080100, 0x02080000, 0x42000100,
+    0x00080000, 0x00000100, 0x40000000, 0x02080000,
+    0x40080100, 0x00080000, 0x02000100, 0x40080100,
+    0x42000100, 0x42080000, 0x00080100, 0x40000000,
+    0x02000000, 0x40080000, 0x40080000, 0x00000000,
+    0x40000100, 0x42080100, 0x42080100, 0x02000100,
+    0x42080000, 0x40000100, 0x00000000, 0x42000000,
+    0x02080100, 0x02000000, 0x42000000, 0x00080100,
+    0x00080000, 0x42000100, 0x00000100, 0x02000000,
+    0x40000000, 0x02080000, 0x42000100, 0x40080100,
+    0x02000100, 0x40000000, 0x42080000, 0x02080100,
+    0x40080100, 0x00000100, 0x02000000, 0x42080000,
+    0x42080100, 0x00080100, 0x42000000, 0x42080100,
+    0x02080000, 0x00000000, 0x40080000, 0x42000000,
+    0x00080100, 0x02000100, 0x40000100, 0x00080000,
+    0x00000000, 0x40080000, 0x02080100, 0x40000100
+};
+
+static const uint32_t SB6[64] =
+{
+    0x20000010, 0x20400000, 0x00004000, 0x20404010,
+    0x20400000, 0x00000010, 0x20404010, 0x00400000,
+    0x20004000, 0x00404010, 0x00400000, 0x20000010,
+    0x00400010, 0x20004000, 0x20000000, 0x00004010,
+    0x00000000, 0x00400010, 0x20004010, 0x00004000,
+    0x00404000, 0x20004010, 0x00000010, 0x20400010,
+    0x20400010, 0x00000000, 0x00404010, 0x20404000,
+    0x00004010, 0x00404000, 0x20404000, 0x20000000,
+    0x20004000, 0x00000010, 0x20400010, 0x00404000,
+    0x20404010, 0x00400000, 0x00004010, 0x20000010,
+    0x00400000, 0x20004000, 0x20000000, 0x00004010,
+    0x20000010, 0x20404010, 0x00404000, 0x20400000,
+    0x00404010, 0x20404000, 0x00000000, 0x20400010,
+    0x00000010, 0x00004000, 0x20400000, 0x00404010,
+    0x00004000, 0x00400010, 0x20004010, 0x00000000,
+    0x20404000, 0x20000000, 0x00400010, 0x20004010
+};
+
+static const uint32_t SB7[64] =
+{
+    0x00200000, 0x04200002, 0x04000802, 0x00000000,
+    0x00000800, 0x04000802, 0x00200802, 0x04200800,
+    0x04200802, 0x00200000, 0x00000000, 0x04000002,
+    0x00000002, 0x04000000, 0x04200002, 0x00000802,
+    0x04000800, 0x00200802, 0x00200002, 0x04000800,
+    0x04000002, 0x04200000, 0x04200800, 0x00200002,
+    0x04200000, 0x00000800, 0x00000802, 0x04200802,
+    0x00200800, 0x00000002, 0x04000000, 0x00200800,
+    0x04000000, 0x00200800, 0x00200000, 0x04000802,
+    0x04000802, 0x04200002, 0x04200002, 0x00000002,
+    0x00200002, 0x04000000, 0x04000800, 0x00200000,
+    0x04200800, 0x00000802, 0x00200802, 0x04200800,
+    0x00000802, 0x04000002, 0x04200802, 0x04200000,
+    0x00200800, 0x00000000, 0x00000002, 0x04200802,
+    0x00000000, 0x00200802, 0x04200000, 0x00000800,
+    0x04000002, 0x04000800, 0x00000800, 0x00200002
+};
+
+static const uint32_t SB8[64] =
+{
+    0x10001040, 0x00001000, 0x00040000, 0x10041040,
+    0x10000000, 0x10001040, 0x00000040, 0x10000000,
+    0x00040040, 0x10040000, 0x10041040, 0x00041000,
+    0x10041000, 0x00041040, 0x00001000, 0x00000040,
+    0x10040000, 0x10000040, 0x10001000, 0x00001040,
+    0x00041000, 0x00040040, 0x10040040, 0x10041000,
+    0x00001040, 0x00000000, 0x00000000, 0x10040040,
+    0x10000040, 0x10001000, 0x00041040, 0x00040000,
+    0x00041040, 0x00040000, 0x10041000, 0x00001000,
+    0x00000040, 0x10040040, 0x00001000, 0x00041040,
+    0x10001000, 0x00000040, 0x10000040, 0x10040000,
+    0x10040040, 0x10000000, 0x00040000, 0x10001040,
+    0x00000000, 0x10041040, 0x00040040, 0x10000040,
+    0x10040000, 0x10001000, 0x10001040, 0x00000000,
+    0x10041040, 0x00041000, 0x00041000, 0x00001040,
+    0x00001040, 0x00040040, 0x10000000, 0x10041000
+};
+
+/*
+ * PC1: left and right halves bit-swap
+ */
+static const uint32_t LHs[16] =
+{
+    0x00000000, 0x00000001, 0x00000100, 0x00000101,
+    0x00010000, 0x00010001, 0x00010100, 0x00010101,
+    0x01000000, 0x01000001, 0x01000100, 0x01000101,
+    0x01010000, 0x01010001, 0x01010100, 0x01010101
+};
+
+static const uint32_t RHs[16] =
+{
+    0x00000000, 0x01000000, 0x00010000, 0x01010000,
+    0x00000100, 0x01000100, 0x00010100, 0x01010100,
+    0x00000001, 0x01000001, 0x00010001, 0x01010001,
+    0x00000101, 0x01000101, 0x00010101, 0x01010101,
+};
+
+/*
+ * Initial Permutation macro
+ */
+#define DES_IP(X,Y)                                             \
+{                                                               \
+    T = ((X >>  4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T <<  4);   \
+    T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16);   \
+    T = ((Y >>  2) ^ X) & 0x33333333; X ^= T; Y ^= (T <<  2);   \
+    T = ((Y >>  8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T <<  8);   \
+    Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF;                    \
+    T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T;                   \
+    X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF;                    \
+}
+
+/*
+ * Final Permutation macro
+ */
+#define DES_FP(X,Y)                                             \
+{                                                               \
+    X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF;                    \
+    T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T;                   \
+    Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF;                    \
+    T = ((Y >>  8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T <<  8);   \
+    T = ((Y >>  2) ^ X) & 0x33333333; X ^= T; Y ^= (T <<  2);   \
+    T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16);   \
+    T = ((X >>  4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T <<  4);   \
+}
+
+/*
+ * DES round macro
+ */
+#define DES_ROUND(X,Y)                          \
+{                                               \
+    T = *SK++ ^ X;                              \
+    Y ^= SB8[ (T      ) & 0x3F ] ^              \
+         SB6[ (T >>  8) & 0x3F ] ^              \
+         SB4[ (T >> 16) & 0x3F ] ^              \
+         SB2[ (T >> 24) & 0x3F ];               \
+                                                \
+    T = *SK++ ^ ((X << 28) | (X >> 4));         \
+    Y ^= SB7[ (T      ) & 0x3F ] ^              \
+         SB5[ (T >>  8) & 0x3F ] ^              \
+         SB3[ (T >> 16) & 0x3F ] ^              \
+         SB1[ (T >> 24) & 0x3F ];               \
+}
+
+#define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 0; }
+
+void mbedtls_des_init( mbedtls_des_context *ctx )
+{
+    memset( ctx, 0, sizeof( mbedtls_des_context ) );
+}
+
+void mbedtls_des_free( mbedtls_des_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    mbedtls_zeroize( ctx, sizeof( mbedtls_des_context ) );
+}
+
+void mbedtls_des3_init( mbedtls_des3_context *ctx )
+{
+    memset( ctx, 0, sizeof( mbedtls_des3_context ) );
+}
+
+void mbedtls_des3_free( mbedtls_des3_context *ctx )
+{
+    if( ctx == NULL )
+        return;
+
+    mbedtls_zeroize( ctx, sizeof( mbedtls_des3_context ) );
+}
+
+static const unsigned char odd_parity_table[128] = { 1,  2,  4,  7,  8,
+        11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
+        47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
+        82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
+        115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
+        143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
+        171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
+        199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
+        227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
+        254 };
+
+void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] )
+{
+    int i;
+
+    for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ )
+        key[i] = odd_parity_table[key[i] / 2];
+}
+
+/*
+ * Check the given key's parity, returns 1 on failure, 0 on SUCCESS
+ */
+int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
+{
+    int i;
+
+    for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ )
+        if( key[i] != odd_parity_table[key[i] / 2] )
+            return( 1 );
+
+    return( 0 );
+}
+
+/*
+ * Table of weak and semi-weak keys
+ *
+ * Source: http://en.wikipedia.org/wiki/Weak_key
+ *
+ * Weak:
+ * Alternating ones + zeros (0x0101010101010101)
+ * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE)
+ * '0xE0E0E0E0F1F1F1F1'
+ * '0x1F1F1F1F0E0E0E0E'
+ *
+ * Semi-weak:
+ * 0x011F011F010E010E and 0x1F011F010E010E01
+ * 0x01E001E001F101F1 and 0xE001E001F101F101
+ * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01
+ * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E
+ * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E
+ * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1
+ *
+ */
+
+#define WEAK_KEY_COUNT 16
+
+static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] =
+{
+    { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+    { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
+    { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
+    { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 },
+
+    { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E },
+    { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 },
+    { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 },
+    { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 },
+    { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE },
+    { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 },
+    { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 },
+    { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E },
+    { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE },
+    { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E },
+    { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },
+    { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 }
+};
+
+int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
+{
+    int i;
+
+    for( i = 0; i < WEAK_KEY_COUNT; i++ )
+        if( memcmp( weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0 )
+            return( 1 );
+
+    return( 0 );
+}
+
+#if !defined(MBEDTLS_DES_SETKEY_ALT)
+void mbedtls_des_setkey( uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
+{
+    int i;
+    uint32_t X, Y, T;
+
+    GET_UINT32_BE( X, key, 0 );
+    GET_UINT32_BE( Y, key, 4 );
+
+    /*
+     * Permuted Choice 1
+     */
+    T =  ((Y >>  4) ^ X) & 0x0F0F0F0F;  X ^= T; Y ^= (T <<  4);
+    T =  ((Y      ) ^ X) & 0x10101010;  X ^= T; Y ^= (T      );
+
+    X =   (LHs[ (X      ) & 0xF] << 3) | (LHs[ (X >>  8) & 0xF ] << 2)
+        | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ]     )
+        | (LHs[ (X >>  5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6)
+        | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4);
+
+    Y =   (RHs[ (Y >>  1) & 0xF] << 3) | (RHs[ (Y >>  9) & 0xF ] << 2)
+        | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ]     )
+        | (RHs[ (Y >>  4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6)
+        | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4);
+
+    X &= 0x0FFFFFFF;
+    Y &= 0x0FFFFFFF;
+
+    /*
+     * calculate subkeys
+     */
+    for( i = 0; i < 16; i++ )
+    {
+        if( i < 2 || i == 8 || i == 15 )
+        {
+            X = ((X <<  1) | (X >> 27)) & 0x0FFFFFFF;
+            Y = ((Y <<  1) | (Y >> 27)) & 0x0FFFFFFF;
+        }
+        else
+        {
+            X = ((X <<  2) | (X >> 26)) & 0x0FFFFFFF;
+            Y = ((Y <<  2) | (Y >> 26)) & 0x0FFFFFFF;
+        }
+
+        *SK++ =   ((X <<  4) & 0x24000000) | ((X << 28) & 0x10000000)
+                | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000)
+                | ((X <<  6) & 0x01000000) | ((X <<  9) & 0x00200000)
+                | ((X >>  1) & 0x00100000) | ((X << 10) & 0x00040000)
+                | ((X <<  2) & 0x00020000) | ((X >> 10) & 0x00010000)
+                | ((Y >> 13) & 0x00002000) | ((Y >>  4) & 0x00001000)
+                | ((Y <<  6) & 0x00000800) | ((Y >>  1) & 0x00000400)
+                | ((Y >> 14) & 0x00000200) | ((Y      ) & 0x00000100)
+                | ((Y >>  5) & 0x00000020) | ((Y >> 10) & 0x00000010)
+                | ((Y >>  3) & 0x00000008) | ((Y >> 18) & 0x00000004)
+                | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001);
+
+        *SK++ =   ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000)
+                | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000)
+                | ((X >>  2) & 0x02000000) | ((X <<  1) & 0x01000000)
+                | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000)
+                | ((X <<  3) & 0x00080000) | ((X >>  6) & 0x00040000)
+                | ((X << 15) & 0x00020000) | ((X >>  4) & 0x00010000)
+                | ((Y >>  2) & 0x00002000) | ((Y <<  8) & 0x00001000)
+                | ((Y >> 14) & 0x00000808) | ((Y >>  9) & 0x00000400)
+                | ((Y      ) & 0x00000200) | ((Y <<  7) & 0x00000100)
+                | ((Y >>  7) & 0x00000020) | ((Y >>  3) & 0x00000011)
+                | ((Y <<  2) & 0x00000004) | ((Y >> 21) & 0x00000002);
+    }
+}
+#endif /* !MBEDTLS_DES_SETKEY_ALT */
+
+/*
+ * DES key schedule (56-bit, encryption)
+ */
+int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
+{
+    mbedtls_des_setkey( ctx->sk, key );
+
+    return( 0 );
+}
+
+/*
+ * DES key schedule (56-bit, decryption)
+ */
+int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] )
+{
+    int i;
+
+    mbedtls_des_setkey( ctx->sk, key );
+
+    for( i = 0; i < 16; i += 2 )
+    {
+        SWAP( ctx->sk[i    ], ctx->sk[30 - i] );
+        SWAP( ctx->sk[i + 1], ctx->sk[31 - i] );
+    }
+
+    return( 0 );
+}
+
+static void des3_set2key( uint32_t esk[96],
+                          uint32_t dsk[96],
+                          const unsigned char key[MBEDTLS_DES_KEY_SIZE*2] )
+{
+    int i;
+
+    mbedtls_des_setkey( esk, key );
+    mbedtls_des_setkey( dsk + 32, key + 8 );
+
+    for( i = 0; i < 32; i += 2 )
+    {
+        dsk[i     ] = esk[30 - i];
+        dsk[i +  1] = esk[31 - i];
+
+        esk[i + 32] = dsk[62 - i];
+        esk[i + 33] = dsk[63 - i];
+
+        esk[i + 64] = esk[i    ];
+        esk[i + 65] = esk[i + 1];
+
+        dsk[i + 64] = dsk[i    ];
+        dsk[i + 65] = dsk[i + 1];
+    }
+}
+
+/*
+ * Triple-DES key schedule (112-bit, encryption)
+ */
+int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
+                      const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
+{
+    uint32_t sk[96];
+
+    des3_set2key( ctx->sk, sk, key );
+    mbedtls_zeroize( sk,  sizeof( sk ) );
+
+    return( 0 );
+}
+
+/*
+ * Triple-DES key schedule (112-bit, decryption)
+ */
+int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
+                      const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] )
+{
+    uint32_t sk[96];
+
+    des3_set2key( sk, ctx->sk, key );
+    mbedtls_zeroize( sk,  sizeof( sk ) );
+
+    return( 0 );
+}
+
+static void des3_set3key( uint32_t esk[96],
+                          uint32_t dsk[96],
+                          const unsigned char key[24] )
+{
+    int i;
+
+    mbedtls_des_setkey( esk, key );
+    mbedtls_des_setkey( dsk + 32, key +  8 );
+    mbedtls_des_setkey( esk + 64, key + 16 );
+
+    for( i = 0; i < 32; i += 2 )
+    {
+        dsk[i     ] = esk[94 - i];
+        dsk[i +  1] = esk[95 - i];
+
+        esk[i + 32] = dsk[62 - i];
+        esk[i + 33] = dsk[63 - i];
+
+        dsk[i + 64] = esk[30 - i];
+        dsk[i + 65] = esk[31 - i];
+    }
+}
+
+/*
+ * Triple-DES key schedule (168-bit, encryption)
+ */
+int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
+                      const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
+{
+    uint32_t sk[96];
+
+    des3_set3key( ctx->sk, sk, key );
+    mbedtls_zeroize( sk,  sizeof( sk ) );
+
+    return( 0 );
+}
+
+/*
+ * Triple-DES key schedule (168-bit, decryption)
+ */
+int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
+                      const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] )
+{
+    uint32_t sk[96];
+
+    des3_set3key( sk, ctx->sk, key );
+    mbedtls_zeroize( sk,  sizeof( sk ) );
+
+    return( 0 );
+}
+
+/*
+ * DES-ECB block encryption/decryption
+ */
+#if !defined(MBEDTLS_DES_CRYPT_ECB_ALT)
+int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
+                    const unsigned char input[8],
+                    unsigned char output[8] )
+{
+    int i;
+    uint32_t X, Y, T, *SK;
+
+    SK = ctx->sk;
+
+    GET_UINT32_BE( X, input, 0 );
+    GET_UINT32_BE( Y, input, 4 );
+
+    DES_IP( X, Y );
+
+    for( i = 0; i < 8; i++ )
+    {
+        DES_ROUND( Y, X );
+        DES_ROUND( X, Y );
+    }
+
+    DES_FP( Y, X );
+
+    PUT_UINT32_BE( Y, output, 0 );
+    PUT_UINT32_BE( X, output, 4 );
+
+    return( 0 );
+}
+#endif /* !MBEDTLS_DES_CRYPT_ECB_ALT */
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+/*
+ * DES-CBC buffer encryption/decryption
+ */
+int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
+                    int mode,
+                    size_t length,
+                    unsigned char iv[8],
+                    const unsigned char *input,
+                    unsigned char *output )
+{
+    int i;
+    unsigned char temp[8];
+
+    if( length % 8 )
+        return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH );
+
+    if( mode == MBEDTLS_DES_ENCRYPT )
+    {
+        while( length > 0 )
+        {
+            for( i = 0; i < 8; i++ )
+                output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+            mbedtls_des_crypt_ecb( ctx, output, output );
+            memcpy( iv, output, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+    else /* MBEDTLS_DES_DECRYPT */
+    {
+        while( length > 0 )
+        {
+            memcpy( temp, input, 8 );
+            mbedtls_des_crypt_ecb( ctx, input, output );
+
+            for( i = 0; i < 8; i++ )
+                output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+            memcpy( iv, temp, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+
+    return( 0 );
+}
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+/*
+ * 3DES-ECB block encryption/decryption
+ */
+#if !defined(MBEDTLS_DES3_CRYPT_ECB_ALT)
+int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
+                     const unsigned char input[8],
+                     unsigned char output[8] )
+{
+    int i;
+    uint32_t X, Y, T, *SK;
+
+    SK = ctx->sk;
+
+    GET_UINT32_BE( X, input, 0 );
+    GET_UINT32_BE( Y, input, 4 );
+
+    DES_IP( X, Y );
+
+    for( i = 0; i < 8; i++ )
+    {
+        DES_ROUND( Y, X );
+        DES_ROUND( X, Y );
+    }
+
+    for( i = 0; i < 8; i++ )
+    {
+        DES_ROUND( X, Y );
+        DES_ROUND( Y, X );
+    }
+
+    for( i = 0; i < 8; i++ )
+    {
+        DES_ROUND( Y, X );
+        DES_ROUND( X, Y );
+    }
+
+    DES_FP( Y, X );
+
+    PUT_UINT32_BE( Y, output, 0 );
+    PUT_UINT32_BE( X, output, 4 );
+
+    return( 0 );
+}
+#endif /* !MBEDTLS_DES3_CRYPT_ECB_ALT */
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+/*
+ * 3DES-CBC buffer encryption/decryption
+ */
+int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
+                     int mode,
+                     size_t length,
+                     unsigned char iv[8],
+                     const unsigned char *input,
+                     unsigned char *output )
+{
+    int i;
+    unsigned char temp[8];
+
+    if( length % 8 )
+        return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH );
+
+    if( mode == MBEDTLS_DES_ENCRYPT )
+    {
+        while( length > 0 )
+        {
+            for( i = 0; i < 8; i++ )
+                output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+            mbedtls_des3_crypt_ecb( ctx, output, output );
+            memcpy( iv, output, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+    else /* MBEDTLS_DES_DECRYPT */
+    {
+        while( length > 0 )
+        {
+            memcpy( temp, input, 8 );
+            mbedtls_des3_crypt_ecb( ctx, input, output );
+
+            for( i = 0; i < 8; i++ )
+                output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+            memcpy( iv, temp, 8 );
+
+            input  += 8;
+            output += 8;
+            length -= 8;
+        }
+    }
+
+    return( 0 );
+}
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#endif /* !MBEDTLS_DES_ALT */
+
+#if defined(MBEDTLS_SELF_TEST)
+/*
+ * DES and 3DES test vectors from:
+ *
+ * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip
+ */
+static const unsigned char des3_test_keys[24] =
+{
+    0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+    0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,
+    0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
+};
+
+static const unsigned char des3_test_buf[8] =
+{
+    0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74
+};
+
+static const unsigned char des3_test_ecb_dec[3][8] =
+{
+    { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D },
+    { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB },
+    { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A }
+};
+
+static const unsigned char des3_test_ecb_enc[3][8] =
+{
+    { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B },
+    { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 },
+    { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 }
+};
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+static const unsigned char des3_test_iv[8] =
+{
+    0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF,
+};
+
+static const unsigned char des3_test_cbc_dec[3][8] =
+{
+    { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 },
+    { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 },
+    { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C }
+};
+
+static const unsigned char des3_test_cbc_enc[3][8] =
+{
+    { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 },
+    { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D },
+    { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 }
+};
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+/*
+ * Checkup routine
+ */
+int mbedtls_des_self_test( int verbose )
+{
+    int i, j, u, v, ret = 0;
+    mbedtls_des_context ctx;
+    mbedtls_des3_context ctx3;
+    unsigned char buf[8];
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    unsigned char prv[8];
+    unsigned char iv[8];
+#endif
+
+    mbedtls_des_init( &ctx );
+    mbedtls_des3_init( &ctx3 );
+    /*
+     * ECB mode
+     */
+    for( i = 0; i < 6; i++ )
+    {
+        u = i >> 1;
+        v = i  & 1;
+
+        if( verbose != 0 )
+            mbedtls_printf( "  DES%c-ECB-%3d (%s): ",
+                             ( u == 0 ) ? ' ' : '3', 56 + u * 56,
+                             ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( buf, des3_test_buf, 8 );
+
+        switch( i )
+        {
+        case 0:
+            mbedtls_des_setkey_dec( &ctx, des3_test_keys );
+            break;
+
+        case 1:
+            mbedtls_des_setkey_enc( &ctx, des3_test_keys );
+            break;
+
+        case 2:
+            mbedtls_des3_set2key_dec( &ctx3, des3_test_keys );
+            break;
+
+        case 3:
+            mbedtls_des3_set2key_enc( &ctx3, des3_test_keys );
+            break;
+
+        case 4:
+            mbedtls_des3_set3key_dec( &ctx3, des3_test_keys );
+            break;
+
+        case 5:
+            mbedtls_des3_set3key_enc( &ctx3, des3_test_keys );
+            break;
+
+        default:
+            return( 1 );
+        }
+
+        for( j = 0; j < 10000; j++ )
+        {
+            if( u == 0 )
+                mbedtls_des_crypt_ecb( &ctx, buf, buf );
+            else
+                mbedtls_des3_crypt_ecb( &ctx3, buf, buf );
+        }
+
+        if( ( v == MBEDTLS_DES_DECRYPT &&
+                memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) ||
+            ( v != MBEDTLS_DES_DECRYPT &&
+                memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) )
+        {
+            if( verbose != 0 )
+                mbedtls_printf( "failed\n" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+
+    if( verbose != 0 )
+        mbedtls_printf( "\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( "  DES%c-CBC-%3d (%s): ",
+                             ( u == 0 ) ? ' ' : '3', 56 + u * 56,
+                             ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" );
+
+        memcpy( iv,  des3_test_iv,  8 );
+        memcpy( prv, des3_test_iv,  8 );
+        memcpy( buf, des3_test_buf, 8 );
+
+        switch( i )
+        {
+        case 0:
+            mbedtls_des_setkey_dec( &ctx, des3_test_keys );
+            break;
+
+        case 1:
+            mbedtls_des_setkey_enc( &ctx, des3_test_keys );
+            break;
+
+        case 2:
+            mbedtls_des3_set2key_dec( &ctx3, des3_test_keys );
+            break;
+
+        case 3:
+            mbedtls_des3_set2key_enc( &ctx3, des3_test_keys );
+            break;
+
+        case 4:
+            mbedtls_des3_set3key_dec( &ctx3, des3_test_keys );
+            break;
+
+        case 5:
+            mbedtls_des3_set3key_enc( &ctx3, des3_test_keys );
+            break;
+
+        default:
+            return( 1 );
+        }
+
+        if( v == MBEDTLS_DES_DECRYPT )
+        {
+            for( j = 0; j < 10000; j++ )
+            {
+                if( u == 0 )
+                    mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+                else
+                    mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+            }
+        }
+        else
+        {
+            for( j = 0; j < 10000; j++ )
+            {
+                unsigned char tmp[8];
+
+                if( u == 0 )
+                    mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+                else
+                    mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+
+                memcpy( tmp, prv, 8 );
+                memcpy( prv, buf, 8 );
+                memcpy( buf, tmp, 8 );
+            }
+
+            memcpy( buf, prv, 8 );
+        }
+
+        if( ( v == MBEDTLS_DES_DECRYPT &&
+                memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) ||
+            ( v != MBEDTLS_DES_DECRYPT &&
+                memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) )
+        {
+            if( verbose != 0 )
+                mbedtls_printf( "failed\n" );
+
+            ret = 1;
+            goto exit;
+        }
+
+        if( verbose != 0 )
+            mbedtls_printf( "passed\n" );
+    }
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+    if( verbose != 0 )
+        mbedtls_printf( "\n" );
+
+exit:
+    mbedtls_des_free( &ctx );
+    mbedtls_des3_free( &ctx3 );
+
+    return( ret );
+}
+
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_DES_C */