]>
git.ipfire.org Git - thirdparty/openssl.git/blob - apps/dgst.c
cbd4b4e2bec367fac2a7a151d86283ef029dc22d
2 * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (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
15 #include <openssl/bio.h>
16 #include <openssl/err.h>
17 #include <openssl/evp.h>
18 #include <openssl/objects.h>
19 #include <openssl/x509.h>
20 #include <openssl/pem.h>
21 #include <openssl/hmac.h>
25 #define BUFSIZE 1024*8
27 int do_fp ( BIO
* out
, unsigned char * buf
, BIO
* bp
, int sep
, int binout
, int xoflen
,
28 EVP_PKEY
* key
, unsigned char * sigin
, int siglen
,
29 const char * sig_name
, const char * md_name
,
31 static void show_digests ( const OBJ_NAME
* name
, void * bio_
);
33 struct doall_dgst_digests
{
38 typedef enum OPTION_choice
{
41 OPT_C
, OPT_R
, OPT_OUT
, OPT_SIGN
, OPT_PASSIN
, OPT_VERIFY
,
42 OPT_PRVERIFY
, OPT_SIGNATURE
, OPT_KEYFORM
, OPT_ENGINE
, OPT_ENGINE_IMPL
,
43 OPT_HEX
, OPT_BINARY
, OPT_DEBUG
, OPT_FIPS_FINGERPRINT
,
44 OPT_HMAC
, OPT_MAC
, OPT_SIGOPT
, OPT_MACOPT
, OPT_XOFLEN
,
46 OPT_R_ENUM
, OPT_PROV_ENUM
49 const OPTIONS dgst_options
[] = {
50 { OPT_HELP_STR
, 1 , '-' , "Usage: %s [options] [file...] \n " },
52 OPT_SECTION ( "General" ),
53 { "help" , OPT_HELP
, '-' , "Display this summary" },
54 { "list" , OPT_LIST
, '-' , "List digests" },
55 #ifndef OPENSSL_NO_ENGINE
56 { "engine" , OPT_ENGINE
, 's' , "Use engine e, possibly a hardware device" },
57 { "engine_impl" , OPT_ENGINE_IMPL
, '-' ,
58 "Also use engine given by -engine for digest operations" },
60 { "passin" , OPT_PASSIN
, 's' , "Input file pass phrase source" },
62 OPT_SECTION ( "Output" ),
63 { "c" , OPT_C
, '-' , "Print the digest with separating colons" },
64 { "r" , OPT_R
, '-' , "Print the digest in coreutils format" },
65 { "out" , OPT_OUT
, '>' , "Output to filename rather than stdout" },
66 { "keyform" , OPT_KEYFORM
, 'f' , "Key file format (ENGINE, other values ignored)" },
67 { "hex" , OPT_HEX
, '-' , "Print as hex dump" },
68 { "binary" , OPT_BINARY
, '-' , "Print in binary form" },
69 { "xoflen" , OPT_XOFLEN
, 'p' , "Output length for XOF algorithms. To obtain the maximum security strength set this to 32 (or greater) for SHAKE128, and 64 (or greater) for SHAKE256" },
70 { "d" , OPT_DEBUG
, '-' , "Print debug info" },
71 { "debug" , OPT_DEBUG
, '-' , "Print debug info" },
73 OPT_SECTION ( "Signing" ),
74 { "sign" , OPT_SIGN
, 's' , "Sign digest using private key" },
75 { "verify" , OPT_VERIFY
, 's' , "Verify a signature using public key" },
76 { "prverify" , OPT_PRVERIFY
, 's' , "Verify a signature using private key" },
77 { "sigopt" , OPT_SIGOPT
, 's' , "Signature parameter in n:v form" },
78 { "signature" , OPT_SIGNATURE
, '<' , "File with signature to verify" },
79 { "hmac" , OPT_HMAC
, 's' , "Create hashed MAC with key" },
80 { "mac" , OPT_MAC
, 's' , "Create MAC (not necessarily HMAC)" },
81 { "macopt" , OPT_MACOPT
, 's' , "MAC algorithm parameters in n:v form or key" },
82 { "" , OPT_DIGEST
, '-' , "Any supported digest" },
83 { "fips-fingerprint" , OPT_FIPS_FINGERPRINT
, '-' ,
84 "Compute HMAC with the key used in OpenSSL-FIPS fingerprint" },
90 { "file" , 0 , 0 , "Files to digest (optional; default is stdin)" },
94 int dgst_main ( int argc
, char ** argv
)
96 BIO
* in
= NULL
, * inp
, * bmd
= NULL
, * out
= NULL
;
97 ENGINE
* e
= NULL
, * impl
= NULL
;
98 EVP_PKEY
* sigkey
= NULL
;
99 STACK_OF ( OPENSSL_STRING
) * sigopts
= NULL
, * macopts
= NULL
;
100 char * hmac_key
= NULL
;
101 char * mac_name
= NULL
, * digestname
= NULL
;
102 char * passinarg
= NULL
, * passin
= NULL
;
104 const char * outfile
= NULL
, * keyfile
= NULL
, * prog
= NULL
;
105 const char * sigfile
= NULL
;
106 const char * md_name
= NULL
;
108 int separator
= 0 , debug
= 0 , keyform
= FORMAT_UNDEF
, siglen
= 0 ;
109 int i
, ret
= EXIT_FAILURE
, out_bin
= - 1 , want_pub
= 0 , do_verify
= 0 ;
111 unsigned char * buf
= NULL
, * sigbuf
= NULL
;
113 struct doall_dgst_digests dec
;
115 buf
= app_malloc ( BUFSIZE
, "I/O buffer" );
116 md
= ( EVP_MD
*) EVP_get_digestbyname ( argv
[ 0 ]);
118 digestname
= argv
[ 0 ];
120 opt_set_unknown_name ( "digest" );
121 prog
= opt_init ( argc
, argv
, dgst_options
);
122 while (( o
= opt_next ()) != OPT_EOF
) {
127 BIO_printf ( bio_err
, "%s: Use -help for summary. \n " , prog
);
130 opt_help ( dgst_options
);
134 BIO_printf ( bio_out
, "Supported digests: \n " );
137 OBJ_NAME_do_all_sorted ( OBJ_NAME_TYPE_MD_METH
,
139 BIO_printf ( bio_out
, " \n " );
159 passinarg
= opt_arg ();
163 want_pub
= do_verify
= 1 ;
173 if (! opt_format ( opt_arg (), OPT_FMT_ANY
, & keyform
))
177 e
= setup_engine ( opt_arg (), 0 );
179 case OPT_ENGINE_IMPL
:
189 xoflen
= atoi ( opt_arg ());
194 case OPT_FIPS_FINGERPRINT
:
195 hmac_key
= "etaonrishdlcupfm" ;
198 hmac_key
= opt_arg ();
201 mac_name
= opt_arg ();
205 sigopts
= sk_OPENSSL_STRING_new_null ();
206 if (! sigopts
|| ! sk_OPENSSL_STRING_push ( sigopts
, opt_arg ()))
211 macopts
= sk_OPENSSL_STRING_new_null ();
212 if (! macopts
|| ! sk_OPENSSL_STRING_push ( macopts
, opt_arg ()))
216 digestname
= opt_unknown ();
219 if (! opt_provider ( o
))
225 /* Remaining args are files to digest. */
226 argc
= opt_num_rest ();
228 if ( keyfile
!= NULL
&& argc
> 1 ) {
229 BIO_printf ( bio_err
, "%s: Can only sign or verify one file. \n " , prog
);
232 if (! app_RAND_load ())
235 if ( digestname
!= NULL
) {
236 if (! opt_md ( digestname
, & md
))
240 if ( do_verify
&& sigfile
== NULL
) {
242 "No signature to verify: use the -signature option \n " );
248 in
= BIO_new ( BIO_s_file ());
249 bmd
= BIO_new ( BIO_f_md ());
250 if ( in
== NULL
|| bmd
== NULL
)
254 BIO_set_callback_ex ( in
, BIO_debug_callback_ex
);
255 /* needed for windows 3.1 */
256 BIO_set_callback_arg ( in
, ( char *) bio_err
);
259 if (! app_passwd ( passinarg
, NULL
, & passin
, NULL
)) {
260 BIO_printf ( bio_err
, "Error getting password \n " );
271 out
= bio_open_default ( outfile
, 'w' , out_bin
? FORMAT_BINARY
: FORMAT_TEXT
);
275 if ((!( mac_name
== NULL
) + !( keyfile
== NULL
) + !( hmac_key
== NULL
)) > 1 ) {
276 BIO_printf ( bio_err
, "MAC and signing key cannot both be specified \n " );
280 if ( keyfile
!= NULL
) {
284 sigkey
= load_pubkey ( keyfile
, keyform
, 0 , NULL
, e
, "public key" );
286 sigkey
= load_key ( keyfile
, keyform
, 0 , passin
, e
, "private key" );
287 if ( sigkey
== NULL
) {
289 * load_[pub]key() has already printed an appropriate message
293 type
= EVP_PKEY_get_id ( sigkey
);
294 if ( type
== EVP_PKEY_ED25519
|| type
== EVP_PKEY_ED448
) {
296 * We implement PureEdDSA for these which doesn't have a separate
297 * digest, and only supports one shot.
299 BIO_printf ( bio_err
, "Key type not supported for this operation \n " );
304 if ( mac_name
!= NULL
) {
305 EVP_PKEY_CTX
* mac_ctx
= NULL
;
307 if (! init_gen_str (& mac_ctx
, mac_name
, impl
, 0 , NULL
, NULL
))
309 if ( macopts
!= NULL
) {
310 for ( i
= 0 ; i
< sk_OPENSSL_STRING_num ( macopts
); i
++) {
311 char * macopt
= sk_OPENSSL_STRING_value ( macopts
, i
);
313 if ( pkey_ctrl_string ( mac_ctx
, macopt
) <= 0 ) {
314 EVP_PKEY_CTX_free ( mac_ctx
);
315 BIO_printf ( bio_err
, "MAC parameter error \" %s \"\n " , macopt
);
321 sigkey
= app_keygen ( mac_ctx
, mac_name
, 0 , 0 /* not verbose */ );
322 /* Verbose output would make external-tests gost-engine fail */
323 EVP_PKEY_CTX_free ( mac_ctx
);
326 if ( hmac_key
!= NULL
) {
328 md
= ( EVP_MD
*) EVP_sha256 ();
329 digestname
= SN_sha256
;
331 sigkey
= EVP_PKEY_new_raw_private_key ( EVP_PKEY_HMAC
, impl
,
332 ( unsigned char *) hmac_key
,
338 if ( sigkey
!= NULL
) {
339 EVP_MD_CTX
* mctx
= NULL
;
340 EVP_PKEY_CTX
* pctx
= NULL
;
343 if ( BIO_get_md_ctx ( bmd
, & mctx
) <= 0 ) {
344 BIO_printf ( bio_err
, "Error getting context \n " );
349 res
= EVP_DigestVerifyInit_ex ( mctx
, & pctx
, digestname
,
351 app_get0_propq (), sigkey
, NULL
);
353 res
= EVP_DigestVerifyInit ( mctx
, & pctx
, md
, impl
, sigkey
);
356 res
= EVP_DigestSignInit_ex ( mctx
, & pctx
, digestname
,
358 app_get0_propq (), sigkey
, NULL
);
360 res
= EVP_DigestSignInit ( mctx
, & pctx
, md
, impl
, sigkey
);
362 BIO_printf ( bio_err
, "Error setting context \n " );
365 if ( sigopts
!= NULL
) {
366 for ( i
= 0 ; i
< sk_OPENSSL_STRING_num ( sigopts
); i
++) {
367 char * sigopt
= sk_OPENSSL_STRING_value ( sigopts
, i
);
369 if ( pkey_ctrl_string ( pctx
, sigopt
) <= 0 ) {
370 BIO_printf ( bio_err
, "Signature parameter error \" %s \"\n " ,
377 /* we use md as a filter, reading from 'in' */
379 EVP_MD_CTX
* mctx
= NULL
;
380 if ( BIO_get_md_ctx ( bmd
, & mctx
) <= 0 ) {
381 BIO_printf ( bio_err
, "Error getting context \n " );
385 md
= ( EVP_MD
*) EVP_sha256 ();
386 if (! EVP_DigestInit_ex ( mctx
, md
, impl
)) {
387 BIO_printf ( bio_err
, "Error setting digest \n " );
392 if ( sigfile
!= NULL
&& sigkey
!= NULL
) {
393 BIO
* sigbio
= BIO_new_file ( sigfile
, "rb" );
395 if ( sigbio
== NULL
) {
396 BIO_printf ( bio_err
, "Error opening signature file %s \n " , sigfile
);
399 siglen
= EVP_PKEY_get_size ( sigkey
);
400 sigbuf
= app_malloc ( siglen
, "signature buffer" );
401 siglen
= BIO_read ( sigbio
, sigbuf
, siglen
);
404 BIO_printf ( bio_err
, "Error reading signature file %s \n " , sigfile
);
408 inp
= BIO_push ( bmd
, in
);
413 BIO_get_md_ctx ( bmd
, & tctx
);
414 md
= EVP_MD_CTX_get1_md ( tctx
);
417 md_name
= EVP_MD_get0_name ( md
);
420 if (!( EVP_MD_get_flags ( md
) & EVP_MD_FLAG_XOF
)) {
421 BIO_printf ( bio_err
, "Length can only be specified for XOF \n " );
425 * Signing using XOF is not supported by any algorithms currently since
426 * each algorithm only calls EVP_DigestFinal_ex() in their sign_final
427 * and verify_final methods.
429 if ( sigkey
!= NULL
) {
430 BIO_printf ( bio_err
, "Signing key cannot be specified for XOF \n " );
436 BIO_set_fp ( in
, stdin
, BIO_NOCLOSE
);
437 ret
= do_fp ( out
, buf
, inp
, separator
, out_bin
, xoflen
, sigkey
, sigbuf
,
438 siglen
, NULL
, md_name
, "stdin" );
440 const char * sig_name
= NULL
;
444 sig_name
= EVP_PKEY_get0_type_name ( sigkey
);
447 for ( i
= 0 ; i
< argc
; i
++) {
448 if ( BIO_read_filename ( in
, argv
[ i
]) <= 0 ) {
453 if ( do_fp ( out
, buf
, inp
, separator
, out_bin
, xoflen
,
454 sigkey
, sigbuf
, siglen
, sig_name
, md_name
, argv
[ i
]))
457 ( void ) BIO_reset ( bmd
);
461 if ( ret
!= EXIT_SUCCESS
)
462 ERR_print_errors ( bio_err
);
463 OPENSSL_clear_free ( buf
, BUFSIZE
);
465 OPENSSL_free ( passin
);
468 EVP_PKEY_free ( sigkey
);
469 sk_OPENSSL_STRING_free ( sigopts
);
470 sk_OPENSSL_STRING_free ( macopts
);
471 OPENSSL_free ( sigbuf
);
477 static void show_digests ( const OBJ_NAME
* name
, void * arg
)
479 struct doall_dgst_digests
* dec
= ( struct doall_dgst_digests
*) arg
;
480 const EVP_MD
* md
= NULL
;
482 /* Filter out signed digests (a.k.a signature algorithms) */
483 if ( strstr ( name
-> name
, "rsa" ) != NULL
|| strstr ( name
-> name
, "RSA" ) != NULL
)
486 if (! islower (( unsigned char )* name
-> name
))
489 /* Filter out message digests that we cannot use */
490 md
= EVP_MD_fetch ( app_get0_libctx (), name
-> name
, app_get0_propq ());
494 BIO_printf ( dec
-> bio
, "-%-25s" , name
-> name
);
496 BIO_printf ( dec
-> bio
, " \n " );
499 BIO_printf ( dec
-> bio
, " " );
504 * The newline_escape_filename function performs newline escaping for any
505 * filename that contains a newline. This function also takes a pointer
506 * to backslash. The backslash pointer is a flag to indicating whether a newline
507 * is present in the filename. If a newline is present, the backslash flag is
508 * set and the output format will contain a backslash at the beginning of the
509 * digest output. This output format is to replicate the output format found
510 * in the '*sum' checksum programs. This aims to preserve backward
513 static const char * newline_escape_filename ( const char * file
, int * backslash
)
515 size_t i
, e
= 0 , length
= strlen ( file
), newline_count
= 0 , mem_len
= 0 ;
516 char * file_cpy
= NULL
;
518 for ( i
= 0 ; i
< length
; i
++)
522 mem_len
= length
+ newline_count
+ 1 ;
523 file_cpy
= app_malloc ( mem_len
, file
);
527 const char c
= file
[ e
];
529 file_cpy
[ i
++] = ' \\ ' ;
538 return ( const char *) file_cpy
;
542 int do_fp ( BIO
* out
, unsigned char * buf
, BIO
* bp
, int sep
, int binout
, int xoflen
,
543 EVP_PKEY
* key
, unsigned char * sigin
, int siglen
,
544 const char * sig_name
, const char * md_name
,
547 size_t len
= BUFSIZE
;
548 int i
, backslash
= 0 , ret
= EXIT_FAILURE
;
549 unsigned char * allocated_buf
= NULL
;
551 while ( BIO_pending ( bp
) || ! BIO_eof ( bp
)) {
552 i
= BIO_read ( bp
, ( char *) buf
, BUFSIZE
);
554 BIO_printf ( bio_err
, "Read error in %s \n " , file
);
562 BIO_get_md_ctx ( bp
, & ctx
);
563 i
= EVP_DigestVerifyFinal ( ctx
, sigin
, ( unsigned int ) siglen
);
565 BIO_printf ( out
, "Verified OK \n " );
567 BIO_printf ( out
, "Verification failure \n " );
570 BIO_printf ( bio_err
, "Error verifying data \n " );
580 BIO_get_md_ctx ( bp
, & ctx
);
581 if (! EVP_DigestSignFinal ( ctx
, NULL
, & tmplen
)) {
582 BIO_printf ( bio_err
, "Error getting maximum length of signed data \n " );
585 if ( tmplen
> BUFSIZE
) {
587 allocated_buf
= app_malloc ( len
, "Signature buffer" );
590 if (! EVP_DigestSignFinal ( ctx
, buf
, & len
)) {
591 BIO_printf ( bio_err
, "Error signing data \n " );
594 } else if ( xoflen
> 0 ) {
599 allocated_buf
= app_malloc ( len
, "Digest buffer" );
603 BIO_get_md_ctx ( bp
, & ctx
);
605 if (! EVP_DigestFinalXOF ( ctx
, buf
, len
)) {
606 BIO_printf ( bio_err
, "Error Digesting Data \n " );
610 len
= BIO_gets ( bp
, ( char *) buf
, BUFSIZE
);
616 BIO_write ( out
, buf
, len
);
617 } else if ( sep
== 2 ) {
618 file
= newline_escape_filename ( file
, & backslash
);
623 for ( i
= 0 ; i
< ( int ) len
; i
++)
624 BIO_printf ( out
, "%02x" , buf
[ i
]);
626 BIO_printf ( out
, " *%s \n " , file
);
627 OPENSSL_free (( char *) file
);
629 if ( sig_name
!= NULL
) {
630 BIO_puts ( out
, sig_name
);
632 BIO_printf ( out
, "-%s" , md_name
);
633 BIO_printf ( out
, "(%s)= " , file
);
634 } else if ( md_name
!= NULL
) {
635 BIO_printf ( out
, "%s(%s)= " , md_name
, file
);
637 BIO_printf ( out
, "(%s)= " , file
);
639 for ( i
= 0 ; i
< ( int ) len
; i
++) {
641 BIO_printf ( out
, ":" );
642 BIO_printf ( out
, "%02x" , buf
[ i
]);
644 BIO_printf ( out
, " \n " );
649 if ( allocated_buf
!= NULL
)
650 OPENSSL_clear_free ( allocated_buf
, len
);