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