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