1 /**
2  * \file mbedtls_md.c
3  *
4  * \brief Generic message digest wrapper for mbed TLS
5  *
6  * \author Adriaan de Jong <dejong@fox-it.com>
7  *
8  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
9  *  SPDX-License-Identifier: GPL-2.0
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License along
22  *  with this program; if not, write to the Free Software Foundation, Inc.,
23  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  *
25  *  This file is part of mbed TLS (https://tls.mbed.org)
26  */
27 
28 #if !defined(MBEDTLS_CONFIG_FILE)
29 #include "mbedtls/config.h"
30 #else
31 #include MBEDTLS_CONFIG_FILE
32 #endif
33 
34 #if defined(MBEDTLS_MD_C)
35 
36 #include "mbedtls/md.h"
37 #include "mbedtls/md_internal.h"
38 #include "mbedtls/platform_util.h"
39 
40 #if defined(MBEDTLS_PLATFORM_C)
41 #include "mbedtls/platform.h"
42 #else
43 #include <stdlib.h>
44 #define mbedtls_calloc    calloc
45 #define mbedtls_free       free
46 #endif
47 
48 #include <string.h>
49 
50 #if defined(MBEDTLS_FS_IO)
51 #include <stdio.h>
52 #endif
53 
54 /*
55  * Reminder: update profiles in x509_crt.c when adding a new hash!
56  */
57 static const int supported_digests[] = {
58 
59 #if defined(MBEDTLS_SHA512_C)
60         MBEDTLS_MD_SHA512,
61         MBEDTLS_MD_SHA384,
62 #endif
63 
64 #if defined(MBEDTLS_SHA256_C)
65         MBEDTLS_MD_SHA256,
66         MBEDTLS_MD_SHA224,
67 #endif
68 
69 #if defined(MBEDTLS_SHA1_C)
70         MBEDTLS_MD_SHA1,
71 #endif
72 
73 #if defined(MBEDTLS_RIPEMD160_C)
74         MBEDTLS_MD_RIPEMD160,
75 #endif
76 
77 #if defined(MBEDTLS_MD5_C)
78         MBEDTLS_MD_MD5,
79 #endif
80 
81 #if defined(MBEDTLS_MD4_C)
82         MBEDTLS_MD_MD4,
83 #endif
84 
85 #if defined(MBEDTLS_MD2_C)
86         MBEDTLS_MD_MD2,
87 #endif
88 
89         MBEDTLS_MD_NONE
90 };
91 
mbedtls_md_list(void)92 const int *mbedtls_md_list( void )
93 {
94     return( supported_digests );
95 }
96 
mbedtls_md_info_from_string(const char * md_name)97 const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name )
98 {
99     if( NULL == md_name )
100         return( NULL );
101 
102     /* Get the appropriate digest information */
103 #if defined(MBEDTLS_MD2_C)
104     if( !strcmp( "MD2", md_name ) )
105         return mbedtls_md_info_from_type( MBEDTLS_MD_MD2 );
106 #endif
107 #if defined(MBEDTLS_MD4_C)
108     if( !strcmp( "MD4", md_name ) )
109         return mbedtls_md_info_from_type( MBEDTLS_MD_MD4 );
110 #endif
111 #if defined(MBEDTLS_MD5_C)
112     if( !strcmp( "MD5", md_name ) )
113         return mbedtls_md_info_from_type( MBEDTLS_MD_MD5 );
114 #endif
115 #if defined(MBEDTLS_RIPEMD160_C)
116     if( !strcmp( "RIPEMD160", md_name ) )
117         return mbedtls_md_info_from_type( MBEDTLS_MD_RIPEMD160 );
118 #endif
119 #if defined(MBEDTLS_SHA1_C)
120     if( !strcmp( "SHA1", md_name ) || !strcmp( "SHA", md_name ) )
121         return mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
122 #endif
123 #if defined(MBEDTLS_SHA256_C)
124     if( !strcmp( "SHA224", md_name ) )
125         return mbedtls_md_info_from_type( MBEDTLS_MD_SHA224 );
126     if( !strcmp( "SHA256", md_name ) )
127         return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 );
128 #endif
129 #if defined(MBEDTLS_SHA512_C)
130     if( !strcmp( "SHA384", md_name ) )
131         return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 );
132     if( !strcmp( "SHA512", md_name ) )
133         return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 );
134 #endif
135     return( NULL );
136 }
137 
mbedtls_md_info_from_type(mbedtls_md_type_t md_type)138 const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type )
139 {
140     switch( md_type )
141     {
142 #if defined(MBEDTLS_MD2_C)
143         case MBEDTLS_MD_MD2:
144             return( &mbedtls_md2_info );
145 #endif
146 #if defined(MBEDTLS_MD4_C)
147         case MBEDTLS_MD_MD4:
148             return( &mbedtls_md4_info );
149 #endif
150 #if defined(MBEDTLS_MD5_C)
151         case MBEDTLS_MD_MD5:
152             return( &mbedtls_md5_info );
153 #endif
154 #if defined(MBEDTLS_RIPEMD160_C)
155         case MBEDTLS_MD_RIPEMD160:
156             return( &mbedtls_ripemd160_info );
157 #endif
158 #if defined(MBEDTLS_SHA1_C)
159         case MBEDTLS_MD_SHA1:
160             return( &mbedtls_sha1_info );
161 #endif
162 #if defined(MBEDTLS_SHA256_C)
163         case MBEDTLS_MD_SHA224:
164             return( &mbedtls_sha224_info );
165         case MBEDTLS_MD_SHA256:
166             return( &mbedtls_sha256_info );
167 #endif
168 #if defined(MBEDTLS_SHA512_C)
169         case MBEDTLS_MD_SHA384:
170             return( &mbedtls_sha384_info );
171         case MBEDTLS_MD_SHA512:
172             return( &mbedtls_sha512_info );
173 #endif
174         default:
175             return( NULL );
176     }
177 }
178 
mbedtls_md_init(mbedtls_md_context_t * ctx)179 void mbedtls_md_init( mbedtls_md_context_t *ctx )
180 {
181     memset( ctx, 0, sizeof( mbedtls_md_context_t ) );
182 }
183 
mbedtls_md_free(mbedtls_md_context_t * ctx)184 void mbedtls_md_free( mbedtls_md_context_t *ctx )
185 {
186     if( ctx == NULL || ctx->md_info == NULL )
187         return;
188 
189     if( ctx->md_ctx != NULL )
190         ctx->md_info->ctx_free_func( ctx->md_ctx );
191 
192     if( ctx->hmac_ctx != NULL )
193     {
194         mbedtls_platform_zeroize( ctx->hmac_ctx,
195                                   2 * ctx->md_info->block_size );
196         mbedtls_free( ctx->hmac_ctx );
197     }
198 
199     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md_context_t ) );
200 }
201 
mbedtls_md_clone(mbedtls_md_context_t * dst,const mbedtls_md_context_t * src)202 int mbedtls_md_clone( mbedtls_md_context_t *dst,
203                       const mbedtls_md_context_t *src )
204 {
205     if( dst == NULL || dst->md_info == NULL ||
206         src == NULL || src->md_info == NULL ||
207         dst->md_info != src->md_info )
208     {
209         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
210     }
211 
212     dst->md_info->clone_func( dst->md_ctx, src->md_ctx );
213 
214     return( 0 );
215 }
216 
217 #if ! defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md_init_ctx(mbedtls_md_context_t * ctx,const mbedtls_md_info_t * md_info)218 int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info )
219 {
220     return mbedtls_md_setup( ctx, md_info, 1 );
221 }
222 #endif
223 
mbedtls_md_setup(mbedtls_md_context_t * ctx,const mbedtls_md_info_t * md_info,int hmac)224 int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac )
225 {
226     if( md_info == NULL || ctx == NULL )
227         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
228 
229     if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL )
230         return( MBEDTLS_ERR_MD_ALLOC_FAILED );
231 
232     if( hmac != 0 )
233     {
234         ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size );
235         if( ctx->hmac_ctx == NULL )
236         {
237             md_info->ctx_free_func( ctx->md_ctx );
238             return( MBEDTLS_ERR_MD_ALLOC_FAILED );
239         }
240     }
241 
242     ctx->md_info = md_info;
243 
244     return( 0 );
245 }
246 
mbedtls_md_starts(mbedtls_md_context_t * ctx)247 int mbedtls_md_starts( mbedtls_md_context_t *ctx )
248 {
249     if( ctx == NULL || ctx->md_info == NULL )
250         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
251 
252     return( ctx->md_info->starts_func( ctx->md_ctx ) );
253 }
254 
mbedtls_md_update(mbedtls_md_context_t * ctx,const unsigned char * input,size_t ilen)255 int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen )
256 {
257     if( ctx == NULL || ctx->md_info == NULL )
258         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
259 
260     return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) );
261 }
262 
mbedtls_md_finish(mbedtls_md_context_t * ctx,unsigned char * output)263 int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output )
264 {
265     if( ctx == NULL || ctx->md_info == NULL )
266         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
267 
268     return( ctx->md_info->finish_func( ctx->md_ctx, output ) );
269 }
270 
mbedtls_md(const mbedtls_md_info_t * md_info,const unsigned char * input,size_t ilen,unsigned char * output)271 int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen,
272             unsigned char *output )
273 {
274     if( md_info == NULL )
275         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
276 
277     return( md_info->digest_func( input, ilen, output ) );
278 }
279 
280 #if defined(MBEDTLS_FS_IO)
mbedtls_md_file(const mbedtls_md_info_t * md_info,const char * path,unsigned char * output)281 int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output )
282 {
283     int ret;
284     FILE *f;
285     size_t n;
286     mbedtls_md_context_t ctx;
287     unsigned char buf[1024];
288 
289     if( md_info == NULL )
290         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
291 
292     if( ( f = fopen( path, "rb" ) ) == NULL )
293         return( MBEDTLS_ERR_MD_FILE_IO_ERROR );
294 
295     mbedtls_md_init( &ctx );
296 
297     if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 )
298         goto cleanup;
299 
300     if( ( ret = md_info->starts_func( ctx.md_ctx ) ) != 0 )
301         goto cleanup;
302 
303     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
304         if( ( ret = md_info->update_func( ctx.md_ctx, buf, n ) ) != 0 )
305             goto cleanup;
306 
307     if( ferror( f ) != 0 )
308         ret = MBEDTLS_ERR_MD_FILE_IO_ERROR;
309     else
310         ret = md_info->finish_func( ctx.md_ctx, output );
311 
312 cleanup:
313     mbedtls_platform_zeroize( buf, sizeof( buf ) );
314     fclose( f );
315     mbedtls_md_free( &ctx );
316 
317     return( ret );
318 }
319 #endif /* MBEDTLS_FS_IO */
320 
mbedtls_md_hmac_starts(mbedtls_md_context_t * ctx,const unsigned char * key,size_t keylen)321 int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen )
322 {
323     int ret;
324     unsigned char sum[MBEDTLS_MD_MAX_SIZE];
325     unsigned char *ipad, *opad;
326     size_t i;
327 
328     if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
329         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
330 
331     if( keylen > (size_t) ctx->md_info->block_size )
332     {
333         if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
334             goto cleanup;
335         if( ( ret = ctx->md_info->update_func( ctx->md_ctx, key, keylen ) ) != 0 )
336             goto cleanup;
337         if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, sum ) ) != 0 )
338             goto cleanup;
339 
340         keylen = ctx->md_info->size;
341         key = sum;
342     }
343 
344     ipad = (unsigned char *) ctx->hmac_ctx;
345     opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size;
346 
347     memset( ipad, 0x36, ctx->md_info->block_size );
348     memset( opad, 0x5C, ctx->md_info->block_size );
349 
350     for( i = 0; i < keylen; i++ )
351     {
352         ipad[i] = (unsigned char)( ipad[i] ^ key[i] );
353         opad[i] = (unsigned char)( opad[i] ^ key[i] );
354     }
355 
356     if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
357         goto cleanup;
358     if( ( ret = ctx->md_info->update_func( ctx->md_ctx, ipad,
359                                            ctx->md_info->block_size ) ) != 0 )
360         goto cleanup;
361 
362 cleanup:
363     mbedtls_platform_zeroize( sum, sizeof( sum ) );
364 
365     return( ret );
366 }
367 
mbedtls_md_hmac_update(mbedtls_md_context_t * ctx,const unsigned char * input,size_t ilen)368 int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen )
369 {
370     if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
371         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
372 
373     return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) );
374 }
375 
mbedtls_md_hmac_finish(mbedtls_md_context_t * ctx,unsigned char * output)376 int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output )
377 {
378     int ret;
379     unsigned char tmp[MBEDTLS_MD_MAX_SIZE];
380     unsigned char *opad;
381 
382     if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
383         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
384 
385     opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size;
386 
387     if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, tmp ) ) != 0 )
388         return( ret );
389     if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
390         return( ret );
391     if( ( ret = ctx->md_info->update_func( ctx->md_ctx, opad,
392                                            ctx->md_info->block_size ) ) != 0 )
393         return( ret );
394     if( ( ret = ctx->md_info->update_func( ctx->md_ctx, tmp,
395                                            ctx->md_info->size ) ) != 0 )
396         return( ret );
397     return( ctx->md_info->finish_func( ctx->md_ctx, output ) );
398 }
399 
mbedtls_md_hmac_reset(mbedtls_md_context_t * ctx)400 int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx )
401 {
402     int ret;
403     unsigned char *ipad;
404 
405     if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
406         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
407 
408     ipad = (unsigned char *) ctx->hmac_ctx;
409 
410     if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
411         return( ret );
412     return( ctx->md_info->update_func( ctx->md_ctx, ipad,
413                                        ctx->md_info->block_size ) );
414 }
415 
mbedtls_md_hmac(const mbedtls_md_info_t * md_info,const unsigned char * key,size_t keylen,const unsigned char * input,size_t ilen,unsigned char * output)416 int mbedtls_md_hmac( const mbedtls_md_info_t *md_info,
417                      const unsigned char *key, size_t keylen,
418                      const unsigned char *input, size_t ilen,
419                      unsigned char *output )
420 {
421     mbedtls_md_context_t ctx;
422     int ret;
423 
424     if( md_info == NULL )
425         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
426 
427     mbedtls_md_init( &ctx );
428 
429     if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 )
430         goto cleanup;
431 
432     if( ( ret = mbedtls_md_hmac_starts( &ctx, key, keylen ) ) != 0 )
433         goto cleanup;
434     if( ( ret = mbedtls_md_hmac_update( &ctx, input, ilen ) ) != 0 )
435         goto cleanup;
436     if( ( ret = mbedtls_md_hmac_finish( &ctx, output ) ) != 0 )
437         goto cleanup;
438 
439 cleanup:
440     mbedtls_md_free( &ctx );
441 
442     return( ret );
443 }
444 
mbedtls_md_process(mbedtls_md_context_t * ctx,const unsigned char * data)445 int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data )
446 {
447     if( ctx == NULL || ctx->md_info == NULL )
448         return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
449 
450     return( ctx->md_info->process_func( ctx->md_ctx, data ) );
451 }
452 
mbedtls_md_get_size(const mbedtls_md_info_t * md_info)453 unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info )
454 {
455     if( md_info == NULL )
456         return( 0 );
457 
458     return md_info->size;
459 }
460 
mbedtls_md_get_type(const mbedtls_md_info_t * md_info)461 mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info )
462 {
463     if( md_info == NULL )
464         return( MBEDTLS_MD_NONE );
465 
466     return md_info->type;
467 }
468 
mbedtls_md_get_name(const mbedtls_md_info_t * md_info)469 const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info )
470 {
471     if( md_info == NULL )
472         return( NULL );
473 
474     return md_info->name;
475 }
476 
477 #endif /* MBEDTLS_MD_C */
478