blob: 033366e5cd0d040bcbdc7ca993a4c4f53e1d85ef [file] [log] [blame]
Paul Bakkerfb6c7e22011-01-21 10:21:11 +00001/*
2 * generic message digest layer demonstration program
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Dave Rodgman7ff79652023-11-03 12:04:52 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Paul Bakkerfb6c7e22011-01-21 10:21:11 +00006 */
7
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02008#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +00009#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020010#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020011#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020012#endif
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000013
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000014#include "mbedtls/platform.h"
Rich Evansf90016a2015-01-19 14:26:37 +000015
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020016#if defined(MBEDTLS_MD_C) && defined(MBEDTLS_FS_IO)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000017#include "mbedtls/md.h"
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000018
Rich Evans18b78c72015-02-11 14:06:19 +000019#include <stdio.h>
20#include <string.h>
21#endif
22
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020023#if !defined(MBEDTLS_MD_C) || !defined(MBEDTLS_FS_IO)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010024int main(void)
Paul Bakker5690efc2011-05-26 13:16:06 +000025{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020026 mbedtls_printf("MBEDTLS_MD_C and/or MBEDTLS_FS_IO not defined.\n");
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010027 mbedtls_exit(0);
Paul Bakker5690efc2011-05-26 13:16:06 +000028}
29#else
Manuel Pégourié-Gonnard3ef6a6d2018-12-10 14:31:45 +010030
Manuel Pégourié-Gonnard3ef6a6d2018-12-10 14:31:45 +010031
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010032static int generic_wrapper(const mbedtls_md_info_t *md_info, char *filename, unsigned char *sum)
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000033{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010034 int ret = mbedtls_md_file(md_info, filename, sum);
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000035
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010036 if (ret == 1) {
37 mbedtls_fprintf(stderr, "failed to open: %s\n", filename);
38 }
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000039
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010040 if (ret == 2) {
41 mbedtls_fprintf(stderr, "failed to read: %s\n", filename);
42 }
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000043
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010044 return ret;
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000045}
46
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010047static int generic_print(const mbedtls_md_info_t *md_info, char *filename)
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000048{
49 int i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020050 unsigned char sum[MBEDTLS_MD_MAX_SIZE];
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000051
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010052 if (generic_wrapper(md_info, filename, sum) != 0) {
53 return 1;
54 }
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000055
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010056 for (i = 0; i < mbedtls_md_get_size(md_info); i++) {
57 mbedtls_printf("%02x", sum[i]);
58 }
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000059
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010060 mbedtls_printf(" %s\n", filename);
61 return 0;
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000062}
63
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010064static int generic_check(const mbedtls_md_info_t *md_info, char *filename)
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000065{
66 int i;
67 size_t n;
68 FILE *f;
69 int nb_err1, nb_err2;
70 int nb_tot1, nb_tot2;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071 unsigned char sum[MBEDTLS_MD_MAX_SIZE];
Paul Bakkerd1fe7aa2016-05-12 12:46:02 +010072 char line[1024];
Manuel Pégourié-Gonnard291f9af2013-10-28 12:51:32 +010073 char diff;
Paul Bakkerd1fe7aa2016-05-12 12:46:02 +010074#if defined(__clang_analyzer__)
75 char buf[MBEDTLS_MD_MAX_SIZE * 2 + 1] = { };
76#else
77 char buf[MBEDTLS_MD_MAX_SIZE * 2 + 1];
78#endif
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000079
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010080 if ((f = fopen(filename, "rb")) == NULL) {
81 mbedtls_printf("failed to open: %s\n", filename);
82 return 1;
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000083 }
84
85 nb_err1 = nb_err2 = 0;
86 nb_tot1 = nb_tot2 = 0;
87
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010088 memset(line, 0, sizeof(line));
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000089
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010090 n = sizeof(line);
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000091
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010092 while (fgets(line, (int) n - 1, f) != NULL) {
93 n = strlen(line);
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000094
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010095 if (n < (size_t) 2 * mbedtls_md_get_size(md_info) + 4) {
96 mbedtls_printf("No '%s' hash found on line.\n", mbedtls_md_get_name(md_info));
Paul Bakkerfb6c7e22011-01-21 10:21:11 +000097 continue;
98 }
99
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100100 if (line[2 * mbedtls_md_get_size(md_info)] != ' ' ||
101 line[2 * mbedtls_md_get_size(md_info) + 1] != ' ') {
102 mbedtls_printf("No '%s' hash found on line.\n", mbedtls_md_get_name(md_info));
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000103 continue;
104 }
105
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100106 if (line[n - 1] == '\n') {
107 n--; line[n] = '\0';
108 }
109 if (line[n - 1] == '\r') {
110 n--; line[n] = '\0';
111 }
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000112
113 nb_tot1++;
114
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100115 if (generic_wrapper(md_info, line + 2 + 2 * mbedtls_md_get_size(md_info), sum) != 0) {
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000116 nb_err1++;
117 continue;
118 }
119
120 nb_tot2++;
121
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100122 for (i = 0; i < mbedtls_md_get_size(md_info); i++) {
123 sprintf(buf + i * 2, "%02x", sum[i]);
124 }
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000125
Manuel Pégourié-Gonnard291f9af2013-10-28 12:51:32 +0100126 /* Use constant-time buffer comparison */
127 diff = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100128 for (i = 0; i < 2 * mbedtls_md_get_size(md_info); i++) {
Manuel Pégourié-Gonnard291f9af2013-10-28 12:51:32 +0100129 diff |= line[i] ^ buf[i];
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000130 }
131
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100132 if (diff != 0) {
133 nb_err2++;
134 mbedtls_fprintf(stderr, "wrong checksum: %s\n", line + 66);
135 }
136
137 n = sizeof(line);
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000138 }
139
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100140 if (nb_err1 != 0) {
141 mbedtls_printf("WARNING: %d (out of %d) input files could "
142 "not be read\n", nb_err1, nb_tot1);
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000143 }
144
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100145 if (nb_err2 != 0) {
146 mbedtls_printf("WARNING: %d (out of %d) computed checksums did "
147 "not match\n", nb_err2, nb_tot2);
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000148 }
149
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100150 fclose(f);
Paul Bakker64abd832014-02-06 15:03:06 +0100151
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100152 return nb_err1 != 0 || nb_err2 != 0;
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000153}
154
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100155int main(int argc, char *argv[])
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000156{
Andres Amaya Garciadabd78f2018-04-29 22:35:36 +0100157 int ret = 1, i;
158 int exit_code = MBEDTLS_EXIT_FAILURE;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200159 const mbedtls_md_info_t *md_info;
160 mbedtls_md_context_t md_ctx;
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000161
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100162 mbedtls_md_init(&md_ctx);
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000163
Aditya Deshpande56d90032023-02-03 16:15:30 +0000164 if (argc < 2) {
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000165 const int *list;
166
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100167 mbedtls_printf("print mode: generic_sum <mbedtls_md> <file> <file> ...\n");
168 mbedtls_printf("check mode: generic_sum <mbedtls_md> -c <checksum file>\n");
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000169
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100170 mbedtls_printf("\nAvailable message digests:\n");
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 list = mbedtls_md_list();
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100172 while (*list) {
173 md_info = mbedtls_md_info_from_type(*list);
174 mbedtls_printf(" %s\n", mbedtls_md_get_name(md_info));
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000175 list++;
176 }
177
Paul Bakkercce9d772011-11-18 14:26:47 +0000178#if defined(_WIN32)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100179 mbedtls_printf("\n Press Enter to exit this program.\n");
180 fflush(stdout); getchar();
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000181#endif
182
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100183 mbedtls_exit(exit_code);
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000184 }
185
186 /*
187 * Read the MD from the command line
188 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100189 md_info = mbedtls_md_info_from_string(argv[1]);
190 if (md_info == NULL) {
191 mbedtls_fprintf(stderr, "Message Digest '%s' not found\n", argv[1]);
192 mbedtls_exit(exit_code);
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000193 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100194 if (mbedtls_md_setup(&md_ctx, md_info, 0)) {
195 mbedtls_fprintf(stderr, "Failed to initialize context.\n");
196 mbedtls_exit(exit_code);
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000197 }
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000198
199 ret = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100200 if (argc == 4 && strcmp("-c", argv[2]) == 0) {
201 ret |= generic_check(md_info, argv[3]);
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000202 goto exit;
203 }
204
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100205 for (i = 2; i < argc; i++) {
206 ret |= generic_print(md_info, argv[i]);
207 }
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000208
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100209 if (ret == 0) {
Andres Amaya Garciadabd78f2018-04-29 22:35:36 +0100210 exit_code = MBEDTLS_EXIT_SUCCESS;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100211 }
Andres Amaya Garciadabd78f2018-04-29 22:35:36 +0100212
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000213exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100214 mbedtls_md_free(&md_ctx);
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000215
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100216 mbedtls_exit(exit_code);
Paul Bakkerfb6c7e22011-01-21 10:21:11 +0000217}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218#endif /* MBEDTLS_MD_C && MBEDTLS_FS_IO */