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 */