source: rtems-libbsd/freebsd/crypto/openssl/apps/dgst.c @ 0fecf49

5
Last change on this file since 0fecf49 was 0fecf49, checked in by Christian Mauderer <christian.mauderer@…>, on 03/26/19 at 09:19:22

bin/openssl: Import from FreeBSD.

  • Property mode set to 100644
File size: 15.2 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*
4 * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
5 *
6 * Licensed under the OpenSSL license (the "License").  You may not use
7 * this file except in compliance with the License.  You can obtain a copy
8 * in the file LICENSE in the source distribution or at
9 * https://www.openssl.org/source/license.html
10 */
11
12#include <stdio.h>
13#include <string.h>
14#include <stdlib.h>
15#include "apps.h"
16#include "progs.h"
17#include <openssl/bio.h>
18#include <openssl/err.h>
19#include <openssl/evp.h>
20#include <openssl/objects.h>
21#include <openssl/x509.h>
22#include <openssl/pem.h>
23#include <openssl/hmac.h>
24
25#undef BUFSIZE
26#define BUFSIZE 1024*8
27
28int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
29          EVP_PKEY *key, unsigned char *sigin, int siglen,
30          const char *sig_name, const char *md_name,
31          const char *file);
32
33typedef enum OPTION_choice {
34    OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
35    OPT_C, OPT_R, OPT_OUT, OPT_SIGN, OPT_PASSIN, OPT_VERIFY,
36    OPT_PRVERIFY, OPT_SIGNATURE, OPT_KEYFORM, OPT_ENGINE, OPT_ENGINE_IMPL,
37    OPT_HEX, OPT_BINARY, OPT_DEBUG, OPT_FIPS_FINGERPRINT,
38    OPT_HMAC, OPT_MAC, OPT_SIGOPT, OPT_MACOPT,
39    OPT_DIGEST,
40    OPT_R_ENUM
41} OPTION_CHOICE;
42
43const OPTIONS dgst_options[] = {
44    {OPT_HELP_STR, 1, '-', "Usage: %s [options] [file...]\n"},
45    {OPT_HELP_STR, 1, '-',
46        "  file... files to digest (default is stdin)\n"},
47    {"help", OPT_HELP, '-', "Display this summary"},
48    {"c", OPT_C, '-', "Print the digest with separating colons"},
49    {"r", OPT_R, '-', "Print the digest in coreutils format"},
50    {"out", OPT_OUT, '>', "Output to filename rather than stdout"},
51    {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
52    {"sign", OPT_SIGN, 's', "Sign digest using private key"},
53    {"verify", OPT_VERIFY, 's',
54     "Verify a signature using public key"},
55    {"prverify", OPT_PRVERIFY, 's',
56     "Verify a signature using private key"},
57    {"signature", OPT_SIGNATURE, '<', "File with signature to verify"},
58    {"keyform", OPT_KEYFORM, 'f', "Key file format (PEM or ENGINE)"},
59    {"hex", OPT_HEX, '-', "Print as hex dump"},
60    {"binary", OPT_BINARY, '-', "Print in binary form"},
61    {"d", OPT_DEBUG, '-', "Print debug info"},
62    {"debug", OPT_DEBUG, '-', "Print debug info"},
63    {"fips-fingerprint", OPT_FIPS_FINGERPRINT, '-',
64     "Compute HMAC with the key used in OpenSSL-FIPS fingerprint"},
65    {"hmac", OPT_HMAC, 's', "Create hashed MAC with key"},
66    {"mac", OPT_MAC, 's', "Create MAC (not necessarily HMAC)"},
67    {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
68    {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form or key"},
69    {"", OPT_DIGEST, '-', "Any supported digest"},
70    OPT_R_OPTIONS,
71#ifndef OPENSSL_NO_ENGINE
72    {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
73    {"engine_impl", OPT_ENGINE_IMPL, '-',
74     "Also use engine given by -engine for digest operations"},
75#endif
76    {NULL}
77};
78
79int dgst_main(int argc, char **argv)
80{
81    BIO *in = NULL, *inp, *bmd = NULL, *out = NULL;
82    ENGINE *e = NULL, *impl = NULL;
83    EVP_PKEY *sigkey = NULL;
84    STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL;
85    char *hmac_key = NULL;
86    char *mac_name = NULL;
87    char *passinarg = NULL, *passin = NULL;
88    const EVP_MD *md = NULL, *m;
89    const char *outfile = NULL, *keyfile = NULL, *prog = NULL;
90    const char *sigfile = NULL;
91    OPTION_CHOICE o;
92    int separator = 0, debug = 0, keyform = FORMAT_PEM, siglen = 0;
93    int i, ret = 1, out_bin = -1, want_pub = 0, do_verify = 0;
94    unsigned char *buf = NULL, *sigbuf = NULL;
95    int engine_impl = 0;
96
97    prog = opt_progname(argv[0]);
98    buf = app_malloc(BUFSIZE, "I/O buffer");
99    md = EVP_get_digestbyname(prog);
100
101    prog = opt_init(argc, argv, dgst_options);
102    while ((o = opt_next()) != OPT_EOF) {
103        switch (o) {
104        case OPT_EOF:
105        case OPT_ERR:
106 opthelp:
107            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
108            goto end;
109        case OPT_HELP:
110            opt_help(dgst_options);
111            ret = 0;
112            goto end;
113        case OPT_C:
114            separator = 1;
115            break;
116        case OPT_R:
117            separator = 2;
118            break;
119        case OPT_R_CASES:
120            if (!opt_rand(o))
121                goto end;
122            break;
123        case OPT_OUT:
124            outfile = opt_arg();
125            break;
126        case OPT_SIGN:
127            keyfile = opt_arg();
128            break;
129        case OPT_PASSIN:
130            passinarg = opt_arg();
131            break;
132        case OPT_VERIFY:
133            keyfile = opt_arg();
134            want_pub = do_verify = 1;
135            break;
136        case OPT_PRVERIFY:
137            keyfile = opt_arg();
138            do_verify = 1;
139            break;
140        case OPT_SIGNATURE:
141            sigfile = opt_arg();
142            break;
143        case OPT_KEYFORM:
144            if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
145                goto opthelp;
146            break;
147        case OPT_ENGINE:
148            e = setup_engine(opt_arg(), 0);
149            break;
150        case OPT_ENGINE_IMPL:
151            engine_impl = 1;
152            break;
153        case OPT_HEX:
154            out_bin = 0;
155            break;
156        case OPT_BINARY:
157            out_bin = 1;
158            break;
159        case OPT_DEBUG:
160            debug = 1;
161            break;
162        case OPT_FIPS_FINGERPRINT:
163            hmac_key = "etaonrishdlcupfm";
164            break;
165        case OPT_HMAC:
166            hmac_key = opt_arg();
167            break;
168        case OPT_MAC:
169            mac_name = opt_arg();
170            break;
171        case OPT_SIGOPT:
172            if (!sigopts)
173                sigopts = sk_OPENSSL_STRING_new_null();
174            if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
175                goto opthelp;
176            break;
177        case OPT_MACOPT:
178            if (!macopts)
179                macopts = sk_OPENSSL_STRING_new_null();
180            if (!macopts || !sk_OPENSSL_STRING_push(macopts, opt_arg()))
181                goto opthelp;
182            break;
183        case OPT_DIGEST:
184            if (!opt_md(opt_unknown(), &m))
185                goto opthelp;
186            md = m;
187            break;
188        }
189    }
190    argc = opt_num_rest();
191    argv = opt_rest();
192    if (keyfile != NULL && argc > 1) {
193        BIO_printf(bio_err, "%s: Can only sign or verify one file.\n", prog);
194        goto end;
195    }
196
197    if (do_verify && sigfile == NULL) {
198        BIO_printf(bio_err,
199                   "No signature to verify: use the -signature option\n");
200        goto end;
201    }
202    if (engine_impl)
203        impl = e;
204
205    in = BIO_new(BIO_s_file());
206    bmd = BIO_new(BIO_f_md());
207    if ((in == NULL) || (bmd == NULL)) {
208        ERR_print_errors(bio_err);
209        goto end;
210    }
211
212    if (debug) {
213        BIO_set_callback(in, BIO_debug_callback);
214        /* needed for windows 3.1 */
215        BIO_set_callback_arg(in, (char *)bio_err);
216    }
217
218    if (!app_passwd(passinarg, NULL, &passin, NULL)) {
219        BIO_printf(bio_err, "Error getting password\n");
220        goto end;
221    }
222
223    if (out_bin == -1) {
224        if (keyfile != NULL)
225            out_bin = 1;
226        else
227            out_bin = 0;
228    }
229
230    out = bio_open_default(outfile, 'w', out_bin ? FORMAT_BINARY : FORMAT_TEXT);
231    if (out == NULL)
232        goto end;
233
234    if ((!(mac_name == NULL) + !(keyfile == NULL) + !(hmac_key == NULL)) > 1) {
235        BIO_printf(bio_err, "MAC and Signing key cannot both be specified\n");
236        goto end;
237    }
238
239    if (keyfile != NULL) {
240        int type;
241
242        if (want_pub)
243            sigkey = load_pubkey(keyfile, keyform, 0, NULL, e, "key file");
244        else
245            sigkey = load_key(keyfile, keyform, 0, passin, e, "key file");
246        if (sigkey == NULL) {
247            /*
248             * load_[pub]key() has already printed an appropriate message
249             */
250            goto end;
251        }
252        type = EVP_PKEY_id(sigkey);
253        if (type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448) {
254            /*
255             * We implement PureEdDSA for these which doesn't have a separate
256             * digest, and only supports one shot.
257             */
258            BIO_printf(bio_err, "Key type not supported for this operation\n");
259            goto end;
260        }
261    }
262
263    if (mac_name != NULL) {
264        EVP_PKEY_CTX *mac_ctx = NULL;
265        int r = 0;
266        if (!init_gen_str(&mac_ctx, mac_name, impl, 0))
267            goto mac_end;
268        if (macopts != NULL) {
269            char *macopt;
270            for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++) {
271                macopt = sk_OPENSSL_STRING_value(macopts, i);
272                if (pkey_ctrl_string(mac_ctx, macopt) <= 0) {
273                    BIO_printf(bio_err,
274                               "MAC parameter error \"%s\"\n", macopt);
275                    ERR_print_errors(bio_err);
276                    goto mac_end;
277                }
278            }
279        }
280        if (EVP_PKEY_keygen(mac_ctx, &sigkey) <= 0) {
281            BIO_puts(bio_err, "Error generating key\n");
282            ERR_print_errors(bio_err);
283            goto mac_end;
284        }
285        r = 1;
286 mac_end:
287        EVP_PKEY_CTX_free(mac_ctx);
288        if (r == 0)
289            goto end;
290    }
291
292    if (hmac_key != NULL) {
293        sigkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, impl,
294                                              (unsigned char *)hmac_key, -1);
295        if (sigkey == NULL)
296            goto end;
297    }
298
299    if (sigkey != NULL) {
300        EVP_MD_CTX *mctx = NULL;
301        EVP_PKEY_CTX *pctx = NULL;
302        int r;
303        if (!BIO_get_md_ctx(bmd, &mctx)) {
304            BIO_printf(bio_err, "Error getting context\n");
305            ERR_print_errors(bio_err);
306            goto end;
307        }
308        if (do_verify)
309            r = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey);
310        else
311            r = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey);
312        if (!r) {
313            BIO_printf(bio_err, "Error setting context\n");
314            ERR_print_errors(bio_err);
315            goto end;
316        }
317        if (sigopts != NULL) {
318            char *sigopt;
319            for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
320                sigopt = sk_OPENSSL_STRING_value(sigopts, i);
321                if (pkey_ctrl_string(pctx, sigopt) <= 0) {
322                    BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt);
323                    ERR_print_errors(bio_err);
324                    goto end;
325                }
326            }
327        }
328    }
329    /* we use md as a filter, reading from 'in' */
330    else {
331        EVP_MD_CTX *mctx = NULL;
332        if (!BIO_get_md_ctx(bmd, &mctx)) {
333            BIO_printf(bio_err, "Error getting context\n");
334            ERR_print_errors(bio_err);
335            goto end;
336        }
337        if (md == NULL)
338            md = EVP_sha256();
339        if (!EVP_DigestInit_ex(mctx, md, impl)) {
340            BIO_printf(bio_err, "Error setting digest\n");
341            ERR_print_errors(bio_err);
342            goto end;
343        }
344    }
345
346    if (sigfile != NULL && sigkey != NULL) {
347        BIO *sigbio = BIO_new_file(sigfile, "rb");
348        if (sigbio == NULL) {
349            BIO_printf(bio_err, "Error opening signature file %s\n", sigfile);
350            ERR_print_errors(bio_err);
351            goto end;
352        }
353        siglen = EVP_PKEY_size(sigkey);
354        sigbuf = app_malloc(siglen, "signature buffer");
355        siglen = BIO_read(sigbio, sigbuf, siglen);
356        BIO_free(sigbio);
357        if (siglen <= 0) {
358            BIO_printf(bio_err, "Error reading signature file %s\n", sigfile);
359            ERR_print_errors(bio_err);
360            goto end;
361        }
362    }
363    inp = BIO_push(bmd, in);
364
365    if (md == NULL) {
366        EVP_MD_CTX *tctx;
367        BIO_get_md_ctx(bmd, &tctx);
368        md = EVP_MD_CTX_md(tctx);
369    }
370
371    if (argc == 0) {
372        BIO_set_fp(in, stdin, BIO_NOCLOSE);
373        ret = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf,
374                    siglen, NULL, NULL, "stdin");
375    } else {
376        const char *md_name = NULL, *sig_name = NULL;
377        if (!out_bin) {
378            if (sigkey != NULL) {
379                const EVP_PKEY_ASN1_METHOD *ameth;
380                ameth = EVP_PKEY_get0_asn1(sigkey);
381                if (ameth)
382                    EVP_PKEY_asn1_get0_info(NULL, NULL,
383                                            NULL, NULL, &sig_name, ameth);
384            }
385            if (md != NULL)
386                md_name = EVP_MD_name(md);
387        }
388        ret = 0;
389        for (i = 0; i < argc; i++) {
390            int r;
391            if (BIO_read_filename(in, argv[i]) <= 0) {
392                perror(argv[i]);
393                ret++;
394                continue;
395            } else {
396                r = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf,
397                          siglen, sig_name, md_name, argv[i]);
398            }
399            if (r)
400                ret = r;
401            (void)BIO_reset(bmd);
402        }
403    }
404 end:
405    OPENSSL_clear_free(buf, BUFSIZE);
406    BIO_free(in);
407    OPENSSL_free(passin);
408    BIO_free_all(out);
409    EVP_PKEY_free(sigkey);
410    sk_OPENSSL_STRING_free(sigopts);
411    sk_OPENSSL_STRING_free(macopts);
412    OPENSSL_free(sigbuf);
413    BIO_free(bmd);
414    release_engine(e);
415    return ret;
416}
417
418int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
419          EVP_PKEY *key, unsigned char *sigin, int siglen,
420          const char *sig_name, const char *md_name,
421          const char *file)
422{
423    size_t len;
424    int i;
425
426    for (;;) {
427        i = BIO_read(bp, (char *)buf, BUFSIZE);
428        if (i < 0) {
429            BIO_printf(bio_err, "Read Error in %s\n", file);
430            ERR_print_errors(bio_err);
431            return 1;
432        }
433        if (i == 0)
434            break;
435    }
436    if (sigin != NULL) {
437        EVP_MD_CTX *ctx;
438        BIO_get_md_ctx(bp, &ctx);
439        i = EVP_DigestVerifyFinal(ctx, sigin, (unsigned int)siglen);
440        if (i > 0) {
441            BIO_printf(out, "Verified OK\n");
442        } else if (i == 0) {
443            BIO_printf(out, "Verification Failure\n");
444            return 1;
445        } else {
446            BIO_printf(bio_err, "Error Verifying Data\n");
447            ERR_print_errors(bio_err);
448            return 1;
449        }
450        return 0;
451    }
452    if (key != NULL) {
453        EVP_MD_CTX *ctx;
454        BIO_get_md_ctx(bp, &ctx);
455        len = BUFSIZE;
456        if (!EVP_DigestSignFinal(ctx, buf, &len)) {
457            BIO_printf(bio_err, "Error Signing Data\n");
458            ERR_print_errors(bio_err);
459            return 1;
460        }
461    } else {
462        len = BIO_gets(bp, (char *)buf, BUFSIZE);
463        if ((int)len < 0) {
464            ERR_print_errors(bio_err);
465            return 1;
466        }
467    }
468
469    if (binout) {
470        BIO_write(out, buf, len);
471    } else if (sep == 2) {
472        for (i = 0; i < (int)len; i++)
473            BIO_printf(out, "%02x", buf[i]);
474        BIO_printf(out, " *%s\n", file);
475    } else {
476        if (sig_name != NULL) {
477            BIO_puts(out, sig_name);
478            if (md_name != NULL)
479                BIO_printf(out, "-%s", md_name);
480            BIO_printf(out, "(%s)= ", file);
481        } else if (md_name != NULL) {
482            BIO_printf(out, "%s(%s)= ", md_name, file);
483        } else {
484            BIO_printf(out, "(%s)= ", file);
485        }
486        for (i = 0; i < (int)len; i++) {
487            if (sep && (i != 0))
488                BIO_printf(out, ":");
489            BIO_printf(out, "%02x", buf[i]);
490        }
491        BIO_printf(out, "\n");
492    }
493    return 0;
494}
Note: See TracBrowser for help on using the repository browser.