1 /*
2 * generic message digest layer demonstration program
3 *
4 * Copyright The Mbed TLS Contributors
5 * 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.
18 */
19
20 #if !defined(MBEDTLS_CONFIG_FILE)
21 #include "mbedtls/config.h"
22 #else
23 #include MBEDTLS_CONFIG_FILE
24 #endif
25
26 #if defined(MBEDTLS_PLATFORM_C)
27 #include "mbedtls/platform.h"
28 #else
29 #include <stdio.h>
30 #include <stdlib.h>
31 #define mbedtls_fprintf fprintf
32 #define mbedtls_printf printf
33 #define mbedtls_exit exit
34 #define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
35 #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
36 #endif /* MBEDTLS_PLATFORM_C */
37
38 #if defined(MBEDTLS_MD_C) && defined(MBEDTLS_FS_IO)
39 #include "mbedtls/md.h"
40
41 #include <stdio.h>
42 #include <string.h>
43 #endif
44
45 #if !defined(MBEDTLS_MD_C) || !defined(MBEDTLS_FS_IO)
main(void)46 int main( void )
47 {
48 mbedtls_printf("MBEDTLS_MD_C and/or MBEDTLS_FS_IO not defined.\n");
49 mbedtls_exit( 0 );
50 }
51 #else
52
53
generic_wrapper(const mbedtls_md_info_t * md_info,char * filename,unsigned char * sum)54 static int generic_wrapper( const mbedtls_md_info_t *md_info, char *filename, unsigned char *sum )
55 {
56 int ret = mbedtls_md_file( md_info, filename, sum );
57
58 if( ret == 1 )
59 mbedtls_fprintf( stderr, "failed to open: %s\n", filename );
60
61 if( ret == 2 )
62 mbedtls_fprintf( stderr, "failed to read: %s\n", filename );
63
64 return( ret );
65 }
66
generic_print(const mbedtls_md_info_t * md_info,char * filename)67 static int generic_print( const mbedtls_md_info_t *md_info, char *filename )
68 {
69 int i;
70 unsigned char sum[MBEDTLS_MD_MAX_SIZE];
71
72 if( generic_wrapper( md_info, filename, sum ) != 0 )
73 return( 1 );
74
75 for( i = 0; i < mbedtls_md_get_size( md_info ); i++ )
76 mbedtls_printf( "%02x", sum[i] );
77
78 mbedtls_printf( " %s\n", filename );
79 return( 0 );
80 }
81
generic_check(const mbedtls_md_info_t * md_info,char * filename)82 static int generic_check( const mbedtls_md_info_t *md_info, char *filename )
83 {
84 int i;
85 size_t n;
86 FILE *f;
87 int nb_err1, nb_err2;
88 int nb_tot1, nb_tot2;
89 unsigned char sum[MBEDTLS_MD_MAX_SIZE];
90 char line[1024];
91 char diff;
92 #if defined(__clang_analyzer__)
93 char buf[MBEDTLS_MD_MAX_SIZE * 2 + 1] = { };
94 #else
95 char buf[MBEDTLS_MD_MAX_SIZE * 2 + 1];
96 #endif
97
98 if( ( f = fopen( filename, "rb" ) ) == NULL )
99 {
100 mbedtls_printf( "failed to open: %s\n", filename );
101 return( 1 );
102 }
103
104 nb_err1 = nb_err2 = 0;
105 nb_tot1 = nb_tot2 = 0;
106
107 memset( line, 0, sizeof( line ) );
108
109 n = sizeof( line );
110
111 while( fgets( line, (int) n - 1, f ) != NULL )
112 {
113 n = strlen( line );
114
115 if( n < (size_t) 2 * mbedtls_md_get_size( md_info ) + 4 )
116 {
117 mbedtls_printf("No '%s' hash found on line.\n", mbedtls_md_get_name( md_info ));
118 continue;
119 }
120
121 if( line[2 * mbedtls_md_get_size( md_info )] != ' ' || line[2 * mbedtls_md_get_size( md_info ) + 1] != ' ' )
122 {
123 mbedtls_printf("No '%s' hash found on line.\n", mbedtls_md_get_name( md_info ));
124 continue;
125 }
126
127 if( line[n - 1] == '\n' ) { n--; line[n] = '\0'; }
128 if( line[n - 1] == '\r' ) { n--; line[n] = '\0'; }
129
130 nb_tot1++;
131
132 if( generic_wrapper( md_info, line + 2 + 2 * mbedtls_md_get_size( md_info ), sum ) != 0 )
133 {
134 nb_err1++;
135 continue;
136 }
137
138 nb_tot2++;
139
140 for( i = 0; i < mbedtls_md_get_size( md_info ); i++ )
141 sprintf( buf + i * 2, "%02x", sum[i] );
142
143 /* Use constant-time buffer comparison */
144 diff = 0;
145 for( i = 0; i < 2 * mbedtls_md_get_size( md_info ); i++ )
146 diff |= line[i] ^ buf[i];
147
148 if( diff != 0 )
149 {
150 nb_err2++;
151 mbedtls_fprintf( stderr, "wrong checksum: %s\n", line + 66 );
152 }
153
154 n = sizeof( line );
155 }
156
157 if( nb_err1 != 0 )
158 {
159 mbedtls_printf( "WARNING: %d (out of %d) input files could "
160 "not be read\n", nb_err1, nb_tot1 );
161 }
162
163 if( nb_err2 != 0 )
164 {
165 mbedtls_printf( "WARNING: %d (out of %d) computed checksums did "
166 "not match\n", nb_err2, nb_tot2 );
167 }
168
169 fclose( f );
170
171 return( nb_err1 != 0 || nb_err2 != 0 );
172 }
173
main(int argc,char * argv[])174 int main( int argc, char *argv[] )
175 {
176 int ret = 1, i;
177 int exit_code = MBEDTLS_EXIT_FAILURE;
178 const mbedtls_md_info_t *md_info;
179 mbedtls_md_context_t md_ctx;
180
181 mbedtls_md_init( &md_ctx );
182
183 if( argc == 1 )
184 {
185 const int *list;
186
187 mbedtls_printf( "print mode: generic_sum <mbedtls_md> <file> <file> ...\n" );
188 mbedtls_printf( "check mode: generic_sum <mbedtls_md> -c <checksum file>\n" );
189
190 mbedtls_printf( "\nAvailable message digests:\n" );
191 list = mbedtls_md_list();
192 while( *list )
193 {
194 md_info = mbedtls_md_info_from_type( *list );
195 mbedtls_printf( " %s\n", mbedtls_md_get_name( md_info ) );
196 list++;
197 }
198
199 #if defined(_WIN32)
200 mbedtls_printf( "\n Press Enter to exit this program.\n" );
201 fflush( stdout ); getchar();
202 #endif
203
204 mbedtls_exit( exit_code );
205 }
206
207 /*
208 * Read the MD from the command line
209 */
210 md_info = mbedtls_md_info_from_string( argv[1] );
211 if( md_info == NULL )
212 {
213 mbedtls_fprintf( stderr, "Message Digest '%s' not found\n", argv[1] );
214 mbedtls_exit( exit_code );
215 }
216 if( mbedtls_md_setup( &md_ctx, md_info, 0 ) )
217 {
218 mbedtls_fprintf( stderr, "Failed to initialize context.\n" );
219 mbedtls_exit( exit_code );
220 }
221
222 ret = 0;
223 if( argc == 4 && strcmp( "-c", argv[2] ) == 0 )
224 {
225 ret |= generic_check( md_info, argv[3] );
226 goto exit;
227 }
228
229 for( i = 2; i < argc; i++ )
230 ret |= generic_print( md_info, argv[i] );
231
232 if ( ret == 0 )
233 exit_code = MBEDTLS_EXIT_SUCCESS;
234
235 exit:
236 mbedtls_md_free( &md_ctx );
237
238 mbedtls_exit( exit_code );
239 }
240 #endif /* MBEDTLS_MD_C && MBEDTLS_FS_IO */
241