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.
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.
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]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
29 * Implements digest(1) and mac(1) commands
30 * If command name is mac, performs mac operation
31 * else perform digest operation
33 * See the man pages for digest and mac for details on
34 * how these commands work.
47 #include <sys/types.h>
49 #include <security/cryptoki.h>
51 #include <cryptoutil.h>
55 * Buffer size for reading file. This is given a rather high value
56 * to get better performance when a hardware provider is present.
58 #define BUFFERSIZE (1024 * 64)
61 * RESULTLEN - large enough size in bytes to hold result for
62 * digest and mac results for all mechanisms
64 #define RESULTLEN (512)
70 #define EXIT_SUCCESS 0 /* No errors */
71 #define EXIT_FAILURE 1 /* All errors except usage */
72 #endif /* EXIT_SUCCESS */
74 #define EXIT_USAGE 2 /* usage/syntax error */
76 #define MAC_NAME "mac" /* name of mac command */
77 #define MAC_OPTIONS "lva:k:T:K:" /* for getopt */
78 #define DIGEST_NAME "digest" /* name of digest command */
79 #define DIGEST_OPTIONS "lva:" /* for getopt */
81 /* Saved command line options */
82 static boolean_t vflag
= B_FALSE
; /* -v (verbose) flag, optional */
83 static boolean_t aflag
= B_FALSE
; /* -a <algorithm> flag, required */
84 static boolean_t lflag
= B_FALSE
; /* -l flag, for mac and digest */
85 static boolean_t kflag
= B_FALSE
; /* -k keyfile */
86 static boolean_t Tflag
= B_FALSE
; /* -T token_spec */
87 static boolean_t Kflag
= B_FALSE
; /* -K key_label */
89 static char *keyfile
= NULL
; /* name of file containing key value */
90 static char *token_label
= NULL
; /* tokensSpec: tokenName[:manufId[:serial]] */
91 static char *key_label
= NULL
; /* PKCS#11 symmetric token key label */
93 static CK_BYTE buf
[BUFFERSIZE
];
96 CK_MECHANISM_TYPE type
;
104 #define MECH_ALIASES_COUNT 11
106 static struct mech_alias mech_aliases
[] = {
107 { CKM_SHA_1
, "sha1", ULONG_MAX
, 0L, 8, B_FALSE
},
108 { CKM_MD5
, "md5", ULONG_MAX
, 0L, 8, B_FALSE
},
109 { CKM_DES_MAC
, "des_mac", ULONG_MAX
, 0L, 8, B_FALSE
},
110 { CKM_SHA_1_HMAC
, "sha1_hmac", ULONG_MAX
, 0L, 8, B_FALSE
},
111 { CKM_MD5_HMAC
, "md5_hmac", ULONG_MAX
, 0L, 8, B_FALSE
},
112 { CKM_SHA256
, "sha256", ULONG_MAX
, 0L, 8, B_FALSE
},
113 { CKM_SHA384
, "sha384", ULONG_MAX
, 0L, 8, B_FALSE
},
114 { CKM_SHA512
, "sha512", ULONG_MAX
, 0L, 8, B_FALSE
},
115 { CKM_SHA256_HMAC
, "sha256_hmac", ULONG_MAX
, 0L, 8, B_FALSE
},
116 { CKM_SHA384_HMAC
, "sha384_hmac", ULONG_MAX
, 0L, 8, B_FALSE
},
117 { CKM_SHA512_HMAC
, "sha512_hmac", ULONG_MAX
, 0L, 8, B_FALSE
}
120 static CK_BBOOL
true = TRUE
;
122 static void usage(boolean_t mac_cmd
);
123 static int execute_cmd(char *algo_str
, int filecount
,
124 char **filelist
, boolean_t mac_cmd
);
125 static CK_RV
do_mac(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pmech
,
126 int fd
, CK_OBJECT_HANDLE key
, CK_BYTE_PTR
*psignature
,
127 CK_ULONG_PTR psignaturelen
);
128 static CK_RV
do_digest(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pmech
,
129 int fd
, CK_BYTE_PTR
*pdigest
, CK_ULONG_PTR pdigestlen
);
132 main(int argc
, char **argv
)
136 int errflag
= 0; /* We had an optstr parse error */
137 char c
; /* current getopts flag */
138 char *algo_str
; /* mechanism/algorithm string */
140 boolean_t mac_cmd
; /* if TRUE, do mac, else do digest */
142 char **filelist
; /* list of files */
143 char *cmdname
= NULL
; /* name of command */
145 (void) setlocale(LC_ALL
, "");
146 #if !defined(TEXT_DOMAIN) /* Should be defiend by cc -D */
147 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
149 (void) textdomain(TEXT_DOMAIN
);
152 * Based on command name, determine
153 * type of command. mac is mac
154 * everything else is digest.
156 cmdname
= basename(argv
[0]);
158 cryptodebug_init(cmdname
);
160 if (strcmp(cmdname
, MAC_NAME
) == 0)
162 else if (strcmp(cmdname
, DIGEST_NAME
) == 0)
165 cryptoerror(LOG_STDERR
, gettext(
166 "command name must be either digest or mac\n"));
171 optstr
= MAC_OPTIONS
;
173 optstr
= DIGEST_OPTIONS
;
176 /* Parse command line arguments */
177 while (!errflag
&& (c
= getopt(argc
, argv
, optstr
)) != -1) {
196 token_label
= optarg
;
207 filecount
= argc
- optind
;
208 if (errflag
|| (!aflag
&& !lflag
) || (lflag
&& argc
> 2) ||
209 (kflag
&& Kflag
) || (Tflag
&& !Kflag
) || filecount
< 0) {
214 if (filecount
== 0) {
217 filelist
= &argv
[optind
];
220 return (execute_cmd(algo_str
, filecount
, filelist
, mac_cmd
));
224 * usage message for digest/mac
227 usage(boolean_t mac_cmd
)
229 (void) fprintf(stderr
, gettext("Usage:\n"));
231 (void) fprintf(stderr
, gettext(" mac -l\n"));
232 (void) fprintf(stderr
, gettext(" mac [-v] -a <algorithm> "
233 "[-k <keyfile> | -K <keylabel> [-T <tokenspec>]] "
236 (void) fprintf(stderr
, gettext(" digest -l | [-v] "
237 "-a <algorithm> [file...]\n"));
242 * Print out list of available algorithms.
245 algorithm_list(boolean_t mac_cmd
)
250 (void) printf(gettext("Algorithm Keysize: Min "
252 "------------------------------------------\n"));
254 for (mech
= 0; mech
< MECH_ALIASES_COUNT
; mech
++) {
256 if (mech_aliases
[mech
].available
== B_FALSE
)
260 (void) printf("%-15s", mech_aliases
[mech
].alias
);
262 if (mech_aliases
[mech
].keysize_min
!= ULONG_MAX
&&
263 mech_aliases
[mech
].keysize_max
!= 0)
264 (void) printf(" %5lu %5lu\n",
265 (mech_aliases
[mech
].keysize_min
*
266 mech_aliases
[mech
].keysize_unit
),
267 (mech_aliases
[mech
].keysize_max
*
268 mech_aliases
[mech
].keysize_unit
));
273 (void) printf("%s\n", mech_aliases
[mech
].alias
);
279 get_token_key(CK_SESSION_HANDLE hSession
, CK_KEY_TYPE keytype
,
280 char *keylabel
, CK_BYTE
*password
, int password_len
,
281 CK_OBJECT_HANDLE
*keyobj
)
284 CK_ATTRIBUTE pTmpl
[10];
285 CK_OBJECT_CLASS
class = CKO_SECRET_KEY
;
287 CK_BBOOL is_token
= 1;
288 CK_ULONG key_obj_count
= 1;
290 CK_KEY_TYPE ckKeyType
= keytype
;
293 rv
= C_Login(hSession
, CKU_USER
, (CK_UTF8CHAR_PTR
)password
,
296 (void) fprintf(stderr
, "Cannot login to the token."
297 " error = %s\n", pkcs11_strerror(rv
));
302 pTmpl
[i
].type
= CKA_TOKEN
;
303 pTmpl
[i
].pValue
= &is_token
;
304 pTmpl
[i
].ulValueLen
= sizeof (CK_BBOOL
);
307 pTmpl
[i
].type
= CKA_CLASS
;
308 pTmpl
[i
].pValue
= &class;
309 pTmpl
[i
].ulValueLen
= sizeof (class);
312 pTmpl
[i
].type
= CKA_LABEL
;
313 pTmpl
[i
].pValue
= keylabel
;
314 pTmpl
[i
].ulValueLen
= strlen(keylabel
);
317 pTmpl
[i
].type
= CKA_KEY_TYPE
;
318 pTmpl
[i
].pValue
= &ckKeyType
;
319 pTmpl
[i
].ulValueLen
= sizeof (ckKeyType
);
322 pTmpl
[i
].type
= CKA_PRIVATE
;
323 pTmpl
[i
].pValue
= &true;
324 pTmpl
[i
].ulValueLen
= sizeof (true);
327 rv
= C_FindObjectsInit(hSession
, pTmpl
, i
);
332 rv
= C_FindObjects(hSession
, keyobj
, 1, &key_obj_count
);
333 (void) C_FindObjectsFinal(hSession
);
337 (void) fprintf(stderr
,
338 "Cannot retrieve key object. error = %s\n",
339 pkcs11_strerror(rv
));
343 if (key_obj_count
== 0) {
344 (void) fprintf(stderr
, "Cannot find the key object.\n");
353 * Execute the command.
354 * algo_str - name of algorithm
355 * filecount - no. of files to process, if 0, use stdin
356 * filelist - list of files
357 * mac_cmd - if true do mac else do digest
360 execute_cmd(char *algo_str
, int filecount
, char **filelist
, boolean_t mac_cmd
)
363 char *filename
= NULL
;
367 CK_SLOT_ID_PTR pSlotList
= NULL
;
368 CK_MECHANISM_TYPE mech_type
;
369 CK_MECHANISM_INFO info
;
371 CK_SESSION_HANDLE hSession
= CK_INVALID_HANDLE
;
372 CK_BYTE_PTR resultbuf
= NULL
;
374 CK_BYTE_PTR pkeydata
= NULL
;
375 CK_OBJECT_HANDLE key
= (CK_OBJECT_HANDLE
) 0;
376 size_t keylen
= 0; /* key length */
377 char *resultstr
= NULL
; /* result in hex string */
378 int resultstrlen
; /* result string length */
380 int exitcode
= EXIT_SUCCESS
; /* return code */
381 int slot
, mek
; /* index variables */
383 CK_BYTE salt
[CK_PKCS5_PBKD2_SALT_SIZE
];
385 CK_ULONG iterations
= CK_PKCS5_PBKD2_ITERATIONS
;
388 CK_SLOT_ID token_slot_id
;
392 * Determine if algorithm/mechanism is valid
394 for (mech_match
= 0; mech_match
< MECH_ALIASES_COUNT
;
397 mech_aliases
[mech_match
].alias
) == 0) {
398 mech_type
= mech_aliases
[mech_match
].type
;
404 if (mech_match
== MECH_ALIASES_COUNT
) {
405 cryptoerror(LOG_STDERR
,
406 gettext("unknown algorithm -- %s"), algo_str
);
407 return (EXIT_FAILURE
);
410 /* Get key to do a MAC operation */
415 /* get the pin of the token */
416 if (token_label
== NULL
||
417 !strlen(token_label
)) {
418 token_label
= pkcs11_default_token();
421 status
= pkcs11_get_pass(token_label
,
422 (char **)&pkeydata
, &keylen
,
424 } else if (keyfile
!= NULL
) {
425 /* get the key file */
426 status
= pkcs11_read_data(keyfile
,
427 (void **)&pkeydata
, &keylen
);
429 /* get the key from input */
430 status
= pkcs11_get_pass(NULL
,
431 (char **)&pkeydata
, &keylen
,
435 if (status
!= 0 || keylen
== 0 || pkeydata
== NULL
) {
436 cryptoerror(LOG_STDERR
,
437 (Kflag
|| (keyfile
== NULL
)) ?
438 gettext("invalid passphrase.") :
439 gettext("invalid key."));
440 return (EXIT_FAILURE
);
445 /* Initialize, and get list of slots */
446 rv
= C_Initialize(NULL
);
447 if (rv
!= CKR_OK
&& rv
!= CKR_CRYPTOKI_ALREADY_INITIALIZED
) {
448 cryptoerror(LOG_STDERR
,
449 gettext("failed to initialize PKCS #11 framework: %s"),
450 pkcs11_strerror(rv
));
451 return (EXIT_FAILURE
);
455 rv
= C_GetSlotList(0, NULL_PTR
, &slotcount
);
456 if (rv
!= CKR_OK
|| slotcount
== 0) {
457 cryptoerror(LOG_STDERR
, gettext(
458 "failed to find any cryptographic provider; "
459 "please check with your system administrator: %s"),
460 pkcs11_strerror(rv
));
461 exitcode
= EXIT_FAILURE
;
465 /* Found at least one slot, allocate memory for slot list */
466 pSlotList
= malloc(slotcount
* sizeof (CK_SLOT_ID
));
467 if (pSlotList
== NULL_PTR
) {
469 cryptoerror(LOG_STDERR
, gettext("malloc: %s\n"),
471 exitcode
= EXIT_FAILURE
;
475 /* Get the list of slots */
476 if ((rv
= C_GetSlotList(0, pSlotList
, &slotcount
)) != CKR_OK
) {
477 cryptoerror(LOG_STDERR
, gettext(
478 "failed to find any cryptographic provider; "
479 "please check with your system administrator: %s"),
480 pkcs11_strerror(rv
));
481 exitcode
= EXIT_FAILURE
;
486 * Obtain list of algorithms if -l option was given
490 for (slot
= 0; slot
< slotcount
; slot
++) {
492 /* Iterate through each mechanism */
493 for (mek
= 0; mek
< MECH_ALIASES_COUNT
; mek
++) {
494 rv
= C_GetMechanismInfo(pSlotList
[slot
],
495 mech_aliases
[mek
].type
, &info
);
497 /* Only check algorithms that can be used */
498 if ((rv
!= CKR_OK
) ||
499 (!mac_cmd
&& (info
.flags
& CKF_SIGN
)) ||
500 (mac_cmd
&& (info
.flags
& CKF_DIGEST
)))
504 * Set to minimum/maximum key sizes assuming
505 * the values available are not 0.
507 if (info
.ulMinKeySize
&& (info
.ulMinKeySize
<
508 mech_aliases
[mek
].keysize_min
))
509 mech_aliases
[mek
].keysize_min
=
512 if (info
.ulMaxKeySize
&& (info
.ulMaxKeySize
>
513 mech_aliases
[mek
].keysize_max
))
514 mech_aliases
[mek
].keysize_max
=
517 mech_aliases
[mek
].available
= B_TRUE
;
522 algorithm_list(mac_cmd
);
528 * Find a slot with matching mechanism
530 * If -K is specified, we find the slot id for the token first, then
531 * check if the slot supports the algorithm.
535 kmfrv
= kmf_pk11_token_lookup(NULL
, token_label
,
537 if (kmfrv
!= KMF_OK
) {
538 cryptoerror(LOG_STDERR
,
539 gettext("no matching PKCS#11 token"));
540 exitcode
= EXIT_FAILURE
;
543 rv
= C_GetMechanismInfo(token_slot_id
, mech_type
, &info
);
544 if (rv
== CKR_OK
&& (info
.flags
& CKF_SIGN
))
545 slotID
= token_slot_id
;
550 for (i
= 0; i
< slotcount
; i
++) {
551 slotID
= pSlotList
[i
];
552 rv
= C_GetMechanismInfo(slotID
, mech_type
, &info
);
554 continue; /* to the next slot */
558 * Make sure the slot supports
559 * PKCS5 key generation if we
560 * will be using it later.
561 * We use it whenever the key
562 * is entered at command line.
564 if ((info
.flags
& CKF_SIGN
) &&
566 CK_MECHANISM_INFO kg_info
;
567 rv
= C_GetMechanismInfo(slotID
,
568 CKM_PKCS5_PBKD2
, &kg_info
);
571 } else if (info
.flags
& CKF_SIGN
) {
575 if (info
.flags
& CKF_DIGEST
)
582 /* Show error if no matching mechanism found */
583 if (i
== slotcount
) {
584 cryptoerror(LOG_STDERR
,
585 gettext("no cryptographic provider was "
586 "found for this algorithm -- %s"), algo_str
);
587 exitcode
= EXIT_FAILURE
;
591 /* Mechanism is supported. Go ahead & open a session */
592 rv
= C_OpenSession(slotID
, CKF_SERIAL_SESSION
,
593 NULL_PTR
, NULL
, &hSession
);
596 cryptoerror(LOG_STDERR
,
597 gettext("can not open PKCS#11 session: %s"),
598 pkcs11_strerror(rv
));
599 exitcode
= EXIT_FAILURE
;
603 /* Create a key object for mac operation */
606 * If we read keybytes from a file,
607 * do NOT process them with C_GenerateKey,
608 * treat them as raw keydata bytes and
609 * create a key object for them.
612 /* XXX : why wasn't SUNW_C_KeyToObject used here? */
613 CK_OBJECT_CLASS
class = CKO_SECRET_KEY
;
614 CK_KEY_TYPE tmpl_keytype
= CKK_GENERIC_SECRET
;
615 CK_BBOOL
false = FALSE
;
617 CK_ATTRIBUTE
template[5];
619 if (mech_type
== CKM_DES_MAC
) {
620 tmpl_keytype
= CKK_DES
;
622 template[nattr
].type
= CKA_CLASS
;
623 template[nattr
].pValue
= &class;
624 template[nattr
].ulValueLen
= sizeof (class);
627 template[nattr
].type
= CKA_KEY_TYPE
;
628 template[nattr
].pValue
= &tmpl_keytype
;
629 template[nattr
].ulValueLen
= sizeof (tmpl_keytype
);
632 template[nattr
].type
= CKA_SIGN
;
633 template[nattr
].pValue
= &true;
634 template[nattr
].ulValueLen
= sizeof (true);
637 template[nattr
].type
= CKA_TOKEN
;
638 template[nattr
].pValue
= &false;
639 template[nattr
].ulValueLen
= sizeof (false);
642 template[nattr
].type
= CKA_VALUE
;
643 template[nattr
].pValue
= pkeydata
;
644 template[nattr
].ulValueLen
= keylen
;
647 rv
= C_CreateObject(hSession
, template, nattr
, &key
);
651 if (mech_type
== CKM_DES_MAC
) {
654 keytype
= CKK_GENERIC_SECRET
;
657 rv
= get_token_key(hSession
, keytype
, key_label
,
658 pkeydata
, keylen
, &key
);
660 exitcode
= EXIT_FAILURE
;
665 if (mech_type
== CKM_DES_MAC
) {
669 keytype
= CKK_GENERIC_SECRET
;
670 keysize
= 16; /* 128 bits */
673 * We use a fixed salt (0x0a, 0x0a, 0x0a ...)
674 * for creating the key so that the end user
675 * will be able to generate the same 'mac'
676 * using the same passphrase.
678 (void) memset(salt
, 0x0a, sizeof (salt
));
679 rv
= pkcs11_PasswdToPBKD2Object(hSession
,
680 (char *)pkeydata
, (size_t)keylen
, (void *)salt
,
681 sizeof (salt
), iterations
, keytype
, keysize
,
686 cryptoerror(LOG_STDERR
,
687 gettext("unable to create key for crypto "
688 "operation: %s"), pkcs11_strerror(rv
));
689 exitcode
= EXIT_FAILURE
;
694 /* Allocate a buffer to store result. */
695 resultlen
= RESULTLEN
;
696 if ((resultbuf
= malloc(resultlen
)) == NULL
) {
698 cryptoerror(LOG_STDERR
, gettext("malloc: %s\n"),
700 exitcode
= EXIT_FAILURE
;
704 /* Allocate a buffer to store result string */
705 resultstrlen
= RESULTLEN
;
706 if ((resultstr
= malloc(resultstrlen
)) == NULL
) {
708 cryptoerror(LOG_STDERR
, gettext("malloc: %s\n"),
710 exitcode
= EXIT_FAILURE
;
714 mech
.mechanism
= mech_type
;
715 mech
.pParameter
= NULL_PTR
;
716 mech
.ulParameterLen
= 0;
717 exitcode
= EXIT_SUCCESS
;
721 if (filecount
> 0 && filelist
!= NULL
) {
722 filename
= filelist
[i
];
723 if ((fd
= open(filename
, O_RDONLY
| O_NONBLOCK
)) ==
725 cryptoerror(LOG_STDERR
, gettext(
726 "can not open input file %s\n"), filename
);
727 exitcode
= EXIT_USAGE
;
731 fd
= 0; /* use stdin */
735 * Perform the operation
738 rv
= do_mac(hSession
, &mech
, fd
, key
, &resultbuf
,
741 rv
= do_digest(hSession
, &mech
, fd
, &resultbuf
,
746 cryptoerror(LOG_STDERR
,
747 gettext("crypto operation failed for "
749 filename
? filename
: "STDIN",
750 pkcs11_strerror(rv
));
751 exitcode
= EXIT_FAILURE
;
755 /* if result size has changed, allocate a bigger resulstr buf */
756 if (resultlen
!= RESULTLEN
) {
757 resultstrlen
= 2 * resultlen
+ 1;
758 resultstr
= realloc(resultstr
, resultstrlen
);
760 if (resultstr
== NULL
) {
762 cryptoerror(LOG_STDERR
,
763 gettext("realloc: %s\n"), strerror(err
));
764 exitcode
= EXIT_FAILURE
;
769 /* Output the result */
770 tohexstr(resultbuf
, resultlen
, resultstr
, resultstrlen
);
772 /* Include mechanism name for verbose */
774 (void) fprintf(stdout
, "%s ", algo_str
);
776 /* Include file name for multiple files, or if verbose */
777 if (filecount
> 1 || (vflag
&& filecount
> 0)) {
778 (void) fprintf(stdout
, "(%s) = ", filename
);
781 (void) fprintf(stdout
, "%s\n", resultstr
);
785 } while (++i
< filecount
);
788 /* clear and free the key */
790 (void) memset(pkeydata
, 0, keylen
);
796 if (resultbuf
!= NULL
) {
800 if (resultstr
!= NULL
) {
804 if (pSlotList
!= NULL
) {
808 if (!Kflag
&& key
!= (CK_OBJECT_HANDLE
) 0) {
809 (void) C_DestroyObject(hSession
, key
);
812 if (hSession
!= CK_INVALID_HANDLE
)
813 (void) C_CloseSession(hSession
);
815 (void) C_Finalize(NULL_PTR
);
821 * do_digest - Compute digest of a file
824 * pmech - ptr to mechanism to be used for digest
825 * fd - file descriptor
826 * pdigest - buffer where digest result is returned
827 * pdigestlen - length of digest buffer on input,
828 * length of result on output
831 do_digest(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pmech
,
832 int fd
, CK_BYTE_PTR
*pdigest
, CK_ULONG_PTR pdigestlen
)
838 if ((rv
= C_DigestInit(hSession
, pmech
)) != CKR_OK
) {
842 while ((nread
= read(fd
, buf
, sizeof (buf
))) > 0) {
844 rv
= C_DigestUpdate(hSession
, buf
, (CK_ULONG
)nread
);
849 saved_errno
= errno
; /* for later use */
852 * Perform the C_DigestFinal, even if there is a read error.
853 * Otherwise C_DigestInit will return CKR_OPERATION_ACTIVE
854 * next time it is called (for another file)
857 rv
= C_DigestFinal(hSession
, *pdigest
, pdigestlen
);
859 /* result too big to fit? Allocate a bigger buffer */
860 if (rv
== CKR_BUFFER_TOO_SMALL
) {
861 *pdigest
= realloc(*pdigest
, *pdigestlen
);
863 if (*pdigest
== NULL_PTR
) {
865 cryptoerror(LOG_STDERR
,
866 gettext("realloc: %s\n"), strerror(err
));
867 return (CKR_HOST_MEMORY
);
870 rv
= C_DigestFinal(hSession
, *pdigest
, pdigestlen
);
874 /* There was a read error */
876 cryptoerror(LOG_STDERR
, gettext(
877 "error reading file: %s"), strerror(saved_errno
));
878 return (CKR_GENERAL_ERROR
);
885 * do_mac - Compute mac of a file
888 * pmech - ptr to mechanism to be used
889 * fd - file descriptor
890 * key - key to be used
891 * psignature - ptr buffer where mac result is returned
892 * returns new buf if current buf is small
893 * psignaturelen - length of mac buffer on input,
894 * length of result on output
897 do_mac(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pmech
,
898 int fd
, CK_OBJECT_HANDLE key
, CK_BYTE_PTR
*psignature
,
899 CK_ULONG_PTR psignaturelen
)
905 if ((rv
= C_SignInit(hSession
, pmech
, key
)) != CKR_OK
) {
909 while ((nread
= read(fd
, buf
, sizeof (buf
))) > 0) {
911 rv
= C_SignUpdate(hSession
, buf
, (CK_ULONG
)nread
);
916 saved_errno
= errno
; /* for later use */
919 * Perform the C_SignFinal, even if there is a read error.
920 * Otherwise C_SignInit will return CKR_OPERATION_ACTIVE
921 * next time it is called (for another file)
924 rv
= C_SignFinal(hSession
, *psignature
, psignaturelen
);
926 /* result too big to fit? Allocate a bigger buffer */
927 if (rv
== CKR_BUFFER_TOO_SMALL
) {
928 *psignature
= realloc(*psignature
, *psignaturelen
);
930 if (*psignature
== NULL_PTR
) {
932 cryptoerror(LOG_STDERR
,
933 gettext("realloc: %s\n"), strerror(err
));
934 return (CKR_HOST_MEMORY
);
937 rv
= C_SignFinal(hSession
, *psignature
, psignaturelen
);
940 /* There was a read error */
942 cryptoerror(LOG_STDERR
, gettext("error reading file: %s"),
943 strerror(saved_errno
));
944 return (CKR_GENERAL_ERROR
);