Print this page
3887 Enlarge data buffer in digest/mac to boost performance
Reviewed by: Saso Kiselkov <skiselkov.ml@gmail.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/cmd-crypto/digest/digest.c
+++ new/usr/src/cmd/cmd-crypto/digest/digest.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 /*
27 27 * digest.c
28 28 *
29 29 * Implements digest(1) and mac(1) commands
30 30 * If command name is mac, performs mac operation
31 31 * else perform digest operation
32 32 *
33 33 * See the man pages for digest and mac for details on
34 34 * how these commands work.
35 35 */
36 36
37 37 #include <stdio.h>
38 38 #include <stdlib.h>
39 39 #include <unistd.h>
40 40 #include <fcntl.h>
41 41 #include <ctype.h>
42 42 #include <strings.h>
43 43 #include <libintl.h>
↓ open down ↓ |
43 lines elided |
↑ open up ↑ |
44 44 #include <libgen.h>
45 45 #include <locale.h>
46 46 #include <errno.h>
47 47 #include <sys/types.h>
48 48 #include <sys/stat.h>
49 49 #include <security/cryptoki.h>
50 50 #include <limits.h>
51 51 #include <cryptoutil.h>
52 52 #include <kmfapi.h>
53 53
54 -#define BUFFERSIZE (4096) /* Buffer size for reading file */
54 +/*
55 + * Buffer size for reading file. This is given a rather high value
56 + * to get better performance when a hardware provider is present.
57 + */
58 +#define BUFFERSIZE (1024 * 64)
55 59
56 60 /*
57 61 * RESULTLEN - large enough size in bytes to hold result for
58 62 * digest and mac results for all mechanisms
59 63 */
60 64 #define RESULTLEN (512)
61 65
62 66 /*
63 67 * Exit Status codes
64 68 */
65 69 #ifndef EXIT_SUCCESS
66 70 #define EXIT_SUCCESS 0 /* No errors */
67 71 #define EXIT_FAILURE 1 /* All errors except usage */
68 72 #endif /* EXIT_SUCCESS */
69 73
70 74 #define EXIT_USAGE 2 /* usage/syntax error */
71 75
72 76 #define MAC_NAME "mac" /* name of mac command */
73 77 #define MAC_OPTIONS "lva:k:T:K:" /* for getopt */
74 78 #define DIGEST_NAME "digest" /* name of digest command */
75 79 #define DIGEST_OPTIONS "lva:" /* for getopt */
76 80
77 81 /* Saved command line options */
78 82 static boolean_t vflag = B_FALSE; /* -v (verbose) flag, optional */
79 83 static boolean_t aflag = B_FALSE; /* -a <algorithm> flag, required */
80 84 static boolean_t lflag = B_FALSE; /* -l flag, for mac and digest */
81 85 static boolean_t kflag = B_FALSE; /* -k keyfile */
82 86 static boolean_t Tflag = B_FALSE; /* -T token_spec */
83 87 static boolean_t Kflag = B_FALSE; /* -K key_label */
84 88
85 89 static char *keyfile = NULL; /* name of file containing key value */
86 90 static char *token_label = NULL; /* tokensSpec: tokenName[:manufId[:serial]] */
87 91 static char *key_label = NULL; /* PKCS#11 symmetric token key label */
88 92
89 93 static CK_BYTE buf[BUFFERSIZE];
90 94
91 95 struct mech_alias {
92 96 CK_MECHANISM_TYPE type;
93 97 char *alias;
94 98 CK_ULONG keysize_min;
95 99 CK_ULONG keysize_max;
96 100 int keysize_unit;
97 101 boolean_t available;
98 102 };
99 103
100 104 #define MECH_ALIASES_COUNT 11
101 105
102 106 static struct mech_alias mech_aliases[] = {
103 107 { CKM_SHA_1, "sha1", ULONG_MAX, 0L, 8, B_FALSE },
104 108 { CKM_MD5, "md5", ULONG_MAX, 0L, 8, B_FALSE },
105 109 { CKM_DES_MAC, "des_mac", ULONG_MAX, 0L, 8, B_FALSE },
106 110 { CKM_SHA_1_HMAC, "sha1_hmac", ULONG_MAX, 0L, 8, B_FALSE },
107 111 { CKM_MD5_HMAC, "md5_hmac", ULONG_MAX, 0L, 8, B_FALSE },
108 112 { CKM_SHA256, "sha256", ULONG_MAX, 0L, 8, B_FALSE },
109 113 { CKM_SHA384, "sha384", ULONG_MAX, 0L, 8, B_FALSE },
110 114 { CKM_SHA512, "sha512", ULONG_MAX, 0L, 8, B_FALSE },
111 115 { CKM_SHA256_HMAC, "sha256_hmac", ULONG_MAX, 0L, 8, B_FALSE },
112 116 { CKM_SHA384_HMAC, "sha384_hmac", ULONG_MAX, 0L, 8, B_FALSE },
113 117 { CKM_SHA512_HMAC, "sha512_hmac", ULONG_MAX, 0L, 8, B_FALSE }
114 118 };
115 119
116 120 static CK_BBOOL true = TRUE;
117 121
118 122 static void usage(boolean_t mac_cmd);
119 123 static int execute_cmd(char *algo_str, int filecount,
120 124 char **filelist, boolean_t mac_cmd);
121 125 static CK_RV do_mac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pmech,
122 126 int fd, CK_OBJECT_HANDLE key, CK_BYTE_PTR *psignature,
123 127 CK_ULONG_PTR psignaturelen);
124 128 static CK_RV do_digest(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pmech,
125 129 int fd, CK_BYTE_PTR *pdigest, CK_ULONG_PTR pdigestlen);
126 130
127 131 int
128 132 main(int argc, char **argv)
129 133 {
130 134 extern char *optarg;
131 135 extern int optind;
132 136 int errflag = 0; /* We had an optstr parse error */
133 137 char c; /* current getopts flag */
134 138 char *algo_str; /* mechanism/algorithm string */
135 139 int filecount;
136 140 boolean_t mac_cmd; /* if TRUE, do mac, else do digest */
137 141 char *optstr;
138 142 char **filelist; /* list of files */
139 143 char *cmdname = NULL; /* name of command */
140 144
141 145 (void) setlocale(LC_ALL, "");
142 146 #if !defined(TEXT_DOMAIN) /* Should be defiend by cc -D */
143 147 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
144 148 #endif
145 149 (void) textdomain(TEXT_DOMAIN);
146 150
147 151 /*
148 152 * Based on command name, determine
149 153 * type of command. mac is mac
150 154 * everything else is digest.
151 155 */
152 156 cmdname = basename(argv[0]);
153 157
154 158 cryptodebug_init(cmdname);
155 159
156 160 if (strcmp(cmdname, MAC_NAME) == 0)
157 161 mac_cmd = B_TRUE;
158 162 else if (strcmp(cmdname, DIGEST_NAME) == 0)
159 163 mac_cmd = B_FALSE;
160 164 else {
161 165 cryptoerror(LOG_STDERR, gettext(
162 166 "command name must be either digest or mac\n"));
163 167 exit(EXIT_USAGE);
164 168 }
165 169
166 170 if (mac_cmd) {
167 171 optstr = MAC_OPTIONS;
168 172 } else {
169 173 optstr = DIGEST_OPTIONS;
170 174 }
171 175
172 176 /* Parse command line arguments */
173 177 while (!errflag && (c = getopt(argc, argv, optstr)) != -1) {
174 178
175 179 switch (c) {
176 180 case 'v':
177 181 vflag = B_TRUE;
178 182 break;
179 183 case 'a':
180 184 aflag = B_TRUE;
181 185 algo_str = optarg;
182 186 break;
183 187 case 'k':
184 188 kflag = B_TRUE;
185 189 keyfile = optarg;
186 190 break;
187 191 case 'l':
188 192 lflag = B_TRUE;
189 193 break;
190 194 case 'T':
191 195 Tflag = B_TRUE;
192 196 token_label = optarg;
193 197 break;
194 198 case 'K':
195 199 Kflag = B_TRUE;
196 200 key_label = optarg;
197 201 break;
198 202 default:
199 203 errflag++;
200 204 }
201 205 }
202 206
203 207 filecount = argc - optind;
204 208 if (errflag || (!aflag && !lflag) || (lflag && argc > 2) ||
205 209 (kflag && Kflag) || (Tflag && !Kflag) || filecount < 0) {
206 210 usage(mac_cmd);
207 211 exit(EXIT_USAGE);
208 212 }
209 213
210 214 if (filecount == 0) {
211 215 filelist = NULL;
212 216 } else {
213 217 filelist = &argv[optind];
214 218 }
215 219
216 220 return (execute_cmd(algo_str, filecount, filelist, mac_cmd));
217 221 }
218 222
219 223 /*
220 224 * usage message for digest/mac
221 225 */
222 226 static void
223 227 usage(boolean_t mac_cmd)
224 228 {
225 229 (void) fprintf(stderr, gettext("Usage:\n"));
226 230 if (mac_cmd) {
227 231 (void) fprintf(stderr, gettext(" mac -l\n"));
228 232 (void) fprintf(stderr, gettext(" mac [-v] -a <algorithm> "
229 233 "[-k <keyfile> | -K <keylabel> [-T <tokenspec>]] "
230 234 "[file...]\n"));
231 235 } else {
232 236 (void) fprintf(stderr, gettext(" digest -l | [-v] "
233 237 "-a <algorithm> [file...]\n"));
234 238 }
235 239 }
236 240
237 241 /*
238 242 * Print out list of available algorithms.
239 243 */
240 244 static void
241 245 algorithm_list(boolean_t mac_cmd)
242 246 {
243 247 int mech;
244 248
245 249 if (mac_cmd)
246 250 (void) printf(gettext("Algorithm Keysize: Min "
247 251 "Max (bits)\n"
248 252 "------------------------------------------\n"));
249 253
250 254 for (mech = 0; mech < MECH_ALIASES_COUNT; mech++) {
251 255
252 256 if (mech_aliases[mech].available == B_FALSE)
253 257 continue;
254 258
255 259 if (mac_cmd) {
256 260 (void) printf("%-15s", mech_aliases[mech].alias);
257 261
258 262 if (mech_aliases[mech].keysize_min != ULONG_MAX &&
259 263 mech_aliases[mech].keysize_max != 0)
260 264 (void) printf(" %5lu %5lu\n",
261 265 (mech_aliases[mech].keysize_min *
262 266 mech_aliases[mech].keysize_unit),
263 267 (mech_aliases[mech].keysize_max *
264 268 mech_aliases[mech].keysize_unit));
265 269 else
266 270 (void) printf("\n");
267 271
268 272 } else
269 273 (void) printf("%s\n", mech_aliases[mech].alias);
270 274
271 275 }
272 276 }
273 277
274 278 static int
275 279 get_token_key(CK_SESSION_HANDLE hSession, CK_KEY_TYPE keytype,
276 280 char *keylabel, CK_BYTE *password, int password_len,
277 281 CK_OBJECT_HANDLE *keyobj)
278 282 {
279 283 CK_RV rv;
280 284 CK_ATTRIBUTE pTmpl[10];
281 285 CK_OBJECT_CLASS class = CKO_SECRET_KEY;
282 286 CK_BBOOL true = 1;
283 287 CK_BBOOL is_token = 1;
284 288 CK_ULONG key_obj_count = 1;
285 289 int i;
286 290 CK_KEY_TYPE ckKeyType = keytype;
287 291
288 292
289 293 rv = C_Login(hSession, CKU_USER, (CK_UTF8CHAR_PTR)password,
290 294 password_len);
291 295 if (rv != CKR_OK) {
292 296 (void) fprintf(stderr, "Cannot login to the token."
293 297 " error = %s\n", pkcs11_strerror(rv));
294 298 return (-1);
295 299 }
296 300
297 301 i = 0;
298 302 pTmpl[i].type = CKA_TOKEN;
299 303 pTmpl[i].pValue = &is_token;
300 304 pTmpl[i].ulValueLen = sizeof (CK_BBOOL);
301 305 i++;
302 306
303 307 pTmpl[i].type = CKA_CLASS;
304 308 pTmpl[i].pValue = &class;
305 309 pTmpl[i].ulValueLen = sizeof (class);
306 310 i++;
307 311
308 312 pTmpl[i].type = CKA_LABEL;
309 313 pTmpl[i].pValue = keylabel;
310 314 pTmpl[i].ulValueLen = strlen(keylabel);
311 315 i++;
312 316
313 317 pTmpl[i].type = CKA_KEY_TYPE;
314 318 pTmpl[i].pValue = &ckKeyType;
315 319 pTmpl[i].ulValueLen = sizeof (ckKeyType);
316 320 i++;
317 321
318 322 pTmpl[i].type = CKA_PRIVATE;
319 323 pTmpl[i].pValue = &true;
320 324 pTmpl[i].ulValueLen = sizeof (true);
321 325 i++;
322 326
323 327 rv = C_FindObjectsInit(hSession, pTmpl, i);
324 328 if (rv != CKR_OK) {
325 329 goto out;
326 330 }
327 331
328 332 rv = C_FindObjects(hSession, keyobj, 1, &key_obj_count);
329 333 (void) C_FindObjectsFinal(hSession);
330 334
331 335 out:
332 336 if (rv != CKR_OK) {
333 337 (void) fprintf(stderr,
334 338 "Cannot retrieve key object. error = %s\n",
335 339 pkcs11_strerror(rv));
336 340 return (-1);
337 341 }
338 342
339 343 if (key_obj_count == 0) {
340 344 (void) fprintf(stderr, "Cannot find the key object.\n");
341 345 return (-1);
342 346 }
343 347
344 348 return (0);
345 349 }
346 350
347 351
348 352 /*
349 353 * Execute the command.
350 354 * algo_str - name of algorithm
351 355 * filecount - no. of files to process, if 0, use stdin
352 356 * filelist - list of files
353 357 * mac_cmd - if true do mac else do digest
354 358 */
355 359 static int
356 360 execute_cmd(char *algo_str, int filecount, char **filelist, boolean_t mac_cmd)
357 361 {
358 362 int fd;
359 363 char *filename = NULL;
360 364 CK_RV rv;
361 365 CK_ULONG slotcount;
362 366 CK_SLOT_ID slotID;
363 367 CK_SLOT_ID_PTR pSlotList = NULL;
364 368 CK_MECHANISM_TYPE mech_type;
365 369 CK_MECHANISM_INFO info;
366 370 CK_MECHANISM mech;
367 371 CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
368 372 CK_BYTE_PTR resultbuf = NULL;
369 373 CK_ULONG resultlen;
370 374 CK_BYTE_PTR pkeydata = NULL;
371 375 CK_OBJECT_HANDLE key = (CK_OBJECT_HANDLE) 0;
372 376 size_t keylen = 0; /* key length */
373 377 char *resultstr = NULL; /* result in hex string */
374 378 int resultstrlen; /* result string length */
375 379 int i;
376 380 int exitcode = EXIT_SUCCESS; /* return code */
377 381 int slot, mek; /* index variables */
378 382 int mech_match = 0;
379 383 CK_BYTE salt[CK_PKCS5_PBKD2_SALT_SIZE];
380 384 CK_ULONG keysize;
381 385 CK_ULONG iterations = CK_PKCS5_PBKD2_ITERATIONS;
382 386 CK_KEY_TYPE keytype;
383 387 KMF_RETURN kmfrv;
384 388 CK_SLOT_ID token_slot_id;
385 389
386 390 if (aflag) {
387 391 /*
388 392 * Determine if algorithm/mechanism is valid
389 393 */
390 394 for (mech_match = 0; mech_match < MECH_ALIASES_COUNT;
391 395 mech_match++) {
392 396 if (strcmp(algo_str,
393 397 mech_aliases[mech_match].alias) == 0) {
394 398 mech_type = mech_aliases[mech_match].type;
395 399 break;
396 400 }
397 401
398 402 }
399 403
400 404 if (mech_match == MECH_ALIASES_COUNT) {
401 405 cryptoerror(LOG_STDERR,
402 406 gettext("unknown algorithm -- %s"), algo_str);
403 407 return (EXIT_FAILURE);
404 408 }
405 409
406 410 /* Get key to do a MAC operation */
407 411 if (mac_cmd) {
408 412 int status;
409 413
410 414 if (Kflag) {
411 415 /* get the pin of the token */
412 416 if (token_label == NULL ||
413 417 !strlen(token_label)) {
414 418 token_label = pkcs11_default_token();
415 419 }
416 420
417 421 status = pkcs11_get_pass(token_label,
418 422 (char **)&pkeydata, &keylen,
419 423 0, B_FALSE);
420 424 } else if (keyfile != NULL) {
421 425 /* get the key file */
422 426 status = pkcs11_read_data(keyfile,
423 427 (void **)&pkeydata, &keylen);
424 428 } else {
425 429 /* get the key from input */
426 430 status = pkcs11_get_pass(NULL,
427 431 (char **)&pkeydata, &keylen,
428 432 0, B_FALSE);
429 433 }
430 434
431 435 if (status != 0 || keylen == 0 || pkeydata == NULL) {
432 436 cryptoerror(LOG_STDERR,
433 437 (Kflag || (keyfile == NULL)) ?
434 438 gettext("invalid passphrase.") :
435 439 gettext("invalid key."));
436 440 return (EXIT_FAILURE);
437 441 }
438 442 }
439 443 }
440 444
441 445 /* Initialize, and get list of slots */
442 446 rv = C_Initialize(NULL);
443 447 if (rv != CKR_OK && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
444 448 cryptoerror(LOG_STDERR,
445 449 gettext("failed to initialize PKCS #11 framework: %s"),
446 450 pkcs11_strerror(rv));
447 451 return (EXIT_FAILURE);
448 452 }
449 453
450 454 /* Get slot count */
451 455 rv = C_GetSlotList(0, NULL_PTR, &slotcount);
452 456 if (rv != CKR_OK || slotcount == 0) {
453 457 cryptoerror(LOG_STDERR, gettext(
454 458 "failed to find any cryptographic provider; "
455 459 "please check with your system administrator: %s"),
456 460 pkcs11_strerror(rv));
457 461 exitcode = EXIT_FAILURE;
458 462 goto cleanup;
459 463 }
460 464
461 465 /* Found at least one slot, allocate memory for slot list */
462 466 pSlotList = malloc(slotcount * sizeof (CK_SLOT_ID));
463 467 if (pSlotList == NULL_PTR) {
464 468 int err = errno;
465 469 cryptoerror(LOG_STDERR, gettext("malloc: %s\n"),
466 470 strerror(err));
467 471 exitcode = EXIT_FAILURE;
468 472 goto cleanup;
469 473 }
470 474
471 475 /* Get the list of slots */
472 476 if ((rv = C_GetSlotList(0, pSlotList, &slotcount)) != CKR_OK) {
473 477 cryptoerror(LOG_STDERR, gettext(
474 478 "failed to find any cryptographic provider; "
475 479 "please check with your system administrator: %s"),
476 480 pkcs11_strerror(rv));
477 481 exitcode = EXIT_FAILURE;
478 482 goto cleanup;
479 483 }
480 484
481 485 /*
482 486 * Obtain list of algorithms if -l option was given
483 487 */
484 488 if (lflag) {
485 489
486 490 for (slot = 0; slot < slotcount; slot++) {
487 491
488 492 /* Iterate through each mechanism */
489 493 for (mek = 0; mek < MECH_ALIASES_COUNT; mek++) {
490 494 rv = C_GetMechanismInfo(pSlotList[slot],
491 495 mech_aliases[mek].type, &info);
492 496
493 497 /* Only check algorithms that can be used */
494 498 if ((rv != CKR_OK) ||
495 499 (!mac_cmd && (info.flags & CKF_SIGN)) ||
496 500 (mac_cmd && (info.flags & CKF_DIGEST)))
497 501 continue;
498 502
499 503 /*
500 504 * Set to minimum/maximum key sizes assuming
501 505 * the values available are not 0.
502 506 */
503 507 if (info.ulMinKeySize && (info.ulMinKeySize <
504 508 mech_aliases[mek].keysize_min))
505 509 mech_aliases[mek].keysize_min =
506 510 info.ulMinKeySize;
507 511
508 512 if (info.ulMaxKeySize && (info.ulMaxKeySize >
509 513 mech_aliases[mek].keysize_max))
510 514 mech_aliases[mek].keysize_max =
511 515 info.ulMaxKeySize;
512 516
513 517 mech_aliases[mek].available = B_TRUE;
514 518 }
515 519
516 520 }
517 521
518 522 algorithm_list(mac_cmd);
519 523
520 524 goto cleanup;
521 525 }
522 526
523 527 /*
524 528 * Find a slot with matching mechanism
525 529 *
526 530 * If -K is specified, we find the slot id for the token first, then
527 531 * check if the slot supports the algorithm.
528 532 */
529 533 i = 0;
530 534 if (Kflag) {
531 535 kmfrv = kmf_pk11_token_lookup(NULL, token_label,
532 536 &token_slot_id);
533 537 if (kmfrv != KMF_OK) {
534 538 cryptoerror(LOG_STDERR,
535 539 gettext("no matching PKCS#11 token"));
536 540 exitcode = EXIT_FAILURE;
537 541 goto cleanup;
538 542 }
539 543 rv = C_GetMechanismInfo(token_slot_id, mech_type, &info);
540 544 if (rv == CKR_OK && (info.flags & CKF_SIGN))
541 545 slotID = token_slot_id;
542 546 else
543 547 i = slotcount;
544 548
545 549 } else {
546 550 for (i = 0; i < slotcount; i++) {
547 551 slotID = pSlotList[i];
548 552 rv = C_GetMechanismInfo(slotID, mech_type, &info);
549 553 if (rv != CKR_OK) {
550 554 continue; /* to the next slot */
551 555 } else {
552 556 if (mac_cmd) {
553 557 /*
554 558 * Make sure the slot supports
555 559 * PKCS5 key generation if we
556 560 * will be using it later.
557 561 * We use it whenever the key
558 562 * is entered at command line.
559 563 */
560 564 if ((info.flags & CKF_SIGN) &&
561 565 (keyfile == NULL)) {
562 566 CK_MECHANISM_INFO kg_info;
563 567 rv = C_GetMechanismInfo(slotID,
564 568 CKM_PKCS5_PBKD2, &kg_info);
565 569 if (rv == CKR_OK)
566 570 break;
567 571 } else if (info.flags & CKF_SIGN) {
568 572 break;
569 573 }
570 574 } else {
571 575 if (info.flags & CKF_DIGEST)
572 576 break;
573 577 }
574 578 }
575 579 }
576 580 }
577 581
578 582 /* Show error if no matching mechanism found */
579 583 if (i == slotcount) {
580 584 cryptoerror(LOG_STDERR,
581 585 gettext("no cryptographic provider was "
582 586 "found for this algorithm -- %s"), algo_str);
583 587 exitcode = EXIT_FAILURE;
584 588 goto cleanup;
585 589 }
586 590
587 591 /* Mechanism is supported. Go ahead & open a session */
588 592 rv = C_OpenSession(slotID, CKF_SERIAL_SESSION,
589 593 NULL_PTR, NULL, &hSession);
590 594
591 595 if (rv != CKR_OK) {
592 596 cryptoerror(LOG_STDERR,
593 597 gettext("can not open PKCS#11 session: %s"),
594 598 pkcs11_strerror(rv));
595 599 exitcode = EXIT_FAILURE;
596 600 goto cleanup;
597 601 }
598 602
599 603 /* Create a key object for mac operation */
600 604 if (mac_cmd) {
601 605 /*
602 606 * If we read keybytes from a file,
603 607 * do NOT process them with C_GenerateKey,
604 608 * treat them as raw keydata bytes and
605 609 * create a key object for them.
606 610 */
607 611 if (keyfile) {
608 612 /* XXX : why wasn't SUNW_C_KeyToObject used here? */
609 613 CK_OBJECT_CLASS class = CKO_SECRET_KEY;
610 614 CK_KEY_TYPE tmpl_keytype = CKK_GENERIC_SECRET;
611 615 CK_BBOOL false = FALSE;
612 616 int nattr = 0;
613 617 CK_ATTRIBUTE template[5];
614 618
615 619 if (mech_type == CKM_DES_MAC) {
616 620 tmpl_keytype = CKK_DES;
617 621 }
618 622 template[nattr].type = CKA_CLASS;
619 623 template[nattr].pValue = &class;
620 624 template[nattr].ulValueLen = sizeof (class);
621 625 nattr++;
622 626
623 627 template[nattr].type = CKA_KEY_TYPE;
624 628 template[nattr].pValue = &tmpl_keytype;
625 629 template[nattr].ulValueLen = sizeof (tmpl_keytype);
626 630 nattr++;
627 631
628 632 template[nattr].type = CKA_SIGN;
629 633 template[nattr].pValue = &true;
630 634 template[nattr].ulValueLen = sizeof (true);
631 635 nattr++;
632 636
633 637 template[nattr].type = CKA_TOKEN;
634 638 template[nattr].pValue = &false;
635 639 template[nattr].ulValueLen = sizeof (false);
636 640 nattr++;
637 641
638 642 template[nattr].type = CKA_VALUE;
639 643 template[nattr].pValue = pkeydata;
640 644 template[nattr].ulValueLen = keylen;
641 645 nattr++;
642 646
643 647 rv = C_CreateObject(hSession, template, nattr, &key);
644 648
645 649 } else if (Kflag) {
646 650
647 651 if (mech_type == CKM_DES_MAC) {
648 652 keytype = CKK_DES;
649 653 } else {
650 654 keytype = CKK_GENERIC_SECRET;
651 655 }
652 656
653 657 rv = get_token_key(hSession, keytype, key_label,
654 658 pkeydata, keylen, &key);
655 659 if (rv != CKR_OK) {
656 660 exitcode = EXIT_FAILURE;
657 661 goto cleanup;
658 662 }
659 663 } else {
660 664 CK_KEY_TYPE keytype;
661 665 if (mech_type == CKM_DES_MAC) {
662 666 keytype = CKK_DES;
663 667 keysize = 0;
664 668 } else {
665 669 keytype = CKK_GENERIC_SECRET;
666 670 keysize = 16; /* 128 bits */
667 671 }
668 672 /*
669 673 * We use a fixed salt (0x0a, 0x0a, 0x0a ...)
670 674 * for creating the key so that the end user
671 675 * will be able to generate the same 'mac'
672 676 * using the same passphrase.
673 677 */
674 678 (void) memset(salt, 0x0a, sizeof (salt));
675 679 rv = pkcs11_PasswdToPBKD2Object(hSession,
676 680 (char *)pkeydata, (size_t)keylen, (void *)salt,
677 681 sizeof (salt), iterations, keytype, keysize,
678 682 CKF_SIGN, &key);
679 683 }
680 684
681 685 if (rv != CKR_OK) {
682 686 cryptoerror(LOG_STDERR,
683 687 gettext("unable to create key for crypto "
684 688 "operation: %s"), pkcs11_strerror(rv));
685 689 exitcode = EXIT_FAILURE;
686 690 goto cleanup;
687 691 }
688 692 }
689 693
690 694 /* Allocate a buffer to store result. */
691 695 resultlen = RESULTLEN;
692 696 if ((resultbuf = malloc(resultlen)) == NULL) {
693 697 int err = errno;
694 698 cryptoerror(LOG_STDERR, gettext("malloc: %s\n"),
695 699 strerror(err));
696 700 exitcode = EXIT_FAILURE;
697 701 goto cleanup;
698 702 }
699 703
700 704 /* Allocate a buffer to store result string */
701 705 resultstrlen = RESULTLEN;
702 706 if ((resultstr = malloc(resultstrlen)) == NULL) {
703 707 int err = errno;
704 708 cryptoerror(LOG_STDERR, gettext("malloc: %s\n"),
705 709 strerror(err));
706 710 exitcode = EXIT_FAILURE;
707 711 goto cleanup;
708 712 }
709 713
710 714 mech.mechanism = mech_type;
711 715 mech.pParameter = NULL_PTR;
712 716 mech.ulParameterLen = 0;
713 717 exitcode = EXIT_SUCCESS;
714 718 i = 0;
715 719
716 720 do {
717 721 if (filecount > 0 && filelist != NULL) {
718 722 filename = filelist[i];
719 723 if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) ==
720 724 -1) {
721 725 cryptoerror(LOG_STDERR, gettext(
722 726 "can not open input file %s\n"), filename);
723 727 exitcode = EXIT_USAGE;
724 728 continue;
725 729 }
726 730 } else {
727 731 fd = 0; /* use stdin */
728 732 }
729 733
730 734 /*
731 735 * Perform the operation
732 736 */
733 737 if (mac_cmd) {
734 738 rv = do_mac(hSession, &mech, fd, key, &resultbuf,
735 739 &resultlen);
736 740 } else {
737 741 rv = do_digest(hSession, &mech, fd, &resultbuf,
738 742 &resultlen);
739 743 }
740 744
741 745 if (rv != CKR_OK) {
742 746 cryptoerror(LOG_STDERR,
743 747 gettext("crypto operation failed for "
744 748 "file %s: %s\n"),
745 749 filename ? filename : "STDIN",
746 750 pkcs11_strerror(rv));
747 751 exitcode = EXIT_FAILURE;
748 752 continue;
749 753 }
750 754
751 755 /* if result size has changed, allocate a bigger resulstr buf */
752 756 if (resultlen != RESULTLEN) {
753 757 resultstrlen = 2 * resultlen + 1;
754 758 resultstr = realloc(resultstr, resultstrlen);
755 759
756 760 if (resultstr == NULL) {
757 761 int err = errno;
758 762 cryptoerror(LOG_STDERR,
759 763 gettext("realloc: %s\n"), strerror(err));
760 764 exitcode = EXIT_FAILURE;
761 765 goto cleanup;
762 766 }
763 767 }
764 768
765 769 /* Output the result */
766 770 tohexstr(resultbuf, resultlen, resultstr, resultstrlen);
767 771
768 772 /* Include mechanism name for verbose */
769 773 if (vflag)
770 774 (void) fprintf(stdout, "%s ", algo_str);
771 775
772 776 /* Include file name for multiple files, or if verbose */
773 777 if (filecount > 1 || (vflag && filecount > 0)) {
774 778 (void) fprintf(stdout, "(%s) = ", filename);
775 779 }
776 780
777 781 (void) fprintf(stdout, "%s\n", resultstr);
778 782 (void) close(fd);
779 783
780 784
781 785 } while (++i < filecount);
782 786
783 787
784 788 /* clear and free the key */
785 789 if (mac_cmd) {
786 790 (void) memset(pkeydata, 0, keylen);
787 791 free(pkeydata);
788 792 pkeydata = NULL;
789 793 }
790 794
791 795 cleanup:
792 796 if (resultbuf != NULL) {
793 797 free(resultbuf);
794 798 }
795 799
796 800 if (resultstr != NULL) {
797 801 free(resultstr);
798 802 }
799 803
800 804 if (pSlotList != NULL) {
801 805 free(pSlotList);
802 806 }
803 807
804 808 if (!Kflag && key != (CK_OBJECT_HANDLE) 0) {
805 809 (void) C_DestroyObject(hSession, key);
806 810 }
807 811
808 812 if (hSession != CK_INVALID_HANDLE)
809 813 (void) C_CloseSession(hSession);
810 814
811 815 (void) C_Finalize(NULL_PTR);
812 816
813 817 return (exitcode);
814 818 }
815 819
816 820 /*
817 821 * do_digest - Compute digest of a file
818 822 *
819 823 * hSession - session
820 824 * pmech - ptr to mechanism to be used for digest
821 825 * fd - file descriptor
822 826 * pdigest - buffer where digest result is returned
823 827 * pdigestlen - length of digest buffer on input,
824 828 * length of result on output
825 829 */
826 830 static CK_RV
827 831 do_digest(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pmech,
828 832 int fd, CK_BYTE_PTR *pdigest, CK_ULONG_PTR pdigestlen)
829 833 {
830 834 CK_RV rv;
831 835 ssize_t nread;
832 836 int saved_errno;
833 837
834 838 if ((rv = C_DigestInit(hSession, pmech)) != CKR_OK) {
835 839 return (rv);
836 840 }
837 841
838 842 while ((nread = read(fd, buf, sizeof (buf))) > 0) {
839 843 /* Get the digest */
840 844 rv = C_DigestUpdate(hSession, buf, (CK_ULONG)nread);
841 845 if (rv != CKR_OK)
842 846 return (rv);
843 847 }
844 848
845 849 saved_errno = errno; /* for later use */
846 850
847 851 /*
848 852 * Perform the C_DigestFinal, even if there is a read error.
849 853 * Otherwise C_DigestInit will return CKR_OPERATION_ACTIVE
850 854 * next time it is called (for another file)
851 855 */
852 856
853 857 rv = C_DigestFinal(hSession, *pdigest, pdigestlen);
854 858
855 859 /* result too big to fit? Allocate a bigger buffer */
856 860 if (rv == CKR_BUFFER_TOO_SMALL) {
857 861 *pdigest = realloc(*pdigest, *pdigestlen);
858 862
859 863 if (*pdigest == NULL_PTR) {
860 864 int err = errno;
861 865 cryptoerror(LOG_STDERR,
862 866 gettext("realloc: %s\n"), strerror(err));
863 867 return (CKR_HOST_MEMORY);
864 868 }
865 869
866 870 rv = C_DigestFinal(hSession, *pdigest, pdigestlen);
867 871 }
868 872
869 873
870 874 /* There was a read error */
871 875 if (nread == -1) {
872 876 cryptoerror(LOG_STDERR, gettext(
873 877 "error reading file: %s"), strerror(saved_errno));
874 878 return (CKR_GENERAL_ERROR);
875 879 } else {
876 880 return (rv);
877 881 }
878 882 }
879 883
880 884 /*
881 885 * do_mac - Compute mac of a file
882 886 *
883 887 * hSession - session
884 888 * pmech - ptr to mechanism to be used
885 889 * fd - file descriptor
886 890 * key - key to be used
887 891 * psignature - ptr buffer where mac result is returned
888 892 * returns new buf if current buf is small
889 893 * psignaturelen - length of mac buffer on input,
890 894 * length of result on output
891 895 */
892 896 static CK_RV
893 897 do_mac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pmech,
894 898 int fd, CK_OBJECT_HANDLE key, CK_BYTE_PTR *psignature,
895 899 CK_ULONG_PTR psignaturelen)
896 900 {
897 901 CK_RV rv;
898 902 ssize_t nread;
899 903 int saved_errno;
900 904
901 905 if ((rv = C_SignInit(hSession, pmech, key)) != CKR_OK) {
902 906 return (rv);
903 907 }
904 908
905 909 while ((nread = read(fd, buf, sizeof (buf))) > 0) {
906 910 /* Get the MAC */
907 911 rv = C_SignUpdate(hSession, buf, (CK_ULONG)nread);
908 912 if (rv != CKR_OK)
909 913 return (rv);
910 914 }
911 915
912 916 saved_errno = errno; /* for later use */
913 917
914 918 /*
915 919 * Perform the C_SignFinal, even if there is a read error.
916 920 * Otherwise C_SignInit will return CKR_OPERATION_ACTIVE
917 921 * next time it is called (for another file)
918 922 */
919 923
920 924 rv = C_SignFinal(hSession, *psignature, psignaturelen);
921 925
922 926 /* result too big to fit? Allocate a bigger buffer */
923 927 if (rv == CKR_BUFFER_TOO_SMALL) {
924 928 *psignature = realloc(*psignature, *psignaturelen);
925 929
926 930 if (*psignature == NULL_PTR) {
927 931 int err = errno;
928 932 cryptoerror(LOG_STDERR,
929 933 gettext("realloc: %s\n"), strerror(err));
930 934 return (CKR_HOST_MEMORY);
931 935 }
932 936
933 937 rv = C_SignFinal(hSession, *psignature, psignaturelen);
934 938 }
935 939
936 940 /* There was a read error */
937 941 if (nread == -1) {
938 942 cryptoerror(LOG_STDERR, gettext("error reading file: %s"),
939 943 strerror(saved_errno));
940 944 return (CKR_GENERAL_ERROR);
941 945 } else {
942 946 return (rv);
943 947 }
944 948 }
↓ open down ↓ |
880 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX