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