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:43:55 UTC
[29/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/memory_buffer_alloc.c
----------------------------------------------------------------------
diff --git a/crypto/mbedtls/src/memory_buffer_alloc.c b/crypto/mbedtls/src/memory_buffer_alloc.c
new file mode 100644
index 0000000..b2c775a
--- /dev/null
+++ b/crypto/mbedtls/src/memory_buffer_alloc.c
@@ -0,0 +1,750 @@
+/*
+ * Buffer-based memory allocator
+ *
+ * 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_MEMORY_BUFFER_ALLOC_C)
+#include "mbedtls/memory_buffer_alloc.h"
+
+/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ is dependent upon MBEDTLS_PLATFORM_C */
+#include "mbedtls/platform.h"
+
+#include <string.h>
+
+#if defined(MBEDTLS_MEMORY_BACKTRACE)
+#include <execinfo.h>
+#endif
+
+#if defined(MBEDTLS_THREADING_C)
+#include "mbedtls/threading.h"
+#endif
+
+/* 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;
+}
+
+#define MAGIC1 0xFF00AA55
+#define MAGIC2 0xEE119966
+#define MAX_BT 20
+
+typedef struct _memory_header memory_header;
+struct _memory_header
+{
+ size_t magic1;
+ size_t size;
+ size_t alloc;
+ memory_header *prev;
+ memory_header *next;
+ memory_header *prev_free;
+ memory_header *next_free;
+#if defined(MBEDTLS_MEMORY_BACKTRACE)
+ char **trace;
+ size_t trace_count;
+#endif
+ size_t magic2;
+};
+
+typedef struct
+{
+ unsigned char *buf;
+ size_t len;
+ memory_header *first;
+ memory_header *first_free;
+ int verify;
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ size_t alloc_count;
+ size_t free_count;
+ size_t total_used;
+ size_t maximum_used;
+ size_t header_count;
+ size_t maximum_header_count;
+#endif
+#if defined(MBEDTLS_THREADING_C)
+ mbedtls_threading_mutex_t mutex;
+#endif
+}
+buffer_alloc_ctx;
+
+static buffer_alloc_ctx heap;
+
+#if defined(MBEDTLS_MEMORY_DEBUG)
+static void debug_header( memory_header *hdr )
+{
+#if defined(MBEDTLS_MEMORY_BACKTRACE)
+ size_t i;
+#endif
+
+ mbedtls_fprintf( stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), "
+ "ALLOC(%zu), SIZE(%10zu)\n",
+ (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next,
+ hdr->alloc, hdr->size );
+ mbedtls_fprintf( stderr, " FPREV(%10zu), FNEXT(%10zu)\n",
+ (size_t) hdr->prev_free, (size_t) hdr->next_free );
+
+#if defined(MBEDTLS_MEMORY_BACKTRACE)
+ mbedtls_fprintf( stderr, "TRACE: \n" );
+ for( i = 0; i < hdr->trace_count; i++ )
+ mbedtls_fprintf( stderr, "%s\n", hdr->trace[i] );
+ mbedtls_fprintf( stderr, "\n" );
+#endif
+}
+
+static void debug_chain()
+{
+ memory_header *cur = heap.first;
+
+ mbedtls_fprintf( stderr, "\nBlock list\n" );
+ while( cur != NULL )
+ {
+ debug_header( cur );
+ cur = cur->next;
+ }
+
+ mbedtls_fprintf( stderr, "Free list\n" );
+ cur = heap.first_free;
+
+ while( cur != NULL )
+ {
+ debug_header( cur );
+ cur = cur->next_free;
+ }
+}
+#endif /* MBEDTLS_MEMORY_DEBUG */
+
+static int verify_header( memory_header *hdr )
+{
+ if( hdr->magic1 != MAGIC1 )
+ {
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ mbedtls_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" );
+#endif
+ return( 1 );
+ }
+
+ if( hdr->magic2 != MAGIC2 )
+ {
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ mbedtls_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" );
+#endif
+ return( 1 );
+ }
+
+ if( hdr->alloc > 1 )
+ {
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ mbedtls_fprintf( stderr, "FATAL: alloc has illegal value\n" );
+#endif
+ return( 1 );
+ }
+
+ if( hdr->prev != NULL && hdr->prev == hdr->next )
+ {
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ mbedtls_fprintf( stderr, "FATAL: prev == next\n" );
+#endif
+ return( 1 );
+ }
+
+ if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free )
+ {
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ mbedtls_fprintf( stderr, "FATAL: prev_free == next_free\n" );
+#endif
+ return( 1 );
+ }
+
+ return( 0 );
+}
+
+static int verify_chain()
+{
+ memory_header *prv = heap.first, *cur = heap.first->next;
+
+ if( verify_header( heap.first ) != 0 )
+ {
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ mbedtls_fprintf( stderr, "FATAL: verification of first header "
+ "failed\n" );
+#endif
+ return( 1 );
+ }
+
+ if( heap.first->prev != NULL )
+ {
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ mbedtls_fprintf( stderr, "FATAL: verification failed: "
+ "first->prev != NULL\n" );
+#endif
+ return( 1 );
+ }
+
+ while( cur != NULL )
+ {
+ if( verify_header( cur ) != 0 )
+ {
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ mbedtls_fprintf( stderr, "FATAL: verification of header "
+ "failed\n" );
+#endif
+ return( 1 );
+ }
+
+ if( cur->prev != prv )
+ {
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ mbedtls_fprintf( stderr, "FATAL: verification failed: "
+ "cur->prev != prv\n" );
+#endif
+ return( 1 );
+ }
+
+ prv = cur;
+ cur = cur->next;
+ }
+
+ return( 0 );
+}
+
+static void *buffer_alloc_calloc( size_t n, size_t size )
+{
+ memory_header *new, *cur = heap.first_free;
+ unsigned char *p;
+ void *ret;
+ size_t original_len, len;
+#if defined(MBEDTLS_MEMORY_BACKTRACE)
+ void *trace_buffer[MAX_BT];
+ size_t trace_cnt;
+#endif
+
+ if( heap.buf == NULL || heap.first == NULL )
+ return( NULL );
+
+ original_len = len = n * size;
+
+ if( n != 0 && len / n != size )
+ return( NULL );
+
+ if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE )
+ {
+ len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
+ len += MBEDTLS_MEMORY_ALIGN_MULTIPLE;
+ }
+
+ // Find block that fits
+ //
+ while( cur != NULL )
+ {
+ if( cur->size >= len )
+ break;
+
+ cur = cur->next_free;
+ }
+
+ if( cur == NULL )
+ return( NULL );
+
+ if( cur->alloc != 0 )
+ {
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ mbedtls_fprintf( stderr, "FATAL: block in free_list but allocated "
+ "data\n" );
+#endif
+ mbedtls_exit( 1 );
+ }
+
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ heap.alloc_count++;
+#endif
+
+ // Found location, split block if > memory_header + 4 room left
+ //
+ if( cur->size - len < sizeof(memory_header) +
+ MBEDTLS_MEMORY_ALIGN_MULTIPLE )
+ {
+ cur->alloc = 1;
+
+ // Remove from free_list
+ //
+ if( cur->prev_free != NULL )
+ cur->prev_free->next_free = cur->next_free;
+ else
+ heap.first_free = cur->next_free;
+
+ if( cur->next_free != NULL )
+ cur->next_free->prev_free = cur->prev_free;
+
+ cur->prev_free = NULL;
+ cur->next_free = NULL;
+
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ heap.total_used += cur->size;
+ if( heap.total_used > heap.maximum_used )
+ heap.maximum_used = heap.total_used;
+#endif
+#if defined(MBEDTLS_MEMORY_BACKTRACE)
+ trace_cnt = backtrace( trace_buffer, MAX_BT );
+ cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
+ cur->trace_count = trace_cnt;
+#endif
+
+ if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
+ mbedtls_exit( 1 );
+
+ ret = (unsigned char *) cur + sizeof( memory_header );
+ memset( ret, 0, original_len );
+
+ return( ret );
+ }
+
+ p = ( (unsigned char *) cur ) + sizeof(memory_header) + len;
+ new = (memory_header *) p;
+
+ new->size = cur->size - len - sizeof(memory_header);
+ new->alloc = 0;
+ new->prev = cur;
+ new->next = cur->next;
+#if defined(MBEDTLS_MEMORY_BACKTRACE)
+ new->trace = NULL;
+ new->trace_count = 0;
+#endif
+ new->magic1 = MAGIC1;
+ new->magic2 = MAGIC2;
+
+ if( new->next != NULL )
+ new->next->prev = new;
+
+ // Replace cur with new in free_list
+ //
+ new->prev_free = cur->prev_free;
+ new->next_free = cur->next_free;
+ if( new->prev_free != NULL )
+ new->prev_free->next_free = new;
+ else
+ heap.first_free = new;
+
+ if( new->next_free != NULL )
+ new->next_free->prev_free = new;
+
+ cur->alloc = 1;
+ cur->size = len;
+ cur->next = new;
+ cur->prev_free = NULL;
+ cur->next_free = NULL;
+
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ heap.header_count++;
+ if( heap.header_count > heap.maximum_header_count )
+ heap.maximum_header_count = heap.header_count;
+ heap.total_used += cur->size;
+ if( heap.total_used > heap.maximum_used )
+ heap.maximum_used = heap.total_used;
+#endif
+#if defined(MBEDTLS_MEMORY_BACKTRACE)
+ trace_cnt = backtrace( trace_buffer, MAX_BT );
+ cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
+ cur->trace_count = trace_cnt;
+#endif
+
+ if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
+ mbedtls_exit( 1 );
+
+ ret = (unsigned char *) cur + sizeof( memory_header );
+ memset( ret, 0, original_len );
+
+ return( ret );
+}
+
+static void buffer_alloc_free( void *ptr )
+{
+ memory_header *hdr, *old = NULL;
+ unsigned char *p = (unsigned char *) ptr;
+
+ if( ptr == NULL || heap.buf == NULL || heap.first == NULL )
+ return;
+
+ if( p < heap.buf || p > heap.buf + heap.len )
+ {
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed "
+ "space\n" );
+#endif
+ mbedtls_exit( 1 );
+ }
+
+ p -= sizeof(memory_header);
+ hdr = (memory_header *) p;
+
+ if( verify_header( hdr ) != 0 )
+ mbedtls_exit( 1 );
+
+ if( hdr->alloc != 1 )
+ {
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ mbedtls_fprintf( stderr, "FATAL: mbedtls_free() on unallocated "
+ "data\n" );
+#endif
+ mbedtls_exit( 1 );
+ }
+
+ hdr->alloc = 0;
+
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ heap.free_count++;
+ heap.total_used -= hdr->size;
+#endif
+
+ // Regroup with block before
+ //
+ if( hdr->prev != NULL && hdr->prev->alloc == 0 )
+ {
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ heap.header_count--;
+#endif
+ hdr->prev->size += sizeof(memory_header) + hdr->size;
+ hdr->prev->next = hdr->next;
+ old = hdr;
+ hdr = hdr->prev;
+
+ if( hdr->next != NULL )
+ hdr->next->prev = hdr;
+
+#if defined(MBEDTLS_MEMORY_BACKTRACE)
+ free( old->trace );
+#endif
+ memset( old, 0, sizeof(memory_header) );
+ }
+
+ // Regroup with block after
+ //
+ if( hdr->next != NULL && hdr->next->alloc == 0 )
+ {
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ heap.header_count--;
+#endif
+ hdr->size += sizeof(memory_header) + hdr->next->size;
+ old = hdr->next;
+ hdr->next = hdr->next->next;
+
+ if( hdr->prev_free != NULL || hdr->next_free != NULL )
+ {
+ if( hdr->prev_free != NULL )
+ hdr->prev_free->next_free = hdr->next_free;
+ else
+ heap.first_free = hdr->next_free;
+
+ if( hdr->next_free != NULL )
+ hdr->next_free->prev_free = hdr->prev_free;
+ }
+
+ hdr->prev_free = old->prev_free;
+ hdr->next_free = old->next_free;
+
+ if( hdr->prev_free != NULL )
+ hdr->prev_free->next_free = hdr;
+ else
+ heap.first_free = hdr;
+
+ if( hdr->next_free != NULL )
+ hdr->next_free->prev_free = hdr;
+
+ if( hdr->next != NULL )
+ hdr->next->prev = hdr;
+
+#if defined(MBEDTLS_MEMORY_BACKTRACE)
+ free( old->trace );
+#endif
+ memset( old, 0, sizeof(memory_header) );
+ }
+
+ // Prepend to free_list if we have not merged
+ // (Does not have to stay in same order as prev / next list)
+ //
+ if( old == NULL )
+ {
+ hdr->next_free = heap.first_free;
+ if( heap.first_free != NULL )
+ heap.first_free->prev_free = hdr;
+ heap.first_free = hdr;
+ }
+
+#if defined(MBEDTLS_MEMORY_BACKTRACE)
+ hdr->trace = NULL;
+ hdr->trace_count = 0;
+#endif
+
+ if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_FREE ) && verify_chain() != 0 )
+ mbedtls_exit( 1 );
+}
+
+void mbedtls_memory_buffer_set_verify( int verify )
+{
+ heap.verify = verify;
+}
+
+int mbedtls_memory_buffer_alloc_verify()
+{
+ return verify_chain();
+}
+
+#if defined(MBEDTLS_MEMORY_DEBUG)
+void mbedtls_memory_buffer_alloc_status()
+{
+ mbedtls_fprintf( stderr,
+ "Current use: %zu blocks / %zu bytes, max: %zu blocks / "
+ "%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n",
+ heap.header_count, heap.total_used,
+ heap.maximum_header_count, heap.maximum_used,
+ heap.maximum_header_count * sizeof( memory_header )
+ + heap.maximum_used,
+ heap.alloc_count, heap.free_count );
+
+ if( heap.first->next == NULL )
+ mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" );
+ else
+ {
+ mbedtls_fprintf( stderr, "Memory currently allocated:\n" );
+ debug_chain();
+ }
+}
+
+void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks )
+{
+ *max_used = heap.maximum_used;
+ *max_blocks = heap.maximum_header_count;
+}
+
+void mbedtls_memory_buffer_alloc_max_reset( void )
+{
+ heap.maximum_used = 0;
+ heap.maximum_header_count = 0;
+}
+
+void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks )
+{
+ *cur_used = heap.total_used;
+ *cur_blocks = heap.header_count;
+}
+#endif /* MBEDTLS_MEMORY_DEBUG */
+
+#if defined(MBEDTLS_THREADING_C)
+static void *buffer_alloc_calloc_mutexed( size_t n, size_t size )
+{
+ void *buf;
+ if( mbedtls_mutex_lock( &heap.mutex ) != 0 )
+ return( NULL );
+ buf = buffer_alloc_calloc( n, size );
+ if( mbedtls_mutex_unlock( &heap.mutex ) )
+ return( NULL );
+ return( buf );
+}
+
+static void buffer_alloc_free_mutexed( void *ptr )
+{
+ /* We have to good option here, but corrupting the heap seems
+ * worse than loosing memory. */
+ if( mbedtls_mutex_lock( &heap.mutex ) )
+ return;
+ buffer_alloc_free( ptr );
+ (void) mbedtls_mutex_unlock( &heap.mutex );
+}
+#endif /* MBEDTLS_THREADING_C */
+
+void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len )
+{
+ memset( &heap, 0, sizeof(buffer_alloc_ctx) );
+ memset( buf, 0, len );
+
+#if defined(MBEDTLS_THREADING_C)
+ mbedtls_mutex_init( &heap.mutex );
+ mbedtls_platform_set_calloc_free( buffer_alloc_calloc_mutexed,
+ buffer_alloc_free_mutexed );
+#else
+ mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free );
+#endif
+
+ if( (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE )
+ {
+ /* Adjust len first since buf is used in the computation */
+ len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE
+ - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
+ buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE
+ - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
+ }
+
+ heap.buf = buf;
+ heap.len = len;
+
+ heap.first = (memory_header *) buf;
+ heap.first->size = len - sizeof(memory_header);
+ heap.first->magic1 = MAGIC1;
+ heap.first->magic2 = MAGIC2;
+ heap.first_free = heap.first;
+}
+
+void mbedtls_memory_buffer_alloc_free()
+{
+#if defined(MBEDTLS_THREADING_C)
+ mbedtls_mutex_free( &heap.mutex );
+#endif
+ mbedtls_zeroize( &heap, sizeof(buffer_alloc_ctx) );
+}
+
+#if defined(MBEDTLS_SELF_TEST)
+static int check_pointer( void *p )
+{
+ if( p == NULL )
+ return( -1 );
+
+ if( (size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0 )
+ return( -1 );
+
+ return( 0 );
+}
+
+static int check_all_free( )
+{
+ if(
+#if defined(MBEDTLS_MEMORY_DEBUG)
+ heap.total_used != 0 ||
+#endif
+ heap.first != heap.first_free ||
+ (void *) heap.first != (void *) heap.buf )
+ {
+ return( -1 );
+ }
+
+ return( 0 );
+}
+
+#define TEST_ASSERT( condition ) \
+ if( ! (condition) ) \
+ { \
+ if( verbose != 0 ) \
+ mbedtls_printf( "failed\n" ); \
+ \
+ ret = 1; \
+ goto cleanup; \
+ }
+
+int mbedtls_memory_buffer_alloc_self_test( int verbose )
+{
+ unsigned char buf[1024];
+ unsigned char *p, *q, *r, *end;
+ int ret = 0;
+
+ if( verbose != 0 )
+ mbedtls_printf( " MBA test #1 (basic alloc-free cycle): " );
+
+ mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
+
+ p = mbedtls_calloc( 1, 1 );
+ q = mbedtls_calloc( 1, 128 );
+ r = mbedtls_calloc( 1, 16 );
+
+ TEST_ASSERT( check_pointer( p ) == 0 &&
+ check_pointer( q ) == 0 &&
+ check_pointer( r ) == 0 );
+
+ mbedtls_free( r );
+ mbedtls_free( q );
+ mbedtls_free( p );
+
+ TEST_ASSERT( check_all_free( ) == 0 );
+
+ /* Memorize end to compare with the next test */
+ end = heap.buf + heap.len;
+
+ mbedtls_memory_buffer_alloc_free( );
+
+ if( verbose != 0 )
+ mbedtls_printf( "passed\n" );
+
+ if( verbose != 0 )
+ mbedtls_printf( " MBA test #2 (buf not aligned): " );
+
+ mbedtls_memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 );
+
+ TEST_ASSERT( heap.buf + heap.len == end );
+
+ p = mbedtls_calloc( 1, 1 );
+ q = mbedtls_calloc( 1, 128 );
+ r = mbedtls_calloc( 1, 16 );
+
+ TEST_ASSERT( check_pointer( p ) == 0 &&
+ check_pointer( q ) == 0 &&
+ check_pointer( r ) == 0 );
+
+ mbedtls_free( r );
+ mbedtls_free( q );
+ mbedtls_free( p );
+
+ TEST_ASSERT( check_all_free( ) == 0 );
+
+ mbedtls_memory_buffer_alloc_free( );
+
+ if( verbose != 0 )
+ mbedtls_printf( "passed\n" );
+
+ if( verbose != 0 )
+ mbedtls_printf( " MBA test #3 (full): " );
+
+ mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
+
+ p = mbedtls_calloc( 1, sizeof( buf ) - sizeof( memory_header ) );
+
+ TEST_ASSERT( check_pointer( p ) == 0 );
+ TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL );
+
+ mbedtls_free( p );
+
+ p = mbedtls_calloc( 1, sizeof( buf ) - 2 * sizeof( memory_header ) - 16 );
+ q = mbedtls_calloc( 1, 16 );
+
+ TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 );
+ TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL );
+
+ mbedtls_free( q );
+
+ TEST_ASSERT( mbedtls_calloc( 1, 17 ) == NULL );
+
+ mbedtls_free( p );
+
+ TEST_ASSERT( check_all_free( ) == 0 );
+
+ mbedtls_memory_buffer_alloc_free( );
+
+ if( verbose != 0 )
+ mbedtls_printf( "passed\n" );
+
+cleanup:
+ mbedtls_memory_buffer_alloc_free( );
+
+ return( ret );
+}
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/crypto/mbedtls/src/net.c
----------------------------------------------------------------------
diff --git a/crypto/mbedtls/src/net.c b/crypto/mbedtls/src/net.c
new file mode 100644
index 0000000..a77268c
--- /dev/null
+++ b/crypto/mbedtls/src/net.c
@@ -0,0 +1,575 @@
+/*
+ * TCP/IP or UDP/IP networking functions
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_NET_C)
+
+#include "mbedtls/net.h"
+
+#include <string.h>
+
+#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
+ !defined(EFI32)
+
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#endif
+/* Enables getaddrinfo() & Co */
+#define _WIN32_WINNT 0x0501
+#include <ws2tcpip.h>
+
+#include <winsock2.h>
+#include <windows.h>
+
+#if defined(_MSC_VER)
+#if defined(_WIN32_WCE)
+#pragma comment( lib, "ws2.lib" )
+#else
+#pragma comment( lib, "ws2_32.lib" )
+#endif
+#endif /* _MSC_VER */
+
+#define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0)
+#define write(fd,buf,len) send(fd,(char*)buf,(int) len,0)
+#define close(fd) closesocket(fd)
+
+static int wsa_init_done = 0;
+
+#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <errno.h>
+
+#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
+
+/* Some MS functions want int and MSVC warns if we pass size_t,
+ * but the standard fucntions use socklen_t, so cast only for MSVC */
+#if defined(_MSC_VER)
+#define MSVC_INT_CAST (int)
+#else
+#define MSVC_INT_CAST
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <time.h>
+
+#include <stdint.h>
+
+/*
+ * Prepare for using the sockets interface
+ */
+static int net_prepare( void )
+{
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+ !defined(EFI32)
+ WSADATA wsaData;
+
+ if( wsa_init_done == 0 )
+ {
+ if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
+ return( MBEDTLS_ERR_NET_SOCKET_FAILED );
+
+ wsa_init_done = 1;
+ }
+#else
+#if !defined(EFIX64) && !defined(EFI32)
+ signal( SIGPIPE, SIG_IGN );
+#endif
+#endif
+ return( 0 );
+}
+
+/*
+ * Initialize a context
+ */
+void mbedtls_net_init( mbedtls_net_context *ctx )
+{
+ ctx->fd = -1;
+}
+
+/*
+ * Initiate a TCP connection with host:port and the given protocol
+ */
+int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto )
+{
+ int ret;
+ struct addrinfo hints, *addr_list, *cur;
+
+ if( ( ret = net_prepare() ) != 0 )
+ return( ret );
+
+ /* Do name resolution with both IPv6 and IPv4 */
+ memset( &hints, 0, sizeof( hints ) );
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
+ hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
+
+ if( getaddrinfo( host, port, &hints, &addr_list ) != 0 )
+ return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
+
+ /* Try the sockaddrs until a connection succeeds */
+ ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
+ for( cur = addr_list; cur != NULL; cur = cur->ai_next )
+ {
+ ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
+ cur->ai_protocol );
+ if( ctx->fd < 0 )
+ {
+ ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
+ continue;
+ }
+
+ if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 )
+ {
+ ret = 0;
+ break;
+ }
+
+ close( ctx->fd );
+ ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
+ }
+
+ freeaddrinfo( addr_list );
+
+ return( ret );
+}
+
+/*
+ * Create a listening socket on bind_ip:port
+ */
+int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto )
+{
+ int n, ret;
+ struct addrinfo hints, *addr_list, *cur;
+
+ if( ( ret = net_prepare() ) != 0 )
+ return( ret );
+
+ /* Bind to IPv6 and/or IPv4, but only in the desired protocol */
+ memset( &hints, 0, sizeof( hints ) );
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
+ hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
+ if( bind_ip == NULL )
+ hints.ai_flags = AI_PASSIVE;
+
+ if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 )
+ return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
+
+ /* Try the sockaddrs until a binding succeeds */
+ ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
+ for( cur = addr_list; cur != NULL; cur = cur->ai_next )
+ {
+ ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
+ cur->ai_protocol );
+ if( ctx->fd < 0 )
+ {
+ ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
+ continue;
+ }
+
+ n = 1;
+ if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR,
+ (const char *) &n, sizeof( n ) ) != 0 )
+ {
+ close( ctx->fd );
+ ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
+ continue;
+ }
+
+ if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 )
+ {
+ close( ctx->fd );
+ ret = MBEDTLS_ERR_NET_BIND_FAILED;
+ continue;
+ }
+
+ /* Listen only makes sense for TCP */
+ if( proto == MBEDTLS_NET_PROTO_TCP )
+ {
+ if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 )
+ {
+ close( ctx->fd );
+ ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
+ continue;
+ }
+ }
+
+ /* I we ever get there, it's a success */
+ ret = 0;
+ break;
+ }
+
+ freeaddrinfo( addr_list );
+
+ return( ret );
+
+}
+
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+ !defined(EFI32)
+/*
+ * Check if the requested operation would be blocking on a non-blocking socket
+ * and thus 'failed' with a negative return value.
+ */
+static int net_would_block( const mbedtls_net_context *ctx )
+{
+ ((void) ctx);
+ return( WSAGetLastError() == WSAEWOULDBLOCK );
+}
+#else
+/*
+ * Check if the requested operation would be blocking on a non-blocking socket
+ * and thus 'failed' with a negative return value.
+ *
+ * Note: on a blocking socket this function always returns 0!
+ */
+static int net_would_block( const mbedtls_net_context *ctx )
+{
+ /*
+ * Never return 'WOULD BLOCK' on a non-blocking socket
+ */
+ if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK )
+ return( 0 );
+
+ switch( errno )
+ {
+#if defined EAGAIN
+ case EAGAIN:
+#endif
+#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ return( 1 );
+ }
+ return( 0 );
+}
+#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
+
+/*
+ * Accept a connection from a remote client
+ */
+int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
+ mbedtls_net_context *client_ctx,
+ void *client_ip, size_t buf_size, size_t *ip_len )
+{
+ int ret;
+ int type;
+
+ struct sockaddr_storage client_addr;
+
+#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \
+ defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t)
+ socklen_t n = (socklen_t) sizeof( client_addr );
+ socklen_t type_len = (socklen_t) sizeof( type );
+#else
+ int n = (int) sizeof( client_addr );
+ int type_len = (int) sizeof( type );
+#endif
+
+ /* Is this a TCP or UDP socket? */
+ if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE,
+ (void *) &type, &type_len ) != 0 ||
+ ( type != SOCK_STREAM && type != SOCK_DGRAM ) )
+ {
+ return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
+ }
+
+ if( type == SOCK_STREAM )
+ {
+ /* TCP: actual accept() */
+ ret = client_ctx->fd = (int) accept( bind_ctx->fd,
+ (struct sockaddr *) &client_addr, &n );
+ }
+ else
+ {
+ /* UDP: wait for a message, but keep it in the queue */
+ char buf[1] = { 0 };
+
+ ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
+ (struct sockaddr *) &client_addr, &n );
+
+#if defined(_WIN32)
+ if( ret == SOCKET_ERROR &&
+ WSAGetLastError() == WSAEMSGSIZE )
+ {
+ /* We know buf is too small, thanks, just peeking here */
+ ret = 0;
+ }
+#endif
+ }
+
+ if( ret < 0 )
+ {
+ if( net_would_block( bind_ctx ) != 0 )
+ return( MBEDTLS_ERR_SSL_WANT_READ );
+
+ return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
+ }
+
+ /* UDP: hijack the listening socket to communicate with the client,
+ * then bind a new socket to accept new connections */
+ if( type != SOCK_STREAM )
+ {
+ struct sockaddr_storage local_addr;
+ int one = 1;
+
+ if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 )
+ return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
+
+ client_ctx->fd = bind_ctx->fd;
+ bind_ctx->fd = -1; /* In case we exit early */
+
+ n = sizeof( struct sockaddr_storage );
+ if( getsockname( client_ctx->fd,
+ (struct sockaddr *) &local_addr, &n ) != 0 ||
+ ( bind_ctx->fd = (int) socket( local_addr.ss_family,
+ SOCK_DGRAM, IPPROTO_UDP ) ) < 0 ||
+ setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,
+ (const char *) &one, sizeof( one ) ) != 0 )
+ {
+ return( MBEDTLS_ERR_NET_SOCKET_FAILED );
+ }
+
+ if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 )
+ {
+ return( MBEDTLS_ERR_NET_BIND_FAILED );
+ }
+ }
+
+ if( client_ip != NULL )
+ {
+ if( client_addr.ss_family == AF_INET )
+ {
+ struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
+ *ip_len = sizeof( addr4->sin_addr.s_addr );
+
+ if( buf_size < *ip_len )
+ return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
+
+ memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len );
+ }
+ else
+ {
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
+ *ip_len = sizeof( addr6->sin6_addr.s6_addr );
+
+ if( buf_size < *ip_len )
+ return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
+
+ memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len);
+ }
+ }
+
+ return( 0 );
+}
+
+/*
+ * Set the socket blocking or non-blocking
+ */
+int mbedtls_net_set_block( mbedtls_net_context *ctx )
+{
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+ !defined(EFI32)
+ u_long n = 0;
+ return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
+#else
+ return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) );
+#endif
+}
+
+int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
+{
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+ !defined(EFI32)
+ u_long n = 1;
+ return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
+#else
+ return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) );
+#endif
+}
+
+/*
+ * Portable usleep helper
+ */
+void mbedtls_net_usleep( unsigned long usec )
+{
+#if defined(_WIN32)
+ Sleep( ( usec + 999 ) / 1000 );
+#else
+ struct timeval tv;
+ tv.tv_sec = usec / 1000000;
+#if defined(__unix__) || defined(__unix) || \
+ ( defined(__APPLE__) && defined(__MACH__) )
+ tv.tv_usec = (suseconds_t) usec % 1000000;
+#else
+ tv.tv_usec = usec % 1000000;
+#endif
+ select( 0, NULL, NULL, NULL, &tv );
+#endif
+}
+
+/*
+ * Read at most 'len' characters
+ */
+int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
+{
+ int ret;
+ int fd = ((mbedtls_net_context *) ctx)->fd;
+
+ if( fd < 0 )
+ return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+
+ ret = (int) read( fd, buf, len );
+
+ if( ret < 0 )
+ {
+ if( net_would_block( ctx ) != 0 )
+ return( MBEDTLS_ERR_SSL_WANT_READ );
+
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+ !defined(EFI32)
+ if( WSAGetLastError() == WSAECONNRESET )
+ return( MBEDTLS_ERR_NET_CONN_RESET );
+#else
+ if( errno == EPIPE || errno == ECONNRESET )
+ return( MBEDTLS_ERR_NET_CONN_RESET );
+
+ if( errno == EINTR )
+ return( MBEDTLS_ERR_SSL_WANT_READ );
+#endif
+
+ return( MBEDTLS_ERR_NET_RECV_FAILED );
+ }
+
+ return( ret );
+}
+
+/*
+ * Read at most 'len' characters, blocking for at most 'timeout' ms
+ */
+int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
+ uint32_t timeout )
+{
+ int ret;
+ struct timeval tv;
+ fd_set read_fds;
+ int fd = ((mbedtls_net_context *) ctx)->fd;
+
+ if( fd < 0 )
+ return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+
+ FD_ZERO( &read_fds );
+ FD_SET( fd, &read_fds );
+
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = ( timeout % 1000 ) * 1000;
+
+ ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv );
+
+ /* Zero fds ready means we timed out */
+ if( ret == 0 )
+ return( MBEDTLS_ERR_SSL_TIMEOUT );
+
+ if( ret < 0 )
+ {
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+ !defined(EFI32)
+ if( WSAGetLastError() == WSAEINTR )
+ return( MBEDTLS_ERR_SSL_WANT_READ );
+#else
+ if( errno == EINTR )
+ return( MBEDTLS_ERR_SSL_WANT_READ );
+#endif
+
+ return( MBEDTLS_ERR_NET_RECV_FAILED );
+ }
+
+ /* This call will not block */
+ return( mbedtls_net_recv( ctx, buf, len ) );
+}
+
+/*
+ * Write at most 'len' characters
+ */
+int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
+{
+ int ret;
+ int fd = ((mbedtls_net_context *) ctx)->fd;
+
+ if( fd < 0 )
+ return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+
+ ret = (int) write( fd, buf, len );
+
+ if( ret < 0 )
+ {
+ if( net_would_block( ctx ) != 0 )
+ return( MBEDTLS_ERR_SSL_WANT_WRITE );
+
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+ !defined(EFI32)
+ if( WSAGetLastError() == WSAECONNRESET )
+ return( MBEDTLS_ERR_NET_CONN_RESET );
+#else
+ if( errno == EPIPE || errno == ECONNRESET )
+ return( MBEDTLS_ERR_NET_CONN_RESET );
+
+ if( errno == EINTR )
+ return( MBEDTLS_ERR_SSL_WANT_WRITE );
+#endif
+
+ return( MBEDTLS_ERR_NET_SEND_FAILED );
+ }
+
+ return( ret );
+}
+
+/*
+ * Gracefully close the connection
+ */
+void mbedtls_net_free( mbedtls_net_context *ctx )
+{
+ if( ctx->fd == -1 )
+ return;
+
+ shutdown( ctx->fd, 2 );
+ close( ctx->fd );
+
+ ctx->fd = -1;
+}
+
+#endif /* MBEDTLS_NET_C */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/crypto/mbedtls/src/oid.c
----------------------------------------------------------------------
diff --git a/crypto/mbedtls/src/oid.c b/crypto/mbedtls/src/oid.c
new file mode 100644
index 0000000..c71cd9b
--- /dev/null
+++ b/crypto/mbedtls/src/oid.c
@@ -0,0 +1,650 @@
+/**
+ * \file oid.c
+ *
+ * \brief Object Identifier (OID) database
+ *
+ * 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_OID_C)
+
+#include "mbedtls/oid.h"
+#include "mbedtls/rsa.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#define mbedtls_snprintf snprintf
+#endif
+
+#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
+#include "mbedtls/x509.h"
+#endif
+
+/*
+ * Macro to automatically add the size of #define'd OIDs
+ */
+#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s)
+
+/*
+ * Macro to generate an internal function for oid_XXX_from_asn1() (used by
+ * the other functions)
+ */
+#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \
+static const TYPE_T * oid_ ## NAME ## _from_asn1( const mbedtls_asn1_buf *oid ) \
+{ \
+ const TYPE_T *p = LIST; \
+ const mbedtls_oid_descriptor_t *cur = (const mbedtls_oid_descriptor_t *) p; \
+ if( p == NULL || oid == NULL ) return( NULL ); \
+ while( cur->asn1 != NULL ) { \
+ if( cur->asn1_len == oid->len && \
+ memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \
+ return( p ); \
+ } \
+ p++; \
+ cur = (const mbedtls_oid_descriptor_t *) p; \
+ } \
+ return( NULL ); \
+}
+
+/*
+ * Macro to generate a function for retrieving a single attribute from the
+ * descriptor of an mbedtls_oid_descriptor_t wrapper.
+ */
+#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \
+int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \
+{ \
+ const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \
+ if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \
+ *ATTR1 = data->descriptor.ATTR1; \
+ return( 0 ); \
+}
+
+/*
+ * Macro to generate a function for retrieving a single attribute from an
+ * mbedtls_oid_descriptor_t wrapper.
+ */
+#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \
+int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \
+{ \
+ const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \
+ if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \
+ *ATTR1 = data->ATTR1; \
+ return( 0 ); \
+}
+
+/*
+ * Macro to generate a function for retrieving two attributes from an
+ * mbedtls_oid_descriptor_t wrapper.
+ */
+#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \
+ ATTR2_TYPE, ATTR2) \
+int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, ATTR2_TYPE * ATTR2 ) \
+{ \
+ const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \
+ if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \
+ *ATTR1 = data->ATTR1; \
+ *ATTR2 = data->ATTR2; \
+ return( 0 ); \
+}
+
+/*
+ * Macro to generate a function for retrieving the OID based on a single
+ * attribute from a mbedtls_oid_descriptor_t wrapper.
+ */
+#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \
+int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \
+{ \
+ const TYPE_T *cur = LIST; \
+ while( cur->descriptor.asn1 != NULL ) { \
+ if( cur->ATTR1 == ATTR1 ) { \
+ *oid = cur->descriptor.asn1; \
+ *olen = cur->descriptor.asn1_len; \
+ return( 0 ); \
+ } \
+ cur++; \
+ } \
+ return( MBEDTLS_ERR_OID_NOT_FOUND ); \
+}
+
+/*
+ * Macro to generate a function for retrieving the OID based on two
+ * attributes from a mbedtls_oid_descriptor_t wrapper.
+ */
+#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \
+ ATTR2_TYPE, ATTR2) \
+int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \
+ size_t *olen ) \
+{ \
+ const TYPE_T *cur = LIST; \
+ while( cur->descriptor.asn1 != NULL ) { \
+ if( cur->ATTR1 == ATTR1 && cur->ATTR2 == ATTR2 ) { \
+ *oid = cur->descriptor.asn1; \
+ *olen = cur->descriptor.asn1_len; \
+ return( 0 ); \
+ } \
+ cur++; \
+ } \
+ return( MBEDTLS_ERR_OID_NOT_FOUND ); \
+}
+
+/*
+ * For X520 attribute types
+ */
+typedef struct {
+ mbedtls_oid_descriptor_t descriptor;
+ const char *short_name;
+} oid_x520_attr_t;
+
+static const oid_x520_attr_t oid_x520_attr_type[] =
+{
+ {
+ { ADD_LEN( MBEDTLS_OID_AT_CN ), "id-at-commonName", "Common Name" },
+ "CN",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_AT_COUNTRY ), "id-at-countryName", "Country" },
+ "C",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_AT_LOCALITY ), "id-at-locality", "Locality" },
+ "L",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_AT_STATE ), "id-at-state", "State" },
+ "ST",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_AT_ORGANIZATION ),"id-at-organizationName", "Organization" },
+ "O",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_AT_ORG_UNIT ), "id-at-organizationalUnitName", "Org Unit" },
+ "OU",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_PKCS9_EMAIL ), "emailAddress", "E-mail address" },
+ "emailAddress",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_AT_SERIAL_NUMBER ),"id-at-serialNumber", "Serial number" },
+ "serialNumber",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress", "Postal address" },
+ "postalAddress",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_AT_POSTAL_CODE ), "id-at-postalCode", "Postal code" },
+ "postalCode",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_AT_SUR_NAME ), "id-at-surName", "Surname" },
+ "SN",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_AT_GIVEN_NAME ), "id-at-givenName", "Given name" },
+ "GN",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_AT_INITIALS ), "id-at-initials", "Initials" },
+ "initials",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" },
+ "generationQualifier",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_AT_TITLE ), "id-at-title", "Title" },
+ "title",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_AT_DN_QUALIFIER ),"id-at-dnQualifier", "Distinguished Name qualifier" },
+ "dnQualifier",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_AT_PSEUDONYM ), "id-at-pseudonym", "Pseudonym" },
+ "pseudonym",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_DOMAIN_COMPONENT ), "id-domainComponent", "Domain component" },
+ "DC",
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_AT_UNIQUE_IDENTIFIER ), "id-at-uniqueIdentifier", "Unique Identifier" },
+ "uniqueIdentifier",
+ },
+ {
+ { NULL, 0, NULL, NULL },
+ NULL,
+ }
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type)
+FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name)
+
+#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
+/*
+ * For X509 extensions
+ */
+typedef struct {
+ mbedtls_oid_descriptor_t descriptor;
+ int ext_type;
+} oid_x509_ext_t;
+
+static const oid_x509_ext_t oid_x509_ext[] =
+{
+ {
+ { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" },
+ MBEDTLS_X509_EXT_BASIC_CONSTRAINTS,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" },
+ MBEDTLS_X509_EXT_KEY_USAGE,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" },
+ MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" },
+ MBEDTLS_X509_EXT_SUBJECT_ALT_NAME,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" },
+ MBEDTLS_X509_EXT_NS_CERT_TYPE,
+ },
+ {
+ { NULL, 0, NULL, NULL },
+ 0,
+ },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext)
+FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type)
+
+static const mbedtls_oid_descriptor_t oid_ext_key_usage[] =
+{
+ { ADD_LEN( MBEDTLS_OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" },
+ { ADD_LEN( MBEDTLS_OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" },
+ { ADD_LEN( MBEDTLS_OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" },
+ { ADD_LEN( MBEDTLS_OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" },
+ { ADD_LEN( MBEDTLS_OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" },
+ { ADD_LEN( MBEDTLS_OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" },
+ { NULL, 0, NULL, NULL },
+};
+
+FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage)
+FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description)
+#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */
+
+#if defined(MBEDTLS_MD_C)
+/*
+ * For SignatureAlgorithmIdentifier
+ */
+typedef struct {
+ mbedtls_oid_descriptor_t descriptor;
+ mbedtls_md_type_t md_alg;
+ mbedtls_pk_type_t pk_alg;
+} oid_sig_alg_t;
+
+static const oid_sig_alg_t oid_sig_alg[] =
+{
+ {
+ { ADD_LEN( MBEDTLS_OID_PKCS1_MD2 ), "md2WithRSAEncryption", "RSA with MD2" },
+ MBEDTLS_MD_MD2, MBEDTLS_PK_RSA,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_PKCS1_MD4 ), "md4WithRSAEncryption", "RSA with MD4" },
+ MBEDTLS_MD_MD4, MBEDTLS_PK_RSA,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_PKCS1_MD5 ), "md5WithRSAEncryption", "RSA with MD5" },
+ MBEDTLS_MD_MD5, MBEDTLS_PK_RSA,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_PKCS1_SHA1 ), "sha-1WithRSAEncryption", "RSA with SHA1" },
+ MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_PKCS1_SHA224 ), "sha224WithRSAEncryption", "RSA with SHA-224" },
+ MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_PKCS1_SHA256 ), "sha256WithRSAEncryption", "RSA with SHA-256" },
+ MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_PKCS1_SHA384 ), "sha384WithRSAEncryption", "RSA with SHA-384" },
+ MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_PKCS1_SHA512 ), "sha512WithRSAEncryption", "RSA with SHA-512" },
+ MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_RSA_SHA_OBS ), "sha-1WithRSAEncryption", "RSA with SHA1" },
+ MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_ECDSA_SHA1 ), "ecdsa-with-SHA1", "ECDSA with SHA1" },
+ MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_ECDSA_SHA224 ), "ecdsa-with-SHA224", "ECDSA with SHA224" },
+ MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_ECDSA_SHA256 ), "ecdsa-with-SHA256", "ECDSA with SHA256" },
+ MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_ECDSA_SHA384 ), "ecdsa-with-SHA384", "ECDSA with SHA384" },
+ MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_ECDSA_SHA512 ), "ecdsa-with-SHA512", "ECDSA with SHA512" },
+ MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_RSASSA_PSS ), "RSASSA-PSS", "RSASSA-PSS" },
+ MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS,
+ },
+ {
+ { NULL, 0, NULL, NULL },
+ MBEDTLS_MD_NONE, MBEDTLS_PK_NONE,
+ },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg)
+FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description)
+FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg)
+FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedtls_pk_type_t, pk_alg, mbedtls_md_type_t, md_alg)
+#endif /* MBEDTLS_MD_C */
+
+/*
+ * For PublicKeyInfo (PKCS1, RFC 5480)
+ */
+typedef struct {
+ mbedtls_oid_descriptor_t descriptor;
+ mbedtls_pk_type_t pk_alg;
+} oid_pk_alg_t;
+
+static const oid_pk_alg_t oid_pk_alg[] =
+{
+ {
+ { ADD_LEN( MBEDTLS_OID_PKCS1_RSA ), "rsaEncryption", "RSA" },
+ MBEDTLS_PK_RSA,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_EC_ALG_UNRESTRICTED ), "id-ecPublicKey", "Generic EC key" },
+ MBEDTLS_PK_ECKEY,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_EC_ALG_ECDH ), "id-ecDH", "EC key for ECDH" },
+ MBEDTLS_PK_ECKEY_DH,
+ },
+ {
+ { NULL, 0, NULL, NULL },
+ MBEDTLS_PK_NONE,
+ },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg)
+FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg)
+FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg)
+
+#if defined(MBEDTLS_ECP_C)
+/*
+ * For namedCurve (RFC 5480)
+ */
+typedef struct {
+ mbedtls_oid_descriptor_t descriptor;
+ mbedtls_ecp_group_id grp_id;
+} oid_ecp_grp_t;
+
+static const oid_ecp_grp_t oid_ecp_grp[] =
+{
+ {
+ { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192R1 ), "secp192r1", "secp192r1" },
+ MBEDTLS_ECP_DP_SECP192R1,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224R1 ), "secp224r1", "secp224r1" },
+ MBEDTLS_ECP_DP_SECP224R1,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256R1 ), "secp256r1", "secp256r1" },
+ MBEDTLS_ECP_DP_SECP256R1,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP384R1 ), "secp384r1", "secp384r1" },
+ MBEDTLS_ECP_DP_SECP384R1,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" },
+ MBEDTLS_ECP_DP_SECP521R1,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" },
+ MBEDTLS_ECP_DP_SECP192K1,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" },
+ MBEDTLS_ECP_DP_SECP224K1,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" },
+ MBEDTLS_ECP_DP_SECP256K1,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" },
+ MBEDTLS_ECP_DP_BP256R1,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_EC_GRP_BP384R1 ), "brainpoolP384r1","brainpool384r1" },
+ MBEDTLS_ECP_DP_BP384R1,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_EC_GRP_BP512R1 ), "brainpoolP512r1","brainpool512r1" },
+ MBEDTLS_ECP_DP_BP512R1,
+ },
+ {
+ { NULL, 0, NULL, NULL },
+ MBEDTLS_ECP_DP_NONE,
+ },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp)
+FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id)
+FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id)
+#endif /* MBEDTLS_ECP_C */
+
+#if defined(MBEDTLS_CIPHER_C)
+/*
+ * For PKCS#5 PBES2 encryption algorithm
+ */
+typedef struct {
+ mbedtls_oid_descriptor_t descriptor;
+ mbedtls_cipher_type_t cipher_alg;
+} oid_cipher_alg_t;
+
+static const oid_cipher_alg_t oid_cipher_alg[] =
+{
+ {
+ { ADD_LEN( MBEDTLS_OID_DES_CBC ), "desCBC", "DES-CBC" },
+ MBEDTLS_CIPHER_DES_CBC,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_DES_EDE3_CBC ), "des-ede3-cbc", "DES-EDE3-CBC" },
+ MBEDTLS_CIPHER_DES_EDE3_CBC,
+ },
+ {
+ { NULL, 0, NULL, NULL },
+ MBEDTLS_CIPHER_NONE,
+ },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg)
+FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg)
+#endif /* MBEDTLS_CIPHER_C */
+
+#if defined(MBEDTLS_MD_C)
+/*
+ * For digestAlgorithm
+ */
+typedef struct {
+ mbedtls_oid_descriptor_t descriptor;
+ mbedtls_md_type_t md_alg;
+} oid_md_alg_t;
+
+static const oid_md_alg_t oid_md_alg[] =
+{
+ {
+ { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD2 ), "id-md2", "MD2" },
+ MBEDTLS_MD_MD2,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD4 ), "id-md4", "MD4" },
+ MBEDTLS_MD_MD4,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD5 ), "id-md5", "MD5" },
+ MBEDTLS_MD_MD5,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA1 ), "id-sha1", "SHA-1" },
+ MBEDTLS_MD_SHA1,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA224 ), "id-sha224", "SHA-224" },
+ MBEDTLS_MD_SHA224,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA256 ), "id-sha256", "SHA-256" },
+ MBEDTLS_MD_SHA256,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA384 ), "id-sha384", "SHA-384" },
+ MBEDTLS_MD_SHA384,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA512 ), "id-sha512", "SHA-512" },
+ MBEDTLS_MD_SHA512,
+ },
+ {
+ { NULL, 0, NULL, NULL },
+ MBEDTLS_MD_NONE,
+ },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg)
+FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg)
+FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg)
+#endif /* MBEDTLS_MD_C */
+
+#if defined(MBEDTLS_PKCS12_C)
+/*
+ * For PKCS#12 PBEs
+ */
+typedef struct {
+ mbedtls_oid_descriptor_t descriptor;
+ mbedtls_md_type_t md_alg;
+ mbedtls_cipher_type_t cipher_alg;
+} oid_pkcs12_pbe_alg_t;
+
+static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] =
+{
+ {
+ { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" },
+ MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" },
+ MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC,
+ },
+ {
+ { NULL, 0, NULL, NULL },
+ MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE,
+ },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg)
+FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, mbedtls_cipher_type_t, cipher_alg)
+#endif /* MBEDTLS_PKCS12_C */
+
+#define OID_SAFE_SNPRINTF \
+ do { \
+ if( ret < 0 || (size_t) ret >= n ) \
+ return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); \
+ \
+ n -= (size_t) ret; \
+ p += (size_t) ret; \
+ } while( 0 )
+
+/* Return the x.y.z.... style numeric string for the given OID */
+int mbedtls_oid_get_numeric_string( char *buf, size_t size,
+ const mbedtls_asn1_buf *oid )
+{
+ int ret;
+ size_t i, n;
+ unsigned int value;
+ char *p;
+
+ p = buf;
+ n = size;
+
+ /* First byte contains first two dots */
+ if( oid->len > 0 )
+ {
+ ret = mbedtls_snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 );
+ OID_SAFE_SNPRINTF;
+ }
+
+ value = 0;
+ for( i = 1; i < oid->len; i++ )
+ {
+ /* Prevent overflow in value. */
+ if( ( ( value << 7 ) >> 7 ) != value )
+ return( MBEDTLS_ERR_OID_BUF_TOO_SMALL );
+
+ value <<= 7;
+ value += oid->p[i] & 0x7F;
+
+ if( !( oid->p[i] & 0x80 ) )
+ {
+ /* Last byte */
+ ret = mbedtls_snprintf( p, n, ".%d", value );
+ OID_SAFE_SNPRINTF;
+ value = 0;
+ }
+ }
+
+ return( (int) ( size - n ) );
+}
+
+#endif /* MBEDTLS_OID_C */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/crypto/mbedtls/src/padlock.c
----------------------------------------------------------------------
diff --git a/crypto/mbedtls/src/padlock.c b/crypto/mbedtls/src/padlock.c
new file mode 100644
index 0000000..b85ff9c
--- /dev/null
+++ b/crypto/mbedtls/src/padlock.c
@@ -0,0 +1,170 @@
+/*
+ * VIA PadLock support functions
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+/*
+ * This implementation is based on the VIA PadLock Programming Guide:
+ *
+ * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/
+ * programming_guide.pdf
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PADLOCK_C)
+
+#include "mbedtls/padlock.h"
+
+#include <string.h>
+
+#ifndef asm
+#define asm __asm
+#endif
+
+#if defined(MBEDTLS_HAVE_X86)
+
+/*
+ * PadLock detection routine
+ */
+int mbedtls_padlock_has_support( int feature )
+{
+ static int flags = -1;
+ int ebx = 0, edx = 0;
+
+ if( flags == -1 )
+ {
+ asm( "movl %%ebx, %0 \n\t"
+ "movl $0xC0000000, %%eax \n\t"
+ "cpuid \n\t"
+ "cmpl $0xC0000001, %%eax \n\t"
+ "movl $0, %%edx \n\t"
+ "jb unsupported \n\t"
+ "movl $0xC0000001, %%eax \n\t"
+ "cpuid \n\t"
+ "unsupported: \n\t"
+ "movl %%edx, %1 \n\t"
+ "movl %2, %%ebx \n\t"
+ : "=m" (ebx), "=m" (edx)
+ : "m" (ebx)
+ : "eax", "ecx", "edx" );
+
+ flags = edx;
+ }
+
+ return( flags & feature );
+}
+
+/*
+ * PadLock AES-ECB block en(de)cryption
+ */
+int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx,
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] )
+{
+ int ebx = 0;
+ uint32_t *rk;
+ uint32_t *blk;
+ uint32_t *ctrl;
+ unsigned char buf[256];
+
+ rk = ctx->rk;
+ blk = MBEDTLS_PADLOCK_ALIGN16( buf );
+ memcpy( blk, input, 16 );
+
+ ctrl = blk + 4;
+ *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 );
+
+ asm( "pushfl \n\t"
+ "popfl \n\t"
+ "movl %%ebx, %0 \n\t"
+ "movl $1, %%ecx \n\t"
+ "movl %2, %%edx \n\t"
+ "movl %3, %%ebx \n\t"
+ "movl %4, %%esi \n\t"
+ "movl %4, %%edi \n\t"
+ ".byte 0xf3,0x0f,0xa7,0xc8 \n\t"
+ "movl %1, %%ebx \n\t"
+ : "=m" (ebx)
+ : "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk)
+ : "memory", "ecx", "edx", "esi", "edi" );
+
+ memcpy( output, blk, 16 );
+
+ return( 0 );
+}
+
+/*
+ * PadLock AES-CBC buffer en(de)cryption
+ */
+int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ebx = 0;
+ size_t count;
+ uint32_t *rk;
+ uint32_t *iw;
+ uint32_t *ctrl;
+ unsigned char buf[256];
+
+ if( ( (long) input & 15 ) != 0 ||
+ ( (long) output & 15 ) != 0 )
+ return( MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED );
+
+ rk = ctx->rk;
+ iw = MBEDTLS_PADLOCK_ALIGN16( buf );
+ memcpy( iw, iv, 16 );
+
+ ctrl = iw + 4;
+ *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode ^ 1 ) - 10 ) << 9 );
+
+ count = ( length + 15 ) >> 4;
+
+ asm( "pushfl \n\t"
+ "popfl \n\t"
+ "movl %%ebx, %0 \n\t"
+ "movl %2, %%ecx \n\t"
+ "movl %3, %%edx \n\t"
+ "movl %4, %%ebx \n\t"
+ "movl %5, %%esi \n\t"
+ "movl %6, %%edi \n\t"
+ "movl %7, %%eax \n\t"
+ ".byte 0xf3,0x0f,0xa7,0xd0 \n\t"
+ "movl %1, %%ebx \n\t"
+ : "=m" (ebx)
+ : "m" (ebx), "m" (count), "m" (ctrl),
+ "m" (rk), "m" (input), "m" (output), "m" (iw)
+ : "memory", "eax", "ecx", "edx", "esi", "edi" );
+
+ memcpy( iv, iw, 16 );
+
+ return( 0 );
+}
+
+#endif /* MBEDTLS_HAVE_X86 */
+
+#endif /* MBEDTLS_PADLOCK_C */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0216c73e/crypto/mbedtls/src/pem.c
----------------------------------------------------------------------
diff --git a/crypto/mbedtls/src/pem.c b/crypto/mbedtls/src/pem.c
new file mode 100644
index 0000000..1ee3966
--- /dev/null
+++ b/crypto/mbedtls/src/pem.c
@@ -0,0 +1,447 @@
+/*
+ * Privacy Enhanced Mail (PEM) decoding
+ *
+ * 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_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
+
+#include "mbedtls/pem.h"
+#include "mbedtls/base64.h"
+#include "mbedtls/des.h"
+#include "mbedtls/aes.h"
+#include "mbedtls/md5.h"
+#include "mbedtls/cipher.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
+#endif
+
+/* 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;
+}
+
+#if defined(MBEDTLS_PEM_PARSE_C)
+void mbedtls_pem_init( mbedtls_pem_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedtls_pem_context ) );
+}
+
+#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \
+ ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) )
+/*
+ * Read a 16-byte hex string and convert it to binary
+ */
+static int pem_get_iv( const unsigned char *s, unsigned char *iv,
+ size_t iv_len )
+{
+ size_t i, j, k;
+
+ memset( iv, 0, iv_len );
+
+ for( i = 0; i < iv_len * 2; i++, s++ )
+ {
+ if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
+ if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
+ if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
+ return( MBEDTLS_ERR_PEM_INVALID_ENC_IV );
+
+ k = ( ( i & 1 ) != 0 ) ? j : j << 4;
+
+ iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
+ }
+
+ return( 0 );
+}
+
+static void pem_pbkdf1( unsigned char *key, size_t keylen,
+ unsigned char *iv,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ mbedtls_md5_context md5_ctx;
+ unsigned char md5sum[16];
+ size_t use_len;
+
+ mbedtls_md5_init( &md5_ctx );
+
+ /*
+ * key[ 0..15] = MD5(pwd || IV)
+ */
+ mbedtls_md5_starts( &md5_ctx );
+ mbedtls_md5_update( &md5_ctx, pwd, pwdlen );
+ mbedtls_md5_update( &md5_ctx, iv, 8 );
+ mbedtls_md5_finish( &md5_ctx, md5sum );
+
+ if( keylen <= 16 )
+ {
+ memcpy( key, md5sum, keylen );
+
+ mbedtls_md5_free( &md5_ctx );
+ mbedtls_zeroize( md5sum, 16 );
+ return;
+ }
+
+ memcpy( key, md5sum, 16 );
+
+ /*
+ * key[16..23] = MD5(key[ 0..15] || pwd || IV])
+ */
+ mbedtls_md5_starts( &md5_ctx );
+ mbedtls_md5_update( &md5_ctx, md5sum, 16 );
+ mbedtls_md5_update( &md5_ctx, pwd, pwdlen );
+ mbedtls_md5_update( &md5_ctx, iv, 8 );
+ mbedtls_md5_finish( &md5_ctx, md5sum );
+
+ use_len = 16;
+ if( keylen < 32 )
+ use_len = keylen - 16;
+
+ memcpy( key + 16, md5sum, use_len );
+
+ mbedtls_md5_free( &md5_ctx );
+ mbedtls_zeroize( md5sum, 16 );
+}
+
+#if defined(MBEDTLS_DES_C)
+/*
+ * Decrypt with DES-CBC, using PBKDF1 for key derivation
+ */
+static void pem_des_decrypt( unsigned char des_iv[8],
+ unsigned char *buf, size_t buflen,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ mbedtls_des_context des_ctx;
+ unsigned char des_key[8];
+
+ mbedtls_des_init( &des_ctx );
+
+ pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen );
+
+ mbedtls_des_setkey_dec( &des_ctx, des_key );
+ mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen,
+ des_iv, buf, buf );
+
+ mbedtls_des_free( &des_ctx );
+ mbedtls_zeroize( des_key, 8 );
+}
+
+/*
+ * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
+ */
+static void pem_des3_decrypt( unsigned char des3_iv[8],
+ unsigned char *buf, size_t buflen,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ mbedtls_des3_context des3_ctx;
+ unsigned char des3_key[24];
+
+ mbedtls_des3_init( &des3_ctx );
+
+ pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen );
+
+ mbedtls_des3_set3key_dec( &des3_ctx, des3_key );
+ mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen,
+ des3_iv, buf, buf );
+
+ mbedtls_des3_free( &des3_ctx );
+ mbedtls_zeroize( des3_key, 24 );
+}
+#endif /* MBEDTLS_DES_C */
+
+#if defined(MBEDTLS_AES_C)
+/*
+ * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation
+ */
+static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
+ unsigned char *buf, size_t buflen,
+ const unsigned char *pwd, size_t pwdlen )
+{
+ mbedtls_aes_context aes_ctx;
+ unsigned char aes_key[32];
+
+ mbedtls_aes_init( &aes_ctx );
+
+ pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen );
+
+ mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 );
+ mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen,
+ aes_iv, buf, buf );
+
+ mbedtls_aes_free( &aes_ctx );
+ mbedtls_zeroize( aes_key, keylen );
+}
+#endif /* MBEDTLS_AES_C */
+
+#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
+ ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
+
+int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer,
+ const unsigned char *data, const unsigned char *pwd,
+ size_t pwdlen, size_t *use_len )
+{
+ int ret, enc;
+ size_t len;
+ unsigned char *buf;
+ const unsigned char *s1, *s2, *end;
+#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \
+ ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) )
+ unsigned char pem_iv[16];
+ mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE;
+#else
+ ((void) pwd);
+ ((void) pwdlen);
+#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
+ ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
+
+ if( ctx == NULL )
+ return( MBEDTLS_ERR_PEM_BAD_INPUT_DATA );
+
+ s1 = (unsigned char *) strstr( (const char *) data, header );
+
+ if( s1 == NULL )
+ return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
+
+ s2 = (unsigned char *) strstr( (const char *) data, footer );
+
+ if( s2 == NULL || s2 <= s1 )
+ return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
+
+ s1 += strlen( header );
+ if( *s1 == ' ' ) s1++;
+ if( *s1 == '\r' ) s1++;
+ if( *s1 == '\n' ) s1++;
+ else return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
+
+ end = s2;
+ end += strlen( footer );
+ if( *end == ' ' ) end++;
+ if( *end == '\r' ) end++;
+ if( *end == '\n' ) end++;
+ *use_len = end - data;
+
+ enc = 0;
+
+ if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
+ {
+#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \
+ ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) )
+ enc++;
+
+ s1 += 22;
+ if( *s1 == '\r' ) s1++;
+ if( *s1 == '\n' ) s1++;
+ else return( MBEDTLS_ERR_PEM_INVALID_DATA );
+
+
+#if defined(MBEDTLS_DES_C)
+ if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 )
+ {
+ enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC;
+
+ s1 += 23;
+ if( pem_get_iv( s1, pem_iv, 8 ) != 0 )
+ return( MBEDTLS_ERR_PEM_INVALID_ENC_IV );
+
+ s1 += 16;
+ }
+ else if( memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 )
+ {
+ enc_alg = MBEDTLS_CIPHER_DES_CBC;
+
+ s1 += 18;
+ if( pem_get_iv( s1, pem_iv, 8) != 0 )
+ return( MBEDTLS_ERR_PEM_INVALID_ENC_IV );
+
+ s1 += 16;
+ }
+#endif /* MBEDTLS_DES_C */
+
+#if defined(MBEDTLS_AES_C)
+ if( memcmp( s1, "DEK-Info: AES-", 14 ) == 0 )
+ {
+ if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 )
+ enc_alg = MBEDTLS_CIPHER_AES_128_CBC;
+ else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 )
+ enc_alg = MBEDTLS_CIPHER_AES_192_CBC;
+ else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 )
+ enc_alg = MBEDTLS_CIPHER_AES_256_CBC;
+ else
+ return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG );
+
+ s1 += 22;
+ if( pem_get_iv( s1, pem_iv, 16 ) != 0 )
+ return( MBEDTLS_ERR_PEM_INVALID_ENC_IV );
+
+ s1 += 32;
+ }
+#endif /* MBEDTLS_AES_C */
+
+ if( enc_alg == MBEDTLS_CIPHER_NONE )
+ return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG );
+
+ if( *s1 == '\r' ) s1++;
+ if( *s1 == '\n' ) s1++;
+ else return( MBEDTLS_ERR_PEM_INVALID_DATA );
+#else
+ return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE );
+#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
+ ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
+ }
+
+ if( s1 == s2 )
+ return( MBEDTLS_ERR_PEM_INVALID_DATA );
+
+ ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 );
+
+ if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER )
+ return( MBEDTLS_ERR_PEM_INVALID_DATA + ret );
+
+ if( ( buf = mbedtls_calloc( 1, len ) ) == NULL )
+ return( MBEDTLS_ERR_PEM_ALLOC_FAILED );
+
+ if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 )
+ {
+ mbedtls_free( buf );
+ return( MBEDTLS_ERR_PEM_INVALID_DATA + ret );
+ }
+
+ if( enc != 0 )
+ {
+#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \
+ ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) )
+ if( pwd == NULL )
+ {
+ mbedtls_free( buf );
+ return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED );
+ }
+
+#if defined(MBEDTLS_DES_C)
+ if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC )
+ pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen );
+ else if( enc_alg == MBEDTLS_CIPHER_DES_CBC )
+ pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen );
+#endif /* MBEDTLS_DES_C */
+
+#if defined(MBEDTLS_AES_C)
+ if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC )
+ pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen );
+ else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC )
+ pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen );
+ else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC )
+ pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen );
+#endif /* MBEDTLS_AES_C */
+
+ /*
+ * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3
+ * length bytes (allow 4 to be sure) in all known use cases.
+ *
+ * Use that as heurisitic to try detecting password mismatchs.
+ */
+ if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 )
+ {
+ mbedtls_free( buf );
+ return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH );
+ }
+#else
+ mbedtls_free( buf );
+ return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE );
+#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
+ ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
+ }
+
+ ctx->buf = buf;
+ ctx->buflen = len;
+
+ return( 0 );
+}
+
+void mbedtls_pem_free( mbedtls_pem_context *ctx )
+{
+ mbedtls_free( ctx->buf );
+ mbedtls_free( ctx->info );
+
+ mbedtls_zeroize( ctx, sizeof( mbedtls_pem_context ) );
+}
+#endif /* MBEDTLS_PEM_PARSE_C */
+
+#if defined(MBEDTLS_PEM_WRITE_C)
+int mbedtls_pem_write_buffer( const char *header, const char *footer,
+ const unsigned char *der_data, size_t der_len,
+ unsigned char *buf, size_t buf_len, size_t *olen )
+{
+ int ret;
+ unsigned char *encode_buf, *c, *p = buf;
+ size_t len = 0, use_len, add_len = 0;
+
+ mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len );
+ add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1;
+
+ if( use_len + add_len > buf_len )
+ {
+ *olen = use_len + add_len;
+ return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
+ }
+
+ if( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL )
+ return( MBEDTLS_ERR_PEM_ALLOC_FAILED );
+
+ if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data,
+ der_len ) ) != 0 )
+ {
+ mbedtls_free( encode_buf );
+ return( ret );
+ }
+
+ memcpy( p, header, strlen( header ) );
+ p += strlen( header );
+ c = encode_buf;
+
+ while( use_len )
+ {
+ len = ( use_len > 64 ) ? 64 : use_len;
+ memcpy( p, c, len );
+ use_len -= len;
+ p += len;
+ c += len;
+ *p++ = '\n';
+ }
+
+ memcpy( p, footer, strlen( footer ) );
+ p += strlen( footer );
+
+ *p++ = '\0';
+ *olen = p - buf;
+
+ mbedtls_free( encode_buf );
+ return( 0 );
+}
+#endif /* MBEDTLS_PEM_WRITE_C */
+#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */