blob: 07bcce0dbe7c3875402eebfff25e64617b84e5aa [file] [log] [blame]
Paul Bakker6e339b52013-07-03 13:37:05 +02001/*
2 * Buffer-based memory allocator
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker6e339b52013-07-03 13:37:05 +020018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker6e339b52013-07-03 13:37:05 +020020 */
21
Gilles Peskinedb09ef62020-06-03 01:43:33 +020022#include "common.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020023
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020024#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000025#include "mbedtls/memory_buffer_alloc.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020026
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020027/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C
28 is dependent upon MBEDTLS_PLATFORM_C */
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000029#include "mbedtls/platform.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050030#include "mbedtls/platform_util.h"
Rich Evansd08a6052015-02-12 12:17:10 +000031
Paul Bakker6e339b52013-07-03 13:37:05 +020032#include <string.h>
33
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020034#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +020035#include <execinfo.h>
36#endif
Paul Bakker6e339b52013-07-03 13:37:05 +020037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/threading.h"
Paul Bakker1337aff2013-09-29 14:45:34 +020040#endif
41
Paul Bakker6e339b52013-07-03 13:37:05 +020042#define MAGIC1 0xFF00AA55
43#define MAGIC2 0xEE119966
44#define MAX_BT 20
45
46typedef struct _memory_header memory_header;
47struct _memory_header
48{
49 size_t magic1;
50 size_t size;
51 size_t alloc;
52 memory_header *prev;
53 memory_header *next;
Paul Bakker1ef120f2013-07-03 17:20:39 +020054 memory_header *prev_free;
55 memory_header *next_free;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +020057 char **trace;
58 size_t trace_count;
59#endif
60 size_t magic2;
61};
62
63typedef struct
64{
65 unsigned char *buf;
66 size_t len;
67 memory_header *first;
Paul Bakker1ef120f2013-07-03 17:20:39 +020068 memory_header *first_free;
Paul Bakker6e339b52013-07-03 13:37:05 +020069 int verify;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020070#if defined(MBEDTLS_MEMORY_DEBUG)
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +020071 size_t alloc_count;
Paul Bakker891998e2013-07-03 14:45:05 +020072 size_t free_count;
73 size_t total_used;
74 size_t maximum_used;
75 size_t header_count;
Manuel Pégourié-Gonnard70896a02013-12-30 18:06:41 +010076 size_t maximum_header_count;
Paul Bakker891998e2013-07-03 14:45:05 +020077#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020078#if defined(MBEDTLS_THREADING_C)
79 mbedtls_threading_mutex_t mutex;
Paul Bakker1337aff2013-09-29 14:45:34 +020080#endif
Paul Bakker6e339b52013-07-03 13:37:05 +020081}
82buffer_alloc_ctx;
83
84static buffer_alloc_ctx heap;
85
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020086#if defined(MBEDTLS_MEMORY_DEBUG)
Paul Bakker6e339b52013-07-03 13:37:05 +020087static void debug_header( memory_header *hdr )
88{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020089#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +020090 size_t i;
91#endif
92
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020093 mbedtls_fprintf( stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), "
Manuel Pégourié-Gonnard97884a32014-07-12 02:27:35 +020094 "ALLOC(%zu), SIZE(%10zu)\n",
Paul Bakker7dc4c442014-02-01 22:50:26 +010095 (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next,
96 hdr->alloc, hdr->size );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020097 mbedtls_fprintf( stderr, " FPREV(%10zu), FNEXT(%10zu)\n",
Paul Bakker7dc4c442014-02-01 22:50:26 +010098 (size_t) hdr->prev_free, (size_t) hdr->next_free );
Paul Bakker6e339b52013-07-03 13:37:05 +020099
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100#if defined(MBEDTLS_MEMORY_BACKTRACE)
101 mbedtls_fprintf( stderr, "TRACE: \n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200102 for( i = 0; i < hdr->trace_count; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200103 mbedtls_fprintf( stderr, "%s\n", hdr->trace[i] );
104 mbedtls_fprintf( stderr, "\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200105#endif
106}
107
Joris Aertse75b88d2016-11-04 23:05:56 +0100108static void debug_chain( void )
Paul Bakker6e339b52013-07-03 13:37:05 +0200109{
110 memory_header *cur = heap.first;
111
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200112 mbedtls_fprintf( stderr, "\nBlock list\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200113 while( cur != NULL )
114 {
115 debug_header( cur );
Paul Bakker6e339b52013-07-03 13:37:05 +0200116 cur = cur->next;
117 }
Paul Bakker1ef120f2013-07-03 17:20:39 +0200118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119 mbedtls_fprintf( stderr, "Free list\n" );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200120 cur = heap.first_free;
121
122 while( cur != NULL )
123 {
124 debug_header( cur );
125 cur = cur->next_free;
126 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200127}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128#endif /* MBEDTLS_MEMORY_DEBUG */
Paul Bakker6e339b52013-07-03 13:37:05 +0200129
130static int verify_header( memory_header *hdr )
131{
132 if( hdr->magic1 != MAGIC1 )
133 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134#if defined(MBEDTLS_MEMORY_DEBUG)
135 mbedtls_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200136#endif
137 return( 1 );
138 }
139
140 if( hdr->magic2 != MAGIC2 )
141 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200142#if defined(MBEDTLS_MEMORY_DEBUG)
143 mbedtls_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200144#endif
145 return( 1 );
146 }
147
148 if( hdr->alloc > 1 )
149 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150#if defined(MBEDTLS_MEMORY_DEBUG)
151 mbedtls_fprintf( stderr, "FATAL: alloc has illegal value\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200152#endif
153 return( 1 );
154 }
155
Paul Bakker1ef120f2013-07-03 17:20:39 +0200156 if( hdr->prev != NULL && hdr->prev == hdr->next )
157 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158#if defined(MBEDTLS_MEMORY_DEBUG)
159 mbedtls_fprintf( stderr, "FATAL: prev == next\n" );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200160#endif
161 return( 1 );
162 }
163
164 if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free )
165 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200166#if defined(MBEDTLS_MEMORY_DEBUG)
167 mbedtls_fprintf( stderr, "FATAL: prev_free == next_free\n" );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200168#endif
169 return( 1 );
170 }
171
Paul Bakker6e339b52013-07-03 13:37:05 +0200172 return( 0 );
173}
174
Joris Aertse75b88d2016-11-04 23:05:56 +0100175static int verify_chain( void )
Paul Bakker6e339b52013-07-03 13:37:05 +0200176{
Andres AG9cf1f962017-01-30 14:34:25 +0000177 memory_header *prv = heap.first, *cur;
Paul Bakker6e339b52013-07-03 13:37:05 +0200178
Andres Amaya Garciaf1ee6352017-07-06 10:06:58 +0100179 if( prv == NULL || verify_header( prv ) != 0 )
Paul Bakker6e339b52013-07-03 13:37:05 +0200180 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181#if defined(MBEDTLS_MEMORY_DEBUG)
182 mbedtls_fprintf( stderr, "FATAL: verification of first header "
Paul Bakker7dc4c442014-02-01 22:50:26 +0100183 "failed\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200184#endif
185 return( 1 );
186 }
187
188 if( heap.first->prev != NULL )
189 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190#if defined(MBEDTLS_MEMORY_DEBUG)
191 mbedtls_fprintf( stderr, "FATAL: verification failed: "
Paul Bakker7dc4c442014-02-01 22:50:26 +0100192 "first->prev != NULL\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200193#endif
194 return( 1 );
195 }
196
Andres AG9cf1f962017-01-30 14:34:25 +0000197 cur = heap.first->next;
198
Paul Bakker6e339b52013-07-03 13:37:05 +0200199 while( cur != NULL )
200 {
201 if( verify_header( cur ) != 0 )
202 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203#if defined(MBEDTLS_MEMORY_DEBUG)
204 mbedtls_fprintf( stderr, "FATAL: verification of header "
Paul Bakker7dc4c442014-02-01 22:50:26 +0100205 "failed\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200206#endif
207 return( 1 );
208 }
209
210 if( cur->prev != prv )
211 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200212#if defined(MBEDTLS_MEMORY_DEBUG)
213 mbedtls_fprintf( stderr, "FATAL: verification failed: "
Paul Bakker7dc4c442014-02-01 22:50:26 +0100214 "cur->prev != prv\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200215#endif
216 return( 1 );
217 }
218
219 prv = cur;
220 cur = cur->next;
221 }
222
223 return( 0 );
224}
225
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200226static void *buffer_alloc_calloc( size_t n, size_t size )
Paul Bakker6e339b52013-07-03 13:37:05 +0200227{
Paul Bakker1ef120f2013-07-03 17:20:39 +0200228 memory_header *new, *cur = heap.first_free;
Paul Bakker6e339b52013-07-03 13:37:05 +0200229 unsigned char *p;
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200230 void *ret;
231 size_t original_len, len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200232#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +0200233 void *trace_buffer[MAX_BT];
234 size_t trace_cnt;
235#endif
236
237 if( heap.buf == NULL || heap.first == NULL )
238 return( NULL );
239
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200240 original_len = len = n * size;
241
Andres AG9cf1f962017-01-30 14:34:25 +0000242 if( n == 0 || size == 0 || len / n != size )
243 return( NULL );
244 else if( len > (size_t)-MBEDTLS_MEMORY_ALIGN_MULTIPLE )
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200245 return( NULL );
246
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247 if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE )
Paul Bakker6e339b52013-07-03 13:37:05 +0200248 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249 len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
250 len += MBEDTLS_MEMORY_ALIGN_MULTIPLE;
Paul Bakker6e339b52013-07-03 13:37:05 +0200251 }
252
253 // Find block that fits
254 //
255 while( cur != NULL )
256 {
Paul Bakker1ef120f2013-07-03 17:20:39 +0200257 if( cur->size >= len )
Paul Bakker6e339b52013-07-03 13:37:05 +0200258 break;
259
Paul Bakker1ef120f2013-07-03 17:20:39 +0200260 cur = cur->next_free;
Paul Bakker6e339b52013-07-03 13:37:05 +0200261 }
262
263 if( cur == NULL )
264 return( NULL );
265
Paul Bakker1ef120f2013-07-03 17:20:39 +0200266 if( cur->alloc != 0 )
267 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268#if defined(MBEDTLS_MEMORY_DEBUG)
269 mbedtls_fprintf( stderr, "FATAL: block in free_list but allocated "
Paul Bakker7dc4c442014-02-01 22:50:26 +0100270 "data\n" );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200271#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200272 mbedtls_exit( 1 );
Paul Bakker1ef120f2013-07-03 17:20:39 +0200273 }
274
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200275#if defined(MBEDTLS_MEMORY_DEBUG)
Manuel Pégourié-Gonnard6c967b92015-05-27 20:18:39 +0200276 heap.alloc_count++;
Paul Bakker891998e2013-07-03 14:45:05 +0200277#endif
278
Paul Bakker6e339b52013-07-03 13:37:05 +0200279 // Found location, split block if > memory_header + 4 room left
280 //
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200281 if( cur->size - len < sizeof(memory_header) +
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200282 MBEDTLS_MEMORY_ALIGN_MULTIPLE )
Paul Bakker6e339b52013-07-03 13:37:05 +0200283 {
284 cur->alloc = 1;
285
Paul Bakker1ef120f2013-07-03 17:20:39 +0200286 // Remove from free_list
287 //
288 if( cur->prev_free != NULL )
289 cur->prev_free->next_free = cur->next_free;
290 else
291 heap.first_free = cur->next_free;
292
293 if( cur->next_free != NULL )
294 cur->next_free->prev_free = cur->prev_free;
295
296 cur->prev_free = NULL;
297 cur->next_free = NULL;
298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299#if defined(MBEDTLS_MEMORY_DEBUG)
Paul Bakker891998e2013-07-03 14:45:05 +0200300 heap.total_used += cur->size;
Paul Bakker66d5d072014-06-17 16:39:18 +0200301 if( heap.total_used > heap.maximum_used )
Paul Bakker891998e2013-07-03 14:45:05 +0200302 heap.maximum_used = heap.total_used;
303#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200304#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +0200305 trace_cnt = backtrace( trace_buffer, MAX_BT );
306 cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
307 cur->trace_count = trace_cnt;
308#endif
309
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200310 if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
311 mbedtls_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200312
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200313 ret = (unsigned char *) cur + sizeof( memory_header );
314 memset( ret, 0, original_len );
315
316 return( ret );
Paul Bakker6e339b52013-07-03 13:37:05 +0200317 }
318
319 p = ( (unsigned char *) cur ) + sizeof(memory_header) + len;
320 new = (memory_header *) p;
321
322 new->size = cur->size - len - sizeof(memory_header);
323 new->alloc = 0;
324 new->prev = cur;
325 new->next = cur->next;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +0200327 new->trace = NULL;
328 new->trace_count = 0;
329#endif
330 new->magic1 = MAGIC1;
331 new->magic2 = MAGIC2;
332
333 if( new->next != NULL )
334 new->next->prev = new;
335
Paul Bakker1ef120f2013-07-03 17:20:39 +0200336 // Replace cur with new in free_list
337 //
338 new->prev_free = cur->prev_free;
339 new->next_free = cur->next_free;
340 if( new->prev_free != NULL )
341 new->prev_free->next_free = new;
342 else
343 heap.first_free = new;
344
345 if( new->next_free != NULL )
346 new->next_free->prev_free = new;
347
Paul Bakker6e339b52013-07-03 13:37:05 +0200348 cur->alloc = 1;
349 cur->size = len;
350 cur->next = new;
Paul Bakker1ef120f2013-07-03 17:20:39 +0200351 cur->prev_free = NULL;
352 cur->next_free = NULL;
Paul Bakker6e339b52013-07-03 13:37:05 +0200353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200354#if defined(MBEDTLS_MEMORY_DEBUG)
Paul Bakker891998e2013-07-03 14:45:05 +0200355 heap.header_count++;
Manuel Pégourié-Gonnard70896a02013-12-30 18:06:41 +0100356 if( heap.header_count > heap.maximum_header_count )
357 heap.maximum_header_count = heap.header_count;
Paul Bakker891998e2013-07-03 14:45:05 +0200358 heap.total_used += cur->size;
Paul Bakker66d5d072014-06-17 16:39:18 +0200359 if( heap.total_used > heap.maximum_used )
Paul Bakker891998e2013-07-03 14:45:05 +0200360 heap.maximum_used = heap.total_used;
361#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200362#if defined(MBEDTLS_MEMORY_BACKTRACE)
Paul Bakker6e339b52013-07-03 13:37:05 +0200363 trace_cnt = backtrace( trace_buffer, MAX_BT );
364 cur->trace = backtrace_symbols( trace_buffer, trace_cnt );
365 cur->trace_count = trace_cnt;
366#endif
367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368 if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
369 mbedtls_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200370
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200371 ret = (unsigned char *) cur + sizeof( memory_header );
372 memset( ret, 0, original_len );
373
374 return( ret );
Paul Bakker6e339b52013-07-03 13:37:05 +0200375}
376
377static void buffer_alloc_free( void *ptr )
378{
Paul Bakker1ef120f2013-07-03 17:20:39 +0200379 memory_header *hdr, *old = NULL;
Paul Bakker6e339b52013-07-03 13:37:05 +0200380 unsigned char *p = (unsigned char *) ptr;
381
Paul Bakker6e339b52013-07-03 13:37:05 +0200382 if( ptr == NULL || heap.buf == NULL || heap.first == NULL )
383 return;
384
Andres AG9cf1f962017-01-30 14:34:25 +0000385 if( p < heap.buf || p >= heap.buf + heap.len )
Paul Bakker6e339b52013-07-03 13:37:05 +0200386 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200387#if defined(MBEDTLS_MEMORY_DEBUG)
388 mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed "
Paul Bakker7dc4c442014-02-01 22:50:26 +0100389 "space\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200390#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200391 mbedtls_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200392 }
393
394 p -= sizeof(memory_header);
395 hdr = (memory_header *) p;
396
397 if( verify_header( hdr ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398 mbedtls_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200399
400 if( hdr->alloc != 1 )
401 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200402#if defined(MBEDTLS_MEMORY_DEBUG)
403 mbedtls_fprintf( stderr, "FATAL: mbedtls_free() on unallocated "
Paul Bakker7dc4c442014-02-01 22:50:26 +0100404 "data\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200405#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406 mbedtls_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200407 }
408
409 hdr->alloc = 0;
410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200411#if defined(MBEDTLS_MEMORY_DEBUG)
Paul Bakker891998e2013-07-03 14:45:05 +0200412 heap.free_count++;
413 heap.total_used -= hdr->size;
414#endif
415
SimonB42256112016-05-02 01:05:22 +0100416#if defined(MBEDTLS_MEMORY_BACKTRACE)
417 free( hdr->trace );
418 hdr->trace = NULL;
419 hdr->trace_count = 0;
420#endif
421
Paul Bakker6e339b52013-07-03 13:37:05 +0200422 // Regroup with block before
423 //
424 if( hdr->prev != NULL && hdr->prev->alloc == 0 )
425 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200426#if defined(MBEDTLS_MEMORY_DEBUG)
Paul Bakker891998e2013-07-03 14:45:05 +0200427 heap.header_count--;
428#endif
Paul Bakker6e339b52013-07-03 13:37:05 +0200429 hdr->prev->size += sizeof(memory_header) + hdr->size;
430 hdr->prev->next = hdr->next;
431 old = hdr;
432 hdr = hdr->prev;
433
434 if( hdr->next != NULL )
435 hdr->next->prev = hdr;
436
Paul Bakker6e339b52013-07-03 13:37:05 +0200437 memset( old, 0, sizeof(memory_header) );
438 }
439
440 // Regroup with block after
441 //
442 if( hdr->next != NULL && hdr->next->alloc == 0 )
443 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200444#if defined(MBEDTLS_MEMORY_DEBUG)
Paul Bakker891998e2013-07-03 14:45:05 +0200445 heap.header_count--;
446#endif
Paul Bakker6e339b52013-07-03 13:37:05 +0200447 hdr->size += sizeof(memory_header) + hdr->next->size;
448 old = hdr->next;
449 hdr->next = hdr->next->next;
450
Paul Bakker1ef120f2013-07-03 17:20:39 +0200451 if( hdr->prev_free != NULL || hdr->next_free != NULL )
452 {
453 if( hdr->prev_free != NULL )
454 hdr->prev_free->next_free = hdr->next_free;
455 else
456 heap.first_free = hdr->next_free;
457
458 if( hdr->next_free != NULL )
459 hdr->next_free->prev_free = hdr->prev_free;
460 }
461
462 hdr->prev_free = old->prev_free;
463 hdr->next_free = old->next_free;
464
465 if( hdr->prev_free != NULL )
466 hdr->prev_free->next_free = hdr;
467 else
468 heap.first_free = hdr;
469
470 if( hdr->next_free != NULL )
471 hdr->next_free->prev_free = hdr;
472
Paul Bakker6e339b52013-07-03 13:37:05 +0200473 if( hdr->next != NULL )
474 hdr->next->prev = hdr;
475
Paul Bakker6e339b52013-07-03 13:37:05 +0200476 memset( old, 0, sizeof(memory_header) );
477 }
478
Paul Bakker1ef120f2013-07-03 17:20:39 +0200479 // Prepend to free_list if we have not merged
480 // (Does not have to stay in same order as prev / next list)
481 //
482 if( old == NULL )
483 {
484 hdr->next_free = heap.first_free;
Manuel Pégourié-Gonnard547ff662014-11-26 15:42:16 +0100485 if( heap.first_free != NULL )
486 heap.first_free->prev_free = hdr;
Paul Bakker1ef120f2013-07-03 17:20:39 +0200487 heap.first_free = hdr;
488 }
489
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490 if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_FREE ) && verify_chain() != 0 )
491 mbedtls_exit( 1 );
Paul Bakker6e339b52013-07-03 13:37:05 +0200492}
493
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200494void mbedtls_memory_buffer_set_verify( int verify )
Paul Bakkerbf796ac2013-09-28 11:06:38 +0200495{
496 heap.verify = verify;
497}
498
Joris Aertse75b88d2016-11-04 23:05:56 +0100499int mbedtls_memory_buffer_alloc_verify( void )
Paul Bakker6e339b52013-07-03 13:37:05 +0200500{
501 return verify_chain();
502}
503
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504#if defined(MBEDTLS_MEMORY_DEBUG)
Joris Aertse75b88d2016-11-04 23:05:56 +0100505void mbedtls_memory_buffer_alloc_status( void )
Paul Bakker6e339b52013-07-03 13:37:05 +0200506{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200507 mbedtls_fprintf( stderr,
Manuel Pégourié-Gonnard97884a32014-07-12 02:27:35 +0200508 "Current use: %zu blocks / %zu bytes, max: %zu blocks / "
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200509 "%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n",
Paul Bakker7dc4c442014-02-01 22:50:26 +0100510 heap.header_count, heap.total_used,
511 heap.maximum_header_count, heap.maximum_used,
512 heap.maximum_header_count * sizeof( memory_header )
513 + heap.maximum_used,
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200514 heap.alloc_count, heap.free_count );
Paul Bakker891998e2013-07-03 14:45:05 +0200515
Paul Bakker6e339b52013-07-03 13:37:05 +0200516 if( heap.first->next == NULL )
Darryl Greenb11de302017-11-27 17:12:14 +0000517 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" );
Darryl Greenb11de302017-11-27 17:12:14 +0000519 }
Paul Bakker6e339b52013-07-03 13:37:05 +0200520 else
521 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 mbedtls_fprintf( stderr, "Memory currently allocated:\n" );
Paul Bakker6e339b52013-07-03 13:37:05 +0200523 debug_chain();
524 }
525}
Manuel Pégourié-Gonnard50da0482014-12-19 12:10:37 +0100526
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks )
Manuel Pégourié-Gonnard50da0482014-12-19 12:10:37 +0100528{
529 *max_used = heap.maximum_used;
530 *max_blocks = heap.maximum_header_count;
531}
532
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533void mbedtls_memory_buffer_alloc_max_reset( void )
Manuel Pégourié-Gonnard50da0482014-12-19 12:10:37 +0100534{
535 heap.maximum_used = 0;
536 heap.maximum_header_count = 0;
537}
538
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200539void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks )
Manuel Pégourié-Gonnard50da0482014-12-19 12:10:37 +0100540{
541 *cur_used = heap.total_used;
542 *cur_blocks = heap.header_count;
543}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200544#endif /* MBEDTLS_MEMORY_DEBUG */
Paul Bakker6e339b52013-07-03 13:37:05 +0200545
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200547static void *buffer_alloc_calloc_mutexed( size_t n, size_t size )
Paul Bakker1337aff2013-09-29 14:45:34 +0200548{
549 void *buf;
Manuel Pégourié-Gonnardbdd78282015-04-24 14:42:53 +0200550 if( mbedtls_mutex_lock( &heap.mutex ) != 0 )
551 return( NULL );
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200552 buf = buffer_alloc_calloc( n, size );
Manuel Pégourié-Gonnardbdd78282015-04-24 14:42:53 +0200553 if( mbedtls_mutex_unlock( &heap.mutex ) )
554 return( NULL );
Paul Bakker1337aff2013-09-29 14:45:34 +0200555 return( buf );
556}
557
558static void buffer_alloc_free_mutexed( void *ptr )
559{
Manuel Pégourié-Gonnardbdd78282015-04-24 14:42:53 +0200560 /* We have to good option here, but corrupting the heap seems
561 * worse than loosing memory. */
562 if( mbedtls_mutex_lock( &heap.mutex ) )
563 return;
Paul Bakker1337aff2013-09-29 14:45:34 +0200564 buffer_alloc_free( ptr );
Manuel Pégourié-Gonnardbdd78282015-04-24 14:42:53 +0200565 (void) mbedtls_mutex_unlock( &heap.mutex );
Paul Bakker1337aff2013-09-29 14:45:34 +0200566}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567#endif /* MBEDTLS_THREADING_C */
Paul Bakker1337aff2013-09-29 14:45:34 +0200568
Manuel Pégourié-Gonnard69a69cc2015-04-29 01:05:19 +0200569void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len )
Paul Bakker6e339b52013-07-03 13:37:05 +0200570{
Andres AG9cf1f962017-01-30 14:34:25 +0000571 memset( &heap, 0, sizeof( buffer_alloc_ctx ) );
Paul Bakker6e339b52013-07-03 13:37:05 +0200572
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573#if defined(MBEDTLS_THREADING_C)
574 mbedtls_mutex_init( &heap.mutex );
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200575 mbedtls_platform_set_calloc_free( buffer_alloc_calloc_mutexed,
Paul Bakkerdefc0ca2014-02-04 17:30:24 +0100576 buffer_alloc_free_mutexed );
Paul Bakker1337aff2013-09-29 14:45:34 +0200577#else
Manuel Pégourié-Gonnard200e7312015-05-26 17:42:13 +0200578 mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free );
Paul Bakker1337aff2013-09-29 14:45:34 +0200579#endif
580
Andres AG9cf1f962017-01-30 14:34:25 +0000581 if( len < sizeof( memory_header ) + MBEDTLS_MEMORY_ALIGN_MULTIPLE )
582 return;
583 else if( (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE )
Manuel Pégourié-Gonnard82a5de72014-05-05 14:05:24 +0200584 {
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100585 /* Adjust len first since buf is used in the computation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE
Andres AG9cf1f962017-01-30 14:34:25 +0000587 - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200588 buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE
Andres AG9cf1f962017-01-30 14:34:25 +0000589 - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
Manuel Pégourié-Gonnard82a5de72014-05-05 14:05:24 +0200590 }
591
Andres AG9cf1f962017-01-30 14:34:25 +0000592 memset( buf, 0, len );
593
Paul Bakker6e339b52013-07-03 13:37:05 +0200594 heap.buf = buf;
595 heap.len = len;
596
Andres AG9cf1f962017-01-30 14:34:25 +0000597 heap.first = (memory_header *)buf;
598 heap.first->size = len - sizeof( memory_header );
Paul Bakker6e339b52013-07-03 13:37:05 +0200599 heap.first->magic1 = MAGIC1;
600 heap.first->magic2 = MAGIC2;
Paul Bakker1ef120f2013-07-03 17:20:39 +0200601 heap.first_free = heap.first;
Paul Bakker6e339b52013-07-03 13:37:05 +0200602}
603
Joris Aertse75b88d2016-11-04 23:05:56 +0100604void mbedtls_memory_buffer_alloc_free( void )
Paul Bakker1337aff2013-09-29 14:45:34 +0200605{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200606#if defined(MBEDTLS_THREADING_C)
607 mbedtls_mutex_free( &heap.mutex );
Paul Bakker1337aff2013-09-29 14:45:34 +0200608#endif
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500609 mbedtls_platform_zeroize( &heap, sizeof(buffer_alloc_ctx) );
Paul Bakker1337aff2013-09-29 14:45:34 +0200610}
611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100613static int check_pointer( void *p )
614{
615 if( p == NULL )
616 return( -1 );
617
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200618 if( (size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0 )
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100619 return( -1 );
620
621 return( 0 );
622}
623
Joris Aertse75b88d2016-11-04 23:05:56 +0100624static int check_all_free( void )
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100625{
Manuel Pégourié-Gonnard491a3fe2015-02-05 12:08:47 +0100626 if(
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200627#if defined(MBEDTLS_MEMORY_DEBUG)
Manuel Pégourié-Gonnard491a3fe2015-02-05 12:08:47 +0100628 heap.total_used != 0 ||
629#endif
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100630 heap.first != heap.first_free ||
631 (void *) heap.first != (void *) heap.buf )
632 {
633 return( -1 );
634 }
635
636 return( 0 );
637}
638
639#define TEST_ASSERT( condition ) \
640 if( ! (condition) ) \
641 { \
642 if( verbose != 0 ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200643 mbedtls_printf( "failed\n" ); \
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100644 \
645 ret = 1; \
646 goto cleanup; \
647 }
648
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200649int mbedtls_memory_buffer_alloc_self_test( int verbose )
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100650{
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100651 unsigned char buf[1024];
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100652 unsigned char *p, *q, *r, *end;
653 int ret = 0;
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100654
655 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656 mbedtls_printf( " MBA test #1 (basic alloc-free cycle): " );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100657
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100659
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200660 p = mbedtls_calloc( 1, 1 );
661 q = mbedtls_calloc( 1, 128 );
662 r = mbedtls_calloc( 1, 16 );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100663
664 TEST_ASSERT( check_pointer( p ) == 0 &&
665 check_pointer( q ) == 0 &&
666 check_pointer( r ) == 0 );
667
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668 mbedtls_free( r );
669 mbedtls_free( q );
670 mbedtls_free( p );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100671
672 TEST_ASSERT( check_all_free( ) == 0 );
673
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100674 /* Memorize end to compare with the next test */
675 end = heap.buf + heap.len;
676
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200677 mbedtls_memory_buffer_alloc_free( );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100678
679 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100681
682 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 mbedtls_printf( " MBA test #2 (buf not aligned): " );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100684
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685 mbedtls_memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100686
Manuel Pégourié-Gonnard5dd28ea2014-11-27 13:57:42 +0100687 TEST_ASSERT( heap.buf + heap.len == end );
688
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200689 p = mbedtls_calloc( 1, 1 );
690 q = mbedtls_calloc( 1, 128 );
691 r = mbedtls_calloc( 1, 16 );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100692
693 TEST_ASSERT( check_pointer( p ) == 0 &&
694 check_pointer( q ) == 0 &&
695 check_pointer( r ) == 0 );
696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 mbedtls_free( r );
698 mbedtls_free( q );
699 mbedtls_free( p );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100700
701 TEST_ASSERT( check_all_free( ) == 0 );
702
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703 mbedtls_memory_buffer_alloc_free( );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100704
705 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100707
708 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200709 mbedtls_printf( " MBA test #3 (full): " );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100710
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200711 mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100712
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200713 p = mbedtls_calloc( 1, sizeof( buf ) - sizeof( memory_header ) );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100714
715 TEST_ASSERT( check_pointer( p ) == 0 );
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200716 TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100717
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200718 mbedtls_free( p );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100719
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200720 p = mbedtls_calloc( 1, sizeof( buf ) - 2 * sizeof( memory_header ) - 16 );
721 q = mbedtls_calloc( 1, 16 );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100722
723 TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 );
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200724 TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100725
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200726 mbedtls_free( q );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100727
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200728 TEST_ASSERT( mbedtls_calloc( 1, 17 ) == NULL );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100729
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730 mbedtls_free( p );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100731
732 TEST_ASSERT( check_all_free( ) == 0 );
733
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734 mbedtls_memory_buffer_alloc_free( );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100735
736 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100738
739cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200740 mbedtls_memory_buffer_alloc_free( );
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100741
742 return( ret );
743}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200744#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard5ba1d522014-11-27 11:33:55 +0100745
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200746#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */