2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * digest.c
28 *
29 * Implements digest(1) and mac(1) commands
30 * If command name is mac, performs mac operation
31 * else perform digest operation
32 *
33 * See the man pages for digest and mac for details on
34 * how these commands work.
35 */
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <fcntl.h>
41 #include <ctype.h>
42 #include <strings.h>
54 #define BUFFERSIZE (4096) /* Buffer size for reading file */
55
56 /*
57 * RESULTLEN - large enough size in bytes to hold result for
58 * digest and mac results for all mechanisms
59 */
60 #define RESULTLEN (512)
61
62 /*
63 * Exit Status codes
64 */
65 #ifndef EXIT_SUCCESS
66 #define EXIT_SUCCESS 0 /* No errors */
67 #define EXIT_FAILURE 1 /* All errors except usage */
68 #endif /* EXIT_SUCCESS */
69
70 #define EXIT_USAGE 2 /* usage/syntax error */
71
72 #define MAC_NAME "mac" /* name of mac command */
73 #define MAC_OPTIONS "lva:k:T:K:" /* for getopt */
74 #define DIGEST_NAME "digest" /* name of mac command */
75 #define DIGEST_OPTIONS "lva:" /* for getopt */
76
77 static boolean_t vflag = B_FALSE; /* -v (verbose) flag, optional */
78 static boolean_t aflag = B_FALSE; /* -a <algorithm> flag, required */
79 static boolean_t lflag = B_FALSE; /* -l flag, for mac and digest */
80 static boolean_t kflag = B_FALSE;
81 static boolean_t Tflag = B_FALSE;
82 static boolean_t Kflag = B_FALSE;
83
84 static char *keyfile = NULL; /* name of keyfile */
85 static char *token_label = NULL;
86 static char *key_label = NULL;
87
88 static CK_BYTE buf[BUFFERSIZE];
89
90 struct mech_alias {
91 CK_MECHANISM_TYPE type;
92 char *alias;
93 CK_ULONG keysize_min;
94 CK_ULONG keysize_max;
95 int keysize_unit;
96 boolean_t available;
97 };
98
99 #define MECH_ALIASES_COUNT 11
100
101 static struct mech_alias mech_aliases[] = {
102 { CKM_SHA_1, "sha1", ULONG_MAX, 0L, 8, B_FALSE },
103 { CKM_MD5, "md5", ULONG_MAX, 0L, 8, B_FALSE },
104 { CKM_DES_MAC, "des_mac", ULONG_MAX, 0L, 8, B_FALSE },
105 { CKM_SHA_1_HMAC, "sha1_hmac", ULONG_MAX, 0L, 8, B_FALSE },
106 { CKM_MD5_HMAC, "md5_hmac", ULONG_MAX, 0L, 8, B_FALSE },
109 { CKM_SHA512, "sha512", ULONG_MAX, 0L, 8, B_FALSE },
110 { CKM_SHA256_HMAC, "sha256_hmac", ULONG_MAX, 0L, 8, B_FALSE },
111 { CKM_SHA384_HMAC, "sha384_hmac", ULONG_MAX, 0L, 8, B_FALSE },
112 { CKM_SHA512_HMAC, "sha512_hmac", ULONG_MAX, 0L, 8, B_FALSE }
113 };
114
115 static CK_BBOOL true = TRUE;
116
117 static void usage(boolean_t mac_cmd);
118 static int execute_cmd(char *algo_str, int filecount,
119 char **filelist, boolean_t mac_cmd);
120 static CK_RV do_mac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pmech,
121 int fd, CK_OBJECT_HANDLE key, CK_BYTE_PTR *psignature,
122 CK_ULONG_PTR psignaturelen);
123 static CK_RV do_digest(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pmech,
124 int fd, CK_BYTE_PTR *pdigest, CK_ULONG_PTR pdigestlen);
125
126 int
127 main(int argc, char **argv)
128 {
129
130 extern char *optarg;
131 extern int optind;
132 int errflag = 0; /* We had an optstr parse error */
133 char c; /* current getopts flag */
134 char *algo_str; /* mechanism/algorithm string */
135 int filecount;
136 boolean_t mac_cmd; /* if TRUE, do mac, else do digest */
137 char *optstr;
138 char **filelist; /* list of files */
139 char *cmdname = NULL; /* name of command */
140
141 (void) setlocale(LC_ALL, "");
142 #if !defined(TEXT_DOMAIN) /* Should be defiend by cc -D */
143 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
144 #endif
145 (void) textdomain(TEXT_DOMAIN);
146
147 /*
148 * Based on command name, determine
149 * type of command. mac is mac
413 !strlen(token_label)) {
414 token_label = pkcs11_default_token();
415 }
416
417 status = pkcs11_get_pass(token_label,
418 (char **)&pkeydata, &keylen,
419 0, B_FALSE);
420 } else if (keyfile != NULL) {
421 /* get the key file */
422 status = pkcs11_read_data(keyfile,
423 (void **)&pkeydata, &keylen);
424 } else {
425 /* get the key from input */
426 status = pkcs11_get_pass(NULL,
427 (char **)&pkeydata, &keylen,
428 0, B_FALSE);
429 }
430
431 if (status != 0 || keylen == 0 || pkeydata == NULL) {
432 cryptoerror(LOG_STDERR,
433 Kflag ? gettext("invalid passphrase.") :
434 gettext("invalid key."));
435 return (EXIT_FAILURE);
436 }
437 }
438 }
439
440 /* Initialize, and get list of slots */
441 rv = C_Initialize(NULL);
442 if (rv != CKR_OK && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
443 cryptoerror(LOG_STDERR,
444 gettext("failed to initialize PKCS #11 framework: %s"),
445 pkcs11_strerror(rv));
446 return (EXIT_FAILURE);
447 }
448
449 /* Get slot count */
450 rv = C_GetSlotList(0, NULL_PTR, &slotcount);
451 if (rv != CKR_OK || slotcount == 0) {
452 cryptoerror(LOG_STDERR, gettext(
453 "failed to find any cryptographic provider,"
454 "please check with your system administrator: %s"),
455 pkcs11_strerror(rv));
456 exitcode = EXIT_FAILURE;
457 goto cleanup;
458 }
459
460 /* Found at least one slot, allocate memory for slot list */
461 pSlotList = malloc(slotcount * sizeof (CK_SLOT_ID));
462 if (pSlotList == NULL_PTR) {
463 int err = errno;
464 cryptoerror(LOG_STDERR, gettext("malloc: %s\n"),
465 strerror(err));
466 exitcode = EXIT_FAILURE;
467 goto cleanup;
468 }
469
470 /* Get the list of slots */
471 if ((rv = C_GetSlotList(0, pSlotList, &slotcount)) != CKR_OK) {
472 cryptoerror(LOG_STDERR, gettext(
473 "failed to find any cryptographic provider,"
474 "please check with your system administrator: %s"),
475 pkcs11_strerror(rv));
476 exitcode = EXIT_FAILURE;
477 goto cleanup;
478 }
479
480 /*
481 * Obtain list of algorithms if -l option was given
482 */
483 if (lflag) {
484
485 for (slot = 0; slot < slotcount; slot++) {
486
487 /* Iterate through each mechanism */
488 for (mek = 0; mek < MECH_ALIASES_COUNT; mek++) {
489 rv = C_GetMechanismInfo(pSlotList[slot],
490 mech_aliases[mek].type, &info);
491
492 /* Only check algorithms that can be used */
493 if ((rv != CKR_OK) ||
|
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * digest.c
28 *
29 * Implements digest(1) and mac(1) commands
30 * If command name is mac, performs mac operation
31 * else perform digest operation
32 *
33 * See the man pages for digest and mac for details on
34 * how these commands work.
35 */
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <fcntl.h>
41 #include <ctype.h>
42 #include <strings.h>
54 #define BUFFERSIZE (4096) /* Buffer size for reading file */
55
56 /*
57 * RESULTLEN - large enough size in bytes to hold result for
58 * digest and mac results for all mechanisms
59 */
60 #define RESULTLEN (512)
61
62 /*
63 * Exit Status codes
64 */
65 #ifndef EXIT_SUCCESS
66 #define EXIT_SUCCESS 0 /* No errors */
67 #define EXIT_FAILURE 1 /* All errors except usage */
68 #endif /* EXIT_SUCCESS */
69
70 #define EXIT_USAGE 2 /* usage/syntax error */
71
72 #define MAC_NAME "mac" /* name of mac command */
73 #define MAC_OPTIONS "lva:k:T:K:" /* for getopt */
74 #define DIGEST_NAME "digest" /* name of digest command */
75 #define DIGEST_OPTIONS "lva:" /* for getopt */
76
77 /* Saved command line options */
78 static boolean_t vflag = B_FALSE; /* -v (verbose) flag, optional */
79 static boolean_t aflag = B_FALSE; /* -a <algorithm> flag, required */
80 static boolean_t lflag = B_FALSE; /* -l flag, for mac and digest */
81 static boolean_t kflag = B_FALSE; /* -k keyfile */
82 static boolean_t Tflag = B_FALSE; /* -T token_spec */
83 static boolean_t Kflag = B_FALSE; /* -K key_label */
84
85 static char *keyfile = NULL; /* name of file containing key value */
86 static char *token_label = NULL; /* tokensSpec: tokenName[:manufId[:serial]] */
87 static char *key_label = NULL; /* PKCS#11 symmetric token key label */
88
89 static CK_BYTE buf[BUFFERSIZE];
90
91 struct mech_alias {
92 CK_MECHANISM_TYPE type;
93 char *alias;
94 CK_ULONG keysize_min;
95 CK_ULONG keysize_max;
96 int keysize_unit;
97 boolean_t available;
98 };
99
100 #define MECH_ALIASES_COUNT 11
101
102 static struct mech_alias mech_aliases[] = {
103 { CKM_SHA_1, "sha1", ULONG_MAX, 0L, 8, B_FALSE },
104 { CKM_MD5, "md5", ULONG_MAX, 0L, 8, B_FALSE },
105 { CKM_DES_MAC, "des_mac", ULONG_MAX, 0L, 8, B_FALSE },
106 { CKM_SHA_1_HMAC, "sha1_hmac", ULONG_MAX, 0L, 8, B_FALSE },
107 { CKM_MD5_HMAC, "md5_hmac", ULONG_MAX, 0L, 8, B_FALSE },
110 { CKM_SHA512, "sha512", ULONG_MAX, 0L, 8, B_FALSE },
111 { CKM_SHA256_HMAC, "sha256_hmac", ULONG_MAX, 0L, 8, B_FALSE },
112 { CKM_SHA384_HMAC, "sha384_hmac", ULONG_MAX, 0L, 8, B_FALSE },
113 { CKM_SHA512_HMAC, "sha512_hmac", ULONG_MAX, 0L, 8, B_FALSE }
114 };
115
116 static CK_BBOOL true = TRUE;
117
118 static void usage(boolean_t mac_cmd);
119 static int execute_cmd(char *algo_str, int filecount,
120 char **filelist, boolean_t mac_cmd);
121 static CK_RV do_mac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pmech,
122 int fd, CK_OBJECT_HANDLE key, CK_BYTE_PTR *psignature,
123 CK_ULONG_PTR psignaturelen);
124 static CK_RV do_digest(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pmech,
125 int fd, CK_BYTE_PTR *pdigest, CK_ULONG_PTR pdigestlen);
126
127 int
128 main(int argc, char **argv)
129 {
130 extern char *optarg;
131 extern int optind;
132 int errflag = 0; /* We had an optstr parse error */
133 char c; /* current getopts flag */
134 char *algo_str; /* mechanism/algorithm string */
135 int filecount;
136 boolean_t mac_cmd; /* if TRUE, do mac, else do digest */
137 char *optstr;
138 char **filelist; /* list of files */
139 char *cmdname = NULL; /* name of command */
140
141 (void) setlocale(LC_ALL, "");
142 #if !defined(TEXT_DOMAIN) /* Should be defiend by cc -D */
143 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
144 #endif
145 (void) textdomain(TEXT_DOMAIN);
146
147 /*
148 * Based on command name, determine
149 * type of command. mac is mac
413 !strlen(token_label)) {
414 token_label = pkcs11_default_token();
415 }
416
417 status = pkcs11_get_pass(token_label,
418 (char **)&pkeydata, &keylen,
419 0, B_FALSE);
420 } else if (keyfile != NULL) {
421 /* get the key file */
422 status = pkcs11_read_data(keyfile,
423 (void **)&pkeydata, &keylen);
424 } else {
425 /* get the key from input */
426 status = pkcs11_get_pass(NULL,
427 (char **)&pkeydata, &keylen,
428 0, B_FALSE);
429 }
430
431 if (status != 0 || keylen == 0 || pkeydata == NULL) {
432 cryptoerror(LOG_STDERR,
433 (Kflag || (keyfile == NULL)) ?
434 gettext("invalid passphrase.") :
435 gettext("invalid key."));
436 return (EXIT_FAILURE);
437 }
438 }
439 }
440
441 /* Initialize, and get list of slots */
442 rv = C_Initialize(NULL);
443 if (rv != CKR_OK && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
444 cryptoerror(LOG_STDERR,
445 gettext("failed to initialize PKCS #11 framework: %s"),
446 pkcs11_strerror(rv));
447 return (EXIT_FAILURE);
448 }
449
450 /* Get slot count */
451 rv = C_GetSlotList(0, NULL_PTR, &slotcount);
452 if (rv != CKR_OK || slotcount == 0) {
453 cryptoerror(LOG_STDERR, gettext(
454 "failed to find any cryptographic provider; "
455 "please check with your system administrator: %s"),
456 pkcs11_strerror(rv));
457 exitcode = EXIT_FAILURE;
458 goto cleanup;
459 }
460
461 /* Found at least one slot, allocate memory for slot list */
462 pSlotList = malloc(slotcount * sizeof (CK_SLOT_ID));
463 if (pSlotList == NULL_PTR) {
464 int err = errno;
465 cryptoerror(LOG_STDERR, gettext("malloc: %s\n"),
466 strerror(err));
467 exitcode = EXIT_FAILURE;
468 goto cleanup;
469 }
470
471 /* Get the list of slots */
472 if ((rv = C_GetSlotList(0, pSlotList, &slotcount)) != CKR_OK) {
473 cryptoerror(LOG_STDERR, gettext(
474 "failed to find any cryptographic provider; "
475 "please check with your system administrator: %s"),
476 pkcs11_strerror(rv));
477 exitcode = EXIT_FAILURE;
478 goto cleanup;
479 }
480
481 /*
482 * Obtain list of algorithms if -l option was given
483 */
484 if (lflag) {
485
486 for (slot = 0; slot < slotcount; slot++) {
487
488 /* Iterate through each mechanism */
489 for (mek = 0; mek < MECH_ALIASES_COUNT; mek++) {
490 rv = C_GetMechanismInfo(pSlotList[slot],
491 mech_aliases[mek].type, &info);
492
493 /* Only check algorithms that can be used */
494 if ((rv != CKR_OK) ||
|