]>
Commit | Line | Data |
---|---|---|
4d768e96 | 1 | /* |
a28d06f3 | 2 | * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. |
4d768e96 | 3 | * |
a6ed19dc | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
4d768e96 SL |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
10 | #include <string.h> | |
11 | ||
12 | #include "apps.h" | |
13 | #include "progs.h" | |
14 | #include <openssl/bio.h> | |
15 | #include <openssl/err.h> | |
16 | #include <openssl/evp.h> | |
d747fb2e | 17 | #include <openssl/params.h> |
0f4fb647 | 18 | #include <openssl/core_names.h> |
4d768e96 SL |
19 | |
20 | #undef BUFSIZE | |
21 | #define BUFSIZE 1024*8 | |
22 | ||
23 | typedef enum OPTION_choice { | |
b0f96018 | 24 | OPT_COMMON, |
6bd4e3f2 | 25 | OPT_MACOPT, OPT_BIN, OPT_IN, OPT_OUT, |
0f4fb647 | 26 | OPT_CIPHER, OPT_DIGEST, |
6bd4e3f2 | 27 | OPT_PROV_ENUM |
4d768e96 SL |
28 | } OPTION_CHOICE; |
29 | ||
30 | const OPTIONS mac_options[] = { | |
31 | {OPT_HELP_STR, 1, '-', "Usage: %s [options] mac_name\n"}, | |
5388f986 RS |
32 | |
33 | OPT_SECTION("General"), | |
4d768e96 | 34 | {"help", OPT_HELP, '-', "Display this summary"}, |
92de469f | 35 | {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form"}, |
0f4fb647 P |
36 | {"cipher", OPT_CIPHER, 's', "Cipher"}, |
37 | {"digest", OPT_DIGEST, 's', "Digest"}, | |
92de469f | 38 | {OPT_MORE_STR, 1, '-', "See 'PARAMETER NAMES' in the EVP_MAC_ docs"}, |
5388f986 RS |
39 | |
40 | OPT_SECTION("Input"), | |
4d768e96 | 41 | {"in", OPT_IN, '<', "Input file to MAC (default is stdin)"}, |
5388f986 RS |
42 | |
43 | OPT_SECTION("Output"), | |
4d768e96 | 44 | {"out", OPT_OUT, '>', "Output to filename rather than stdout"}, |
92de469f RS |
45 | {"binary", OPT_BIN, '-', |
46 | "Output in binary format (default is hexadecimal)"}, | |
47 | ||
6bd4e3f2 P |
48 | OPT_PROV_OPTIONS, |
49 | ||
92de469f RS |
50 | OPT_PARAMETERS(), |
51 | {"mac_name", 0, 0, "MAC algorithm"}, | |
4d768e96 SL |
52 | {NULL} |
53 | }; | |
54 | ||
0f4fb647 P |
55 | static char *alloc_mac_algorithm_name(STACK_OF(OPENSSL_STRING) **optp, |
56 | const char *name, const char *arg) | |
57 | { | |
58 | size_t len = strlen(name) + strlen(arg) + 2; | |
54e1c14a | 59 | char *res; |
0f4fb647 P |
60 | |
61 | if (*optp == NULL) | |
62 | *optp = sk_OPENSSL_STRING_new_null(); | |
63 | if (*optp == NULL) | |
64 | return NULL; | |
65 | ||
54e1c14a | 66 | res = app_malloc(len, "algorithm name"); |
0f4fb647 P |
67 | BIO_snprintf(res, len, "%s:%s", name, arg); |
68 | if (sk_OPENSSL_STRING_push(*optp, res)) | |
69 | return res; | |
70 | OPENSSL_free(res); | |
71 | return NULL; | |
72 | } | |
73 | ||
4d768e96 SL |
74 | int mac_main(int argc, char **argv) |
75 | { | |
76 | int ret = 1; | |
77 | char *prog; | |
d747fb2e | 78 | EVP_MAC *mac = NULL; |
4d768e96 SL |
79 | OPTION_CHOICE o; |
80 | EVP_MAC_CTX *ctx = NULL; | |
81 | STACK_OF(OPENSSL_STRING) *opts = NULL; | |
82 | unsigned char *buf = NULL; | |
83 | size_t len; | |
84 | int i; | |
85 | BIO *in = NULL, *out = NULL; | |
86 | const char *outfile = NULL; | |
87 | const char *infile = NULL; | |
88 | int out_bin = 0; | |
89 | int inform = FORMAT_BINARY; | |
0f4fb647 | 90 | char *digest = NULL, *cipher = NULL; |
2211bf6b | 91 | OSSL_PARAM *params = NULL; |
4d768e96 SL |
92 | |
93 | prog = opt_init(argc, argv, mac_options); | |
94 | buf = app_malloc(BUFSIZE, "I/O buffer"); | |
95 | while ((o = opt_next()) != OPT_EOF) { | |
96 | switch (o) { | |
a3c62426 | 97 | default: |
4d768e96 SL |
98 | opthelp: |
99 | BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); | |
100 | goto err; | |
101 | case OPT_HELP: | |
102 | opt_help(mac_options); | |
103 | ret = 0; | |
104 | goto err; | |
105 | case OPT_BIN: | |
106 | out_bin = 1; | |
107 | break; | |
108 | case OPT_IN: | |
109 | infile = opt_arg(); | |
110 | break; | |
111 | case OPT_OUT: | |
112 | outfile = opt_arg(); | |
113 | break; | |
114 | case OPT_MACOPT: | |
115 | if (opts == NULL) | |
116 | opts = sk_OPENSSL_STRING_new_null(); | |
117 | if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg())) | |
118 | goto opthelp; | |
119 | break; | |
0f4fb647 P |
120 | case OPT_CIPHER: |
121 | OPENSSL_free(cipher); | |
122 | cipher = alloc_mac_algorithm_name(&opts, "cipher", opt_arg()); | |
123 | if (cipher == NULL) | |
124 | goto opthelp; | |
125 | break; | |
126 | case OPT_DIGEST: | |
127 | OPENSSL_free(digest); | |
128 | digest = alloc_mac_algorithm_name(&opts, "digest", opt_arg()); | |
129 | if (digest == NULL) | |
130 | goto opthelp; | |
131 | break; | |
6bd4e3f2 P |
132 | case OPT_PROV_CASES: |
133 | if (!opt_provider(o)) | |
134 | goto err; | |
135 | break; | |
4d768e96 SL |
136 | } |
137 | } | |
021410ea RS |
138 | |
139 | /* One argument, the MAC name. */ | |
4d768e96 SL |
140 | argc = opt_num_rest(); |
141 | argv = opt_rest(); | |
021410ea | 142 | if (argc != 1) |
4d768e96 | 143 | goto opthelp; |
4d768e96 | 144 | |
7dc67708 | 145 | mac = EVP_MAC_fetch(app_get0_libctx(), argv[0], app_get0_propq()); |
4d768e96 SL |
146 | if (mac == NULL) { |
147 | BIO_printf(bio_err, "Invalid MAC name %s\n", argv[0]); | |
148 | goto opthelp; | |
149 | } | |
150 | ||
865adf97 | 151 | ctx = EVP_MAC_CTX_new(mac); |
4d768e96 SL |
152 | if (ctx == NULL) |
153 | goto err; | |
154 | ||
155 | if (opts != NULL) { | |
d747fb2e RL |
156 | int ok = 1; |
157 | ||
2211bf6b P |
158 | params = app_params_new_from_opts(opts, |
159 | EVP_MAC_settable_ctx_params(mac)); | |
95214b43 SL |
160 | if (params == NULL) |
161 | goto err; | |
162 | ||
865adf97 | 163 | if (!EVP_MAC_CTX_set_params(ctx, params)) { |
95214b43 SL |
164 | BIO_printf(bio_err, "MAC parameter error\n"); |
165 | ERR_print_errors(bio_err); | |
166 | ok = 0; | |
d747fb2e | 167 | } |
95214b43 | 168 | app_params_free(params); |
d747fb2e RL |
169 | if (!ok) |
170 | goto err; | |
4d768e96 SL |
171 | } |
172 | ||
173 | /* Use text mode for stdin */ | |
174 | if (infile == NULL || strcmp(infile, "-") == 0) | |
175 | inform = FORMAT_TEXT; | |
176 | in = bio_open_default(infile, 'r', inform); | |
177 | if (in == NULL) | |
178 | goto err; | |
179 | ||
180 | out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT); | |
181 | if (out == NULL) | |
182 | goto err; | |
183 | ||
2211bf6b | 184 | if (!EVP_MAC_init(ctx, NULL, 0, NULL)) { |
4d768e96 SL |
185 | BIO_printf(bio_err, "EVP_MAC_Init failed\n"); |
186 | goto err; | |
187 | } | |
188 | ||
29f5727b | 189 | while (BIO_pending(in) || !BIO_eof(in)) { |
4d768e96 SL |
190 | i = BIO_read(in, (char *)buf, BUFSIZE); |
191 | if (i < 0) { | |
192 | BIO_printf(bio_err, "Read Error in '%s'\n", infile); | |
29f5727b | 193 | ERR_print_errors(bio_err); |
4d768e96 SL |
194 | goto err; |
195 | } | |
196 | if (i == 0) | |
197 | break; | |
198 | if (!EVP_MAC_update(ctx, buf, i)) { | |
199 | BIO_printf(bio_err, "EVP_MAC_update failed\n"); | |
200 | goto err; | |
201 | } | |
202 | } | |
203 | ||
d747fb2e | 204 | if (!EVP_MAC_final(ctx, NULL, &len, 0)) { |
4d768e96 SL |
205 | BIO_printf(bio_err, "EVP_MAC_final failed\n"); |
206 | goto err; | |
207 | } | |
208 | if (len > BUFSIZE) { | |
209 | BIO_printf(bio_err, "output len is too large\n"); | |
210 | goto err; | |
211 | } | |
212 | ||
d747fb2e | 213 | if (!EVP_MAC_final(ctx, buf, &len, BUFSIZE)) { |
4d768e96 SL |
214 | BIO_printf(bio_err, "EVP_MAC_final failed\n"); |
215 | goto err; | |
216 | } | |
217 | ||
218 | if (out_bin) { | |
219 | BIO_write(out, buf, len); | |
220 | } else { | |
4d768e96 SL |
221 | for (i = 0; i < (int)len; ++i) |
222 | BIO_printf(out, "%02X", buf[i]); | |
223 | if (outfile == NULL) | |
1287dabd | 224 | BIO_printf(out, "\n"); |
4d768e96 SL |
225 | } |
226 | ||
227 | ret = 0; | |
228 | err: | |
229 | if (ret != 0) | |
230 | ERR_print_errors(bio_err); | |
231 | OPENSSL_clear_free(buf, BUFSIZE); | |
0f4fb647 P |
232 | OPENSSL_free(cipher); |
233 | OPENSSL_free(digest); | |
4d768e96 SL |
234 | sk_OPENSSL_STRING_free(opts); |
235 | BIO_free(in); | |
236 | BIO_free(out); | |
865adf97 | 237 | EVP_MAC_CTX_free(ctx); |
d747fb2e | 238 | EVP_MAC_free(mac); |
4d768e96 SL |
239 | return ret; |
240 | } |