/src/barebox/commands/digest.c
Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-2.0-only |
2 | | // SPDX-FileCopyrightText: © 2015 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> |
3 | | |
4 | | #include <common.h> |
5 | | #include <command.h> |
6 | | #include <linux/pagemap.h> |
7 | | #include <fs.h> |
8 | | #include <fcntl.h> |
9 | | #include <errno.h> |
10 | | #include <xfuncs.h> |
11 | | #include <malloc.h> |
12 | | #include <digest.h> |
13 | | #include <getopt.h> |
14 | | #include <libfile.h> |
15 | | |
16 | | #include "internal.h" |
17 | | |
18 | | int __do_digest(struct digest *d, unsigned char *sig, |
19 | | int argc, char *argv[]) |
20 | 0 | { |
21 | 0 | int ret = COMMAND_ERROR_USAGE; |
22 | 0 | int i; |
23 | 0 | unsigned char *hash; |
24 | |
|
25 | 0 | if (argc < 1) |
26 | 0 | goto err; |
27 | | |
28 | 0 | hash = calloc(digest_length(d), sizeof(unsigned char)); |
29 | 0 | if (!hash) { |
30 | 0 | perror("calloc"); |
31 | 0 | goto err; |
32 | 0 | } |
33 | | |
34 | 0 | while (*argv) { |
35 | 0 | char *filename = "/dev/mem"; |
36 | 0 | loff_t start = 0, size = MAX_LFS_FILESIZE; |
37 | 0 | int show_area = 1; |
38 | | |
39 | | /* arguments are either file, file+area or area */ |
40 | 0 | if (parse_area_spec(*argv, &start, &size)) { |
41 | 0 | filename = *argv; |
42 | 0 | show_area = 0; |
43 | 0 | if (argv[1] && !parse_area_spec(argv[1], &start, &size)) { |
44 | 0 | argv++; |
45 | 0 | show_area = 1; |
46 | 0 | } |
47 | 0 | } |
48 | |
|
49 | 0 | ret = digest_file_window(d, filename, |
50 | 0 | hash, sig, start, size); |
51 | 0 | if (ret < 0) { |
52 | 0 | ret = 1; |
53 | 0 | } else { |
54 | 0 | if (!sig) { |
55 | 0 | for (i = 0; i < digest_length(d); i++) |
56 | 0 | printf("%02x", hash[i]); |
57 | |
|
58 | 0 | printf(" %s", filename); |
59 | 0 | if (show_area) |
60 | 0 | printf("\t0x%08llx ... 0x%08llx", |
61 | 0 | start, start + size); |
62 | |
|
63 | 0 | puts("\n"); |
64 | 0 | } |
65 | 0 | } |
66 | |
|
67 | 0 | argv++; |
68 | 0 | } |
69 | |
|
70 | 0 | free(hash); |
71 | 0 | err: |
72 | 0 | digest_free(d); |
73 | |
|
74 | 0 | return ret; |
75 | 0 | } |
76 | | |
77 | | static void __maybe_unused prints_algo_help(void) |
78 | 0 | { |
79 | 0 | puts("\navailable algo:\n"); |
80 | 0 | digest_algo_prints("\t"); |
81 | 0 | } |
82 | | |
83 | | static int do_digest(int argc, char *argv[]) |
84 | 0 | { |
85 | 0 | struct digest *d; |
86 | 0 | unsigned char *tmp_key = NULL; |
87 | 0 | unsigned char *tmp_sig = NULL; |
88 | 0 | char *sig = NULL; |
89 | 0 | char *sigfile = NULL; |
90 | 0 | size_t siglen = 0; |
91 | 0 | char *key = NULL; |
92 | 0 | char *keyfile = NULL; |
93 | 0 | size_t keylen = 0; |
94 | 0 | size_t digestlen = 0; |
95 | 0 | char *algo = NULL; |
96 | 0 | int opt; |
97 | 0 | int ret = COMMAND_ERROR; |
98 | |
|
99 | 0 | if (argc < 2) |
100 | 0 | return COMMAND_ERROR_USAGE; |
101 | | |
102 | 0 | while((opt = getopt(argc, argv, "a:k:K:s:S:")) > 0) { |
103 | 0 | switch(opt) { |
104 | 0 | case 'k': |
105 | 0 | key = optarg; |
106 | 0 | keylen = strlen(key); |
107 | 0 | break; |
108 | 0 | case 'K': |
109 | 0 | keyfile = optarg; |
110 | 0 | break; |
111 | 0 | case 'a': |
112 | 0 | algo = optarg; |
113 | 0 | break; |
114 | 0 | case 's': |
115 | 0 | sig = optarg; |
116 | 0 | siglen = strlen(sig); |
117 | 0 | break; |
118 | 0 | case 'S': |
119 | 0 | sigfile = optarg; |
120 | 0 | break; |
121 | 0 | } |
122 | 0 | } |
123 | | |
124 | 0 | if (!algo) |
125 | 0 | return COMMAND_ERROR_USAGE; |
126 | | |
127 | 0 | d = digest_alloc(algo); |
128 | 0 | if (!d) { |
129 | 0 | eprintf("algo '%s' not found\n", algo); |
130 | 0 | return COMMAND_ERROR_USAGE; |
131 | 0 | } |
132 | | |
133 | 0 | argc -= optind; |
134 | 0 | argv += optind; |
135 | |
|
136 | 0 | if (keyfile) { |
137 | 0 | tmp_key = key = read_file(keyfile, &keylen); |
138 | 0 | if (!key) { |
139 | 0 | eprintf("file '%s' not found\n", keyfile); |
140 | 0 | goto err; |
141 | 0 | } |
142 | 0 | } |
143 | | |
144 | 0 | if (key) { |
145 | 0 | ret = digest_set_key(d, key, keylen); |
146 | 0 | free(tmp_key); |
147 | 0 | if (ret) |
148 | 0 | goto err; |
149 | 0 | } else if (digest_is_flags(d, DIGEST_ALGO_NEED_KEY)) { |
150 | 0 | eprintf("%s need a key to be used\n", digest_name(d)); |
151 | 0 | goto err; |
152 | 0 | } |
153 | | |
154 | 0 | if (sigfile) { |
155 | 0 | sig = tmp_sig = read_file(sigfile, &siglen); |
156 | 0 | if (!tmp_sig) { |
157 | 0 | eprintf("file '%s' not found\n", sigfile); |
158 | 0 | goto err; |
159 | 0 | } |
160 | 0 | } |
161 | | |
162 | 0 | if (sig) { |
163 | 0 | digestlen = digest_length(d); |
164 | 0 | if (siglen >= 2 * digestlen) { |
165 | 0 | if (!tmp_sig) |
166 | 0 | tmp_sig = xmalloc(digestlen); |
167 | |
|
168 | 0 | ret = hex2bin(tmp_sig, sig, digestlen); |
169 | 0 | if (ret) |
170 | 0 | goto err; |
171 | | |
172 | 0 | sig = tmp_sig; |
173 | 0 | } else if (siglen != digestlen) { |
174 | 0 | eprintf("%s wrong size %zu, expected %zu\n", |
175 | 0 | sigfile, siglen, digestlen); |
176 | 0 | ret = COMMAND_ERROR; |
177 | 0 | goto err; |
178 | 0 | } |
179 | 0 | } |
180 | | |
181 | 0 | ret = __do_digest(d, sig, argc, argv); |
182 | 0 | free(tmp_sig); |
183 | 0 | return ret; |
184 | | |
185 | 0 | err: |
186 | 0 | digest_free(d); |
187 | 0 | return ret; |
188 | 0 | } |
189 | | |
190 | | BAREBOX_CMD_HELP_START(digest) |
191 | | BAREBOX_CMD_HELP_TEXT("Calculate a digest over a FILE or a memory area.") |
192 | | BAREBOX_CMD_HELP_TEXT("Options:") |
193 | | BAREBOX_CMD_HELP_OPT ("-a <algo>\t", "hash or signature algorithm name/driver to use") |
194 | | BAREBOX_CMD_HELP_OPT ("-k <key>\t", "use supplied <key> (ASCII or hex) for MAC") |
195 | | BAREBOX_CMD_HELP_OPT ("-K <file>\t", "use key from <file> (binary) for MAC") |
196 | | BAREBOX_CMD_HELP_OPT ("-s <hex>\t", "verify data against supplied <hex> (hash, MAC or signature)") |
197 | | BAREBOX_CMD_HELP_OPT ("-S <file>\t", "verify data against <file> (hash, MAC or signature)") |
198 | | BAREBOX_CMD_HELP_END |
199 | | |
200 | | BAREBOX_CMD_START(digest) |
201 | | .cmd = do_digest, |
202 | | BAREBOX_CMD_DESC("calculate digest") |
203 | | BAREBOX_CMD_OPTS("-a <algo> [-k <key> | -K <file>] [-s <sig> | -S <file>] FILE|AREA") |
204 | | BAREBOX_CMD_GROUP(CMD_GRP_FILE) |
205 | | BAREBOX_CMD_HELP(cmd_digest_help) |
206 | | BAREBOX_CMD_USAGE(prints_algo_help) |
207 | | BAREBOX_CMD_END |