]>
Commit | Line | Data |
---|---|---|
4d768e96 SL |
1 | /* |
2 | * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
4 | * Licensed under the OpenSSL license (the "License"). You may not use | |
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> | |
17 | ||
18 | #undef BUFSIZE | |
19 | #define BUFSIZE 1024*8 | |
20 | ||
21 | typedef enum OPTION_choice { | |
22 | OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, | |
23 | OPT_MACOPT, OPT_BIN, OPT_IN, OPT_OUT | |
24 | } OPTION_CHOICE; | |
25 | ||
26 | const OPTIONS mac_options[] = { | |
27 | {OPT_HELP_STR, 1, '-', "Usage: %s [options] mac_name\n"}, | |
28 | {OPT_HELP_STR, 1, '-', "mac_name\t\t MAC algorithm (See list " | |
29 | "-mac-algorithms)"}, | |
30 | {"help", OPT_HELP, '-', "Display this summary"}, | |
31 | {"macopt", OPT_MACOPT, 's', "MAC algorithm control parameters in n:v form. " | |
32 | "See 'Supported Controls' in the EVP_MAC_ docs"}, | |
33 | {"in", OPT_IN, '<', "Input file to MAC (default is stdin)"}, | |
34 | {"out", OPT_OUT, '>', "Output to filename rather than stdout"}, | |
35 | {"binary", OPT_BIN, '-', "Output in binary format (Default is hexadecimal " | |
36 | "output)"}, | |
37 | {NULL} | |
38 | }; | |
39 | ||
40 | static int mac_ctrl_string(EVP_MAC_CTX *ctx, const char *value) | |
41 | { | |
42 | int rv; | |
43 | char *stmp, *vtmp = NULL; | |
44 | ||
45 | stmp = OPENSSL_strdup(value); | |
46 | if (stmp == NULL) | |
47 | return -1; | |
48 | vtmp = strchr(stmp, ':'); | |
49 | if (vtmp != NULL) { | |
50 | *vtmp = 0; | |
51 | vtmp++; | |
52 | } | |
53 | rv = EVP_MAC_ctrl_str(ctx, stmp, vtmp); | |
54 | OPENSSL_free(stmp); | |
55 | return rv; | |
56 | } | |
57 | ||
58 | int mac_main(int argc, char **argv) | |
59 | { | |
60 | int ret = 1; | |
61 | char *prog; | |
62 | const EVP_MAC *mac = NULL; | |
63 | OPTION_CHOICE o; | |
64 | EVP_MAC_CTX *ctx = NULL; | |
65 | STACK_OF(OPENSSL_STRING) *opts = NULL; | |
66 | unsigned char *buf = NULL; | |
67 | size_t len; | |
68 | int i; | |
69 | BIO *in = NULL, *out = NULL; | |
70 | const char *outfile = NULL; | |
71 | const char *infile = NULL; | |
72 | int out_bin = 0; | |
73 | int inform = FORMAT_BINARY; | |
74 | ||
75 | prog = opt_init(argc, argv, mac_options); | |
76 | buf = app_malloc(BUFSIZE, "I/O buffer"); | |
77 | while ((o = opt_next()) != OPT_EOF) { | |
78 | switch (o) { | |
a3c62426 | 79 | default: |
4d768e96 SL |
80 | opthelp: |
81 | BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); | |
82 | goto err; | |
83 | case OPT_HELP: | |
84 | opt_help(mac_options); | |
85 | ret = 0; | |
86 | goto err; | |
87 | case OPT_BIN: | |
88 | out_bin = 1; | |
89 | break; | |
90 | case OPT_IN: | |
91 | infile = opt_arg(); | |
92 | break; | |
93 | case OPT_OUT: | |
94 | outfile = opt_arg(); | |
95 | break; | |
96 | case OPT_MACOPT: | |
97 | if (opts == NULL) | |
98 | opts = sk_OPENSSL_STRING_new_null(); | |
99 | if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg())) | |
100 | goto opthelp; | |
101 | break; | |
102 | } | |
103 | } | |
104 | argc = opt_num_rest(); | |
105 | argv = opt_rest(); | |
106 | ||
107 | if (argc != 1) { | |
108 | BIO_printf(bio_err, "Invalid number of extra arguments\n"); | |
109 | goto opthelp; | |
110 | } | |
111 | ||
112 | mac = EVP_get_macbyname(argv[0]); | |
113 | if (mac == NULL) { | |
114 | BIO_printf(bio_err, "Invalid MAC name %s\n", argv[0]); | |
115 | goto opthelp; | |
116 | } | |
117 | ||
118 | ctx = EVP_MAC_CTX_new(mac); | |
119 | if (ctx == NULL) | |
120 | goto err; | |
121 | ||
122 | if (opts != NULL) { | |
123 | for (i = 0; i < sk_OPENSSL_STRING_num(opts); i++) { | |
124 | char *opt = sk_OPENSSL_STRING_value(opts, i); | |
125 | if (mac_ctrl_string(ctx, opt) <= 0) { | |
126 | BIO_printf(bio_err, "MAC parameter error '%s'\n", opt); | |
127 | ERR_print_errors(bio_err); | |
128 | goto err; | |
129 | } | |
130 | } | |
131 | } | |
132 | ||
133 | /* Use text mode for stdin */ | |
134 | if (infile == NULL || strcmp(infile, "-") == 0) | |
135 | inform = FORMAT_TEXT; | |
136 | in = bio_open_default(infile, 'r', inform); | |
137 | if (in == NULL) | |
138 | goto err; | |
139 | ||
140 | out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT); | |
141 | if (out == NULL) | |
142 | goto err; | |
143 | ||
144 | if (!EVP_MAC_init(ctx)) { | |
145 | BIO_printf(bio_err, "EVP_MAC_Init failed\n"); | |
146 | goto err; | |
147 | } | |
148 | ||
149 | ||
150 | for (;;) { | |
151 | i = BIO_read(in, (char *)buf, BUFSIZE); | |
152 | if (i < 0) { | |
153 | BIO_printf(bio_err, "Read Error in '%s'\n", infile); | |
154 | goto err; | |
155 | } | |
156 | if (i == 0) | |
157 | break; | |
158 | if (!EVP_MAC_update(ctx, buf, i)) { | |
159 | BIO_printf(bio_err, "EVP_MAC_update failed\n"); | |
160 | goto err; | |
161 | } | |
162 | } | |
163 | ||
164 | if (!EVP_MAC_final(ctx, NULL, &len)) { | |
165 | BIO_printf(bio_err, "EVP_MAC_final failed\n"); | |
166 | goto err; | |
167 | } | |
168 | if (len > BUFSIZE) { | |
169 | BIO_printf(bio_err, "output len is too large\n"); | |
170 | goto err; | |
171 | } | |
172 | ||
173 | if (!EVP_MAC_final(ctx, buf, &len)) { | |
174 | BIO_printf(bio_err, "EVP_MAC_final failed\n"); | |
175 | goto err; | |
176 | } | |
177 | ||
178 | if (out_bin) { | |
179 | BIO_write(out, buf, len); | |
180 | } else { | |
181 | if (outfile == NULL) | |
182 | BIO_printf(out,"\n"); | |
183 | for (i = 0; i < (int)len; ++i) | |
184 | BIO_printf(out, "%02X", buf[i]); | |
185 | if (outfile == NULL) | |
186 | BIO_printf(out,"\n"); | |
187 | } | |
188 | ||
189 | ret = 0; | |
190 | err: | |
191 | if (ret != 0) | |
192 | ERR_print_errors(bio_err); | |
193 | OPENSSL_clear_free(buf, BUFSIZE); | |
194 | sk_OPENSSL_STRING_free(opts); | |
195 | BIO_free(in); | |
196 | BIO_free(out); | |
197 | EVP_MAC_CTX_free(ctx); | |
198 | return ret; | |
199 | } |