Print this page
9642 PKCS#11 softtoken should use explicit_bzero
Reviewed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Alex Wilson <alex.wilson@joyent.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeystoreUtil.c
+++ new/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeystoreUtil.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 *
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
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 (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
23 + * Copyright 2018, Joyent, Inc.
23 24 */
24 25
25 26 /*
26 27 * Functions used for manipulating the keystore
27 28 */
28 29
29 30 #include <stdio.h>
30 31 #include <stdlib.h>
31 32 #include <errno.h>
32 33 #include <sys/stat.h>
33 34 #include <fcntl.h>
34 35 #include <time.h>
35 36 #include <unistd.h>
36 37 #include <pwd.h>
37 38 #include <sys/types.h>
38 39 #include <dirent.h>
39 40 #include <limits.h>
40 41 #include <libgen.h>
41 42 #include <strings.h>
42 43 #include <security/cryptoki.h>
43 44 #include <cryptoutil.h>
44 45 #include "softGlobal.h"
45 46 #include "softObject.h"
46 47 #include "softSession.h"
47 48 #include "softKeystore.h"
48 49 #include "softKeystoreUtil.h"
49 50
50 51 #define MAXPATHLEN 1024
51 52 #define SUNW_PATH ".sunw" /* top level Sun directory */
52 53 #define KEYSTORE_PATH "pkcs11_softtoken" /* keystore directory */
53 54 #define PUB_OBJ_DIR "public" /* directory for public objects */
54 55 #define PRI_OBJ_DIR "private" /* directory for private objects */
55 56 #define DS_FILE "objstore_info" /* keystore description file */
56 57 #define TMP_DS_FILE "t_info" /* temp name for keystore desc. file */
57 58 #define OBJ_PREFIX "obj" /* prefix of the keystore object file names */
58 59 #define OBJ_PREFIX_LEN sizeof (OBJ_PREFIX) - 1 /* length of prefix */
59 60 #define TMP_OBJ_PREFIX "t_o" /* prefix of the temp object file names */
60 61
61 62 /*
62 63 * KEYSTORE DESCRIPTION FILE:
63 64 *
64 65 * The following describes the content of the keystore description file
65 66 *
66 67 * The order AND data type of the fields are very important.
67 68 * All the code in this file assume that they are in the order specified
68 69 * below. If either order of the fields or their data type changed,
69 70 * you must make sure the ALL the pre-define values are still valid
70 71 *
71 72 * 1) PKCS#11 release number. It's 2.20 in this release (uchar_t[32])
72 73 * 2) keystore version number: used for synchronizing when different
73 74 * processes access the keystore at the same time. It is incremented
74 75 * when there is a change to the keystore. (uint_32)
75 76 * 3) monotonic-counter: last counter value for name of token object file.
76 77 * used for assigning unique name to each token (uint_32)
77 78 * 4) salt used for generating encryption key (uint_16)
78 79 * 5) salt used for generating key used for doing HMAC (uint_16)
79 80 * 6) Length of salt used for generating hashed pin (length of salt
80 81 * is variable)
81 82 * 7) Salt used for generating hashed pin.
82 83 * 8) Hashed pin len (length of hashed pin could be variable, the offset of
83 84 * where this value lives in the file is calculated at run time)
84 85 * 9) Hashed pin
85 86 *
86 87 */
87 88
88 89 /* Keystore description file pre-defined values */
89 90 #define KS_PKCS11_VER "2.20"
90 91 #define KS_PKCS11_OFFSET 0
91 92 #define KS_PKCS11_VER_SIZE 32
92 93
93 94 #define KS_VER_OFFSET (KS_PKCS11_OFFSET + KS_PKCS11_VER_SIZE)
94 95 #define KS_VER_SIZE 4 /* size in bytes of keystore version value */
95 96
96 97 #define KS_COUNTER_OFFSET (KS_VER_OFFSET + KS_VER_SIZE)
97 98 #define KS_COUNTER_SIZE 4 /* size in bytes of the monotonic counter */
98 99
99 100 #define KS_KEY_SALT_OFFSET (KS_COUNTER_OFFSET + KS_COUNTER_SIZE)
100 101 #define KS_KEY_SALT_SIZE PBKD2_SALT_SIZE
101 102
102 103 #define KS_HMAC_SALT_OFFSET (KS_KEY_SALT_OFFSET + KS_KEY_SALT_SIZE)
103 104 #define KS_HMAC_SALT_SIZE PBKD2_SALT_SIZE
104 105
105 106 /* Salt for hashed pin */
106 107 #define KS_HASHED_PIN_SALT_LEN_OFFSET (KS_HMAC_SALT_OFFSET + KS_HMAC_SALT_SIZE)
107 108 #define KS_HASHED_PIN_SALT_LEN_SIZE 8 /* stores length of hashed pin salt */
108 109
109 110 #define KS_HASHED_PIN_SALT_OFFSET \
110 111 (KS_HASHED_PIN_SALT_LEN_OFFSET + KS_HASHED_PIN_SALT_LEN_SIZE)
111 112
112 113 /*
113 114 * hashed pin
114 115 *
115 116 * hashed_pin length offset will be calculated at run time since
116 117 * there's the hashed pin salt size is variable.
117 118 *
118 119 * The offset will be calculated at run time by calling the
119 120 * function calculate_hashed_pin_offset()
120 121 */
121 122 static off_t ks_hashed_pinlen_offset = -1;
122 123 #define KS_HASHED_PINLEN_SIZE 8
123 124
124 125 /* End of Keystore description file pre-defined values */
125 126
126 127 /*
127 128 * Metadata for each object
128 129 *
129 130 * The order AND data type of all the fields is very important.
130 131 * All the code in this file assume that they are in the order specified
131 132 * below. If either order of the fields or their data type is changed,
132 133 * you must make sure the following pre-define value is still valid
133 134 * Each object will have the meta data at the beginning of the object file.
134 135 *
135 136 * 1) object_version: used by softtoken to see if the object
136 137 * has been modified since it last reads it. (uint_32)
137 138 * 2) iv: initialization vector for encrypted data in the object. This
138 139 * value will be 0 for public objects. (uchar_t[16])
139 140 * 3) obj_hmac: keyed hash as verifier to detect private object
140 141 * being tampered this value will be 0 for public objects (uchar_t[16])
141 142 */
142 143
143 144 /* Object metadata pre-defined values */
144 145 #define OBJ_VER_OFFSET 0
145 146 #define OBJ_VER_SIZE 4 /* size of object version in bytes */
146 147 #define OBJ_IV_OFFSET (OBJ_VER_OFFSET + OBJ_VER_SIZE)
147 148 #define OBJ_IV_SIZE 16
148 149 #define OBJ_HMAC_OFFSET (OBJ_IV_OFFSET + OBJ_IV_SIZE)
149 150 #define OBJ_HMAC_SIZE 16 /* MD5 HMAC keyed hash */
150 151 #define OBJ_DATA_OFFSET (OBJ_HMAC_OFFSET + OBJ_HMAC_SIZE)
151 152 /* End of object metadata pre-defined values */
152 153
153 154 #define ALTERNATE_KEYSTORE_PATH "SOFTTOKEN_DIR"
154 155
155 156 static soft_object_t *enc_key = NULL;
156 157 static soft_object_t *hmac_key = NULL;
157 158 static char keystore_path[MAXPATHLEN];
158 159 static boolean_t keystore_path_initialized = B_FALSE;
159 160 static int desc_fd = 0;
160 161
161 162 static char *
162 163 get_keystore_path()
163 164 {
164 165 char *home = getenv("HOME");
165 166 char *alt = getenv(ALTERNATE_KEYSTORE_PATH);
166 167
167 168 if (keystore_path_initialized) {
168 169 return (keystore_path);
169 170 }
170 171
171 172 bzero(keystore_path, sizeof (keystore_path));
172 173 /*
173 174 * If it isn't set or is set to the empty string use the
174 175 * default location. We need to check for the empty string
175 176 * because some users "unset" environment variables by giving
176 177 * them no value, this isn't the same thing as removing it
177 178 * from the environment.
178 179 *
179 180 * We don't want that to attempt to open /.sunw/pkcs11_sofftoken
180 181 */
181 182 if ((alt != NULL) && (strcmp(alt, "") != 0)) {
182 183 (void) snprintf(keystore_path, MAXPATHLEN, "%s/%s",
183 184 alt, KEYSTORE_PATH);
184 185 keystore_path_initialized = B_TRUE;
185 186 } else if ((home != NULL) && (strcmp(home, "") != 0)) {
186 187 /* alternate path not specified, try user's home dir */
187 188 (void) snprintf(keystore_path, MAXPATHLEN, "%s/%s/%s",
188 189 home, SUNW_PATH, KEYSTORE_PATH);
189 190 keystore_path_initialized = B_TRUE;
190 191 }
191 192 return (keystore_path);
192 193 }
193 194
194 195 static char *
195 196 get_pub_obj_path(char *name)
196 197 {
197 198 bzero(name, sizeof (name));
198 199 (void) snprintf(name, MAXPATHLEN, "%s/%s",
199 200 get_keystore_path(), PUB_OBJ_DIR);
200 201 return (name);
201 202 }
202 203
203 204 static char *
204 205 get_pri_obj_path(char *name)
205 206 {
206 207 bzero(name, sizeof (name));
207 208 (void) snprintf(name, MAXPATHLEN, "%s/%s",
208 209 get_keystore_path(), PRI_OBJ_DIR);
209 210 return (name);
210 211 }
211 212
212 213 static char *
213 214 get_desc_file_path(char *name)
214 215 {
215 216 bzero(name, sizeof (name));
216 217 (void) snprintf(name, MAXPATHLEN, "%s/%s",
217 218 get_keystore_path(), DS_FILE);
218 219 return (name);
219 220 }
220 221
221 222 static char *
222 223 get_tmp_desc_file_path(char *name)
223 224 {
224 225 bzero(name, sizeof (name));
225 226 (void) snprintf(name, MAXPATHLEN, "%s/%s",
226 227 get_keystore_path(), TMP_DS_FILE);
227 228 return (name);
228 229 }
229 230
230 231 /*
231 232 * Calculates the offset for hashed_pin length and hashed pin
232 233 *
233 234 * Returns 0 if successful, -1 if there's any error.
234 235 *
235 236 * If successful, global variables "ks_hashed_pinlen_offset" will be set.
236 237 *
237 238 */
238 239 static int
239 240 calculate_hashed_pin_offset(int fd)
240 241 {
241 242 uint64_t salt_length;
242 243
243 244 if (lseek(fd, KS_HASHED_PIN_SALT_LEN_OFFSET, SEEK_SET)
244 245 != KS_HASHED_PIN_SALT_LEN_OFFSET) {
245 246 return (-1);
246 247 }
247 248
248 249 if (readn_nointr(fd, (char *)&salt_length,
249 250 KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
250 251 return (-1);
251 252 }
252 253 salt_length = SWAP64(salt_length);
253 254
254 255 ks_hashed_pinlen_offset = KS_HASHED_PIN_SALT_LEN_OFFSET
255 256 + KS_HASHED_PIN_SALT_LEN_SIZE + salt_length;
256 257
257 258 return (0);
258 259
259 260 }
260 261
261 262 /*
262 263 * acquire or release read/write lock on a specific file
263 264 *
264 265 * read_lock: true for read lock; false for write lock
265 266 * set_lock: true to set a lock; false to release a lock
266 267 */
267 268 static int
268 269 lock_file(int fd, boolean_t read_lock, boolean_t set_lock)
269 270 {
270 271
271 272 flock_t lock_info;
272 273 int r;
273 274
274 275 lock_info.l_whence = SEEK_SET;
275 276 lock_info.l_start = 0;
276 277 lock_info.l_len = 0; /* l_len == 0 means until end of file */
277 278
278 279 if (read_lock) {
279 280 lock_info.l_type = F_RDLCK;
280 281 } else {
281 282 lock_info.l_type = F_WRLCK;
282 283 }
283 284
284 285 if (set_lock) {
285 286 while ((r = fcntl(fd, F_SETLKW, &lock_info)) == -1) {
286 287 if (errno != EINTR)
287 288 break;
288 289 }
289 290 if (r == -1) {
290 291 return (-1);
291 292 }
292 293 } else {
293 294 lock_info.l_type = F_UNLCK;
294 295 while ((r = fcntl(fd, F_SETLKW, &lock_info)) == -1) {
295 296 if (errno != EINTR)
296 297 break;
297 298 }
298 299 if (r == -1) {
299 300 return (-1);
300 301 }
301 302 }
302 303
303 304 return (0);
304 305 }
305 306
306 307 int
307 308 create_keystore()
308 309 {
309 310 int fd, buf;
310 311 uint64_t hashed_pin_len, hashed_pin_salt_len, ulong_buf;
311 312 uchar_t ver_buf[KS_PKCS11_VER_SIZE];
312 313 char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN],
313 314 ks_desc_file[MAXPATHLEN];
314 315 CK_BYTE salt[KS_KEY_SALT_SIZE];
315 316 char *hashed_pin = NULL, *hashed_pin_salt = NULL;
316 317 char *alt;
317 318
318 319 /* keystore doesn't exist, create keystore directory */
319 320 if (mkdir(get_keystore_path(), S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
320 321 if (errno == EEXIST) {
321 322 return (0);
322 323 }
323 324
324 325 if (errno == EACCES) {
325 326 return (-1);
326 327 }
327 328
328 329 /* can't create keystore directory */
329 330 if (errno == ENOENT) { /* part of the path doesn't exist */
330 331 char keystore[MAXPATHLEN];
331 332 /*
332 333 * try to create $HOME/.sunw/pkcs11_softtoken if it
333 334 * doesn't exist. If it is a alternate path provided
334 335 * by the user, it should have existed. Will not
335 336 * create for them.
336 337 */
337 338 alt = getenv(ALTERNATE_KEYSTORE_PATH);
338 339 if ((alt == NULL) || (strcmp(alt, "") == 0)) {
339 340 char *home = getenv("HOME");
340 341
341 342 if (home == NULL || strcmp(home, "") == 0) {
342 343 return (-1);
343 344 }
344 345 /* create $HOME/.sunw/pkcs11_softtoken */
345 346 (void) snprintf(keystore, sizeof (keystore),
346 347 "%s/%s/%s", home, SUNW_PATH, KEYSTORE_PATH);
347 348 if (mkdirp(keystore,
348 349 S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
349 350 return (-1);
350 351 }
351 352 } else {
352 353 return (-1);
353 354 }
354 355 }
355 356 }
356 357
357 358 /* create keystore description file */
358 359 fd = open_nointr(get_desc_file_path(ks_desc_file),
359 360 O_RDWR|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
360 361 if (fd < 0) {
361 362 if (errno == EEXIST) {
362 363 return (0);
363 364 } else {
364 365 /* can't create keystore description file */
365 366 (void) rmdir(get_keystore_path());
366 367 return (-1);
367 368 }
368 369 }
369 370
370 371 if (lock_file(fd, B_FALSE, B_TRUE) != 0) {
371 372 (void) unlink(ks_desc_file);
372 373 (void) close(fd);
373 374 (void) rmdir(get_keystore_path());
374 375 return (-1);
375 376 }
376 377
377 378 if (mkdir(get_pub_obj_path(pub_obj_path),
378 379 S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
379 380 /* can't create directory for public objects */
380 381 (void) lock_file(fd, B_FALSE, B_FALSE);
381 382 (void) unlink(ks_desc_file);
382 383 (void) close(fd);
383 384 (void) rmdir(get_keystore_path());
384 385 return (-1);
385 386 }
386 387
387 388 if (mkdir(get_pri_obj_path(pri_obj_path),
388 389 S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
389 390 /* can't create directory for private objects */
390 391 (void) lock_file(fd, B_FALSE, B_FALSE);
391 392 (void) unlink(ks_desc_file);
392 393 (void) close(fd);
393 394 (void) rmdir(get_keystore_path());
394 395 (void) rmdir(pub_obj_path);
395 396 return (-1);
396 397 }
397 398
398 399
399 400 /* write file format release number */
400 401 bzero(ver_buf, sizeof (ver_buf));
401 402 (void) strcpy((char *)ver_buf, KS_PKCS11_VER);
402 403 if ((writen_nointr(fd, (char *)ver_buf, sizeof (ver_buf)))
403 404 != sizeof (ver_buf)) {
404 405 goto cleanup;
405 406 }
406 407
407 408 /* write version number, version = 0 since keystore just created */
408 409 buf = SWAP32(0);
409 410 if (writen_nointr(fd, (void *)&buf, KS_VER_SIZE) != KS_VER_SIZE) {
410 411 goto cleanup;
411 412 }
412 413
413 414 /* write monotonic-counter. Counter for keystore objects start at 1 */
414 415 buf = SWAP32(1);
415 416 if (writen_nointr(fd, (void *)&buf, KS_COUNTER_SIZE)
416 417 != KS_COUNTER_SIZE) {
417 418 goto cleanup;
418 419 }
419 420
420 421 /* initial encryption key salt should be all NULL */
421 422 bzero(salt, sizeof (salt));
422 423 if (writen_nointr(fd, (void *)salt, KS_KEY_SALT_SIZE)
423 424 != KS_KEY_SALT_SIZE) {
424 425 goto cleanup;
425 426 }
426 427
427 428 /* initial HMAC key salt should also be all NULL */
428 429 if (writen_nointr(fd, (void *)salt, KS_HMAC_SALT_SIZE)
429 430 != KS_HMAC_SALT_SIZE) {
430 431 goto cleanup;
431 432 }
432 433
433 434 /* generate the hashed pin salt, and MD5 hashed pin of default pin */
434 435 if (soft_gen_hashed_pin((CK_CHAR_PTR)SOFT_DEFAULT_PIN, &hashed_pin,
435 436 &hashed_pin_salt) < 0) {
436 437 goto cleanup;
437 438 }
438 439
439 440 if ((hashed_pin_salt == NULL) || (hashed_pin == NULL)) {
440 441 goto cleanup;
441 442 }
442 443
443 444 hashed_pin_salt_len = (uint64_t)strlen(hashed_pin_salt);
444 445 hashed_pin_len = (uint64_t)strlen(hashed_pin);
445 446
446 447 /* write hashed pin salt length */
447 448 ulong_buf = SWAP64(hashed_pin_salt_len);
448 449 if (writen_nointr(fd, (void *)&ulong_buf, KS_HASHED_PIN_SALT_LEN_SIZE)
449 450 != KS_HASHED_PIN_SALT_LEN_SIZE) {
450 451 goto cleanup;
451 452 }
452 453
453 454 if (writen_nointr(fd, (void *)hashed_pin_salt,
454 455 hashed_pin_salt_len) != hashed_pin_salt_len) {
455 456 goto cleanup;
456 457 }
457 458
458 459 /* write MD5 hashed pin of the default pin */
459 460 ulong_buf = SWAP64(hashed_pin_len);
460 461 if (writen_nointr(fd, (void *)&ulong_buf, KS_HASHED_PINLEN_SIZE)
461 462 != KS_HASHED_PINLEN_SIZE) {
462 463 goto cleanup;
↓ open down ↓ |
430 lines elided |
↑ open up ↑ |
463 464 }
464 465
465 466 if (writen_nointr(fd, (void *)hashed_pin, hashed_pin_len)
466 467 != hashed_pin_len) {
467 468 goto cleanup;
468 469 }
469 470
470 471 (void) lock_file(fd, B_FALSE, B_FALSE);
471 472
472 473 (void) close(fd);
473 - if (hashed_pin_salt)
474 - free(hashed_pin_salt);
474 + freezero(hashed_pin_salt, hashed_pin_salt_len);
475 475 return (0);
476 476
477 477 cleanup:
478 478 (void) lock_file(fd, B_FALSE, B_FALSE);
479 479 (void) unlink(ks_desc_file);
480 480 (void) close(fd);
481 481 (void) rmdir(get_keystore_path());
482 482 (void) rmdir(pub_obj_path);
483 483 (void) rmdir(pri_obj_path);
484 484 return (-1);
485 485 }
486 486
487 487 /*
488 488 * Determines if the file referenced by "fd" has the same
489 489 * inode as the file referenced by "fname".
490 490 *
491 491 * The argument "same" contains the result of determining
492 492 * if the inode is the same or not
493 493 *
494 494 * Returns 0 if there's no error.
495 495 * Returns 1 if there's any error with opening the file.
496 496 *
497 497 *
498 498 */
499 499 static int
500 500 is_inode_same(int fd, char *fname, boolean_t *same)
501 501 {
502 502 struct stat fn_stat, fd_stat;
503 503
504 504 if (fstat(fd, &fd_stat) != 0) {
505 505 return (-1);
506 506 }
507 507
508 508 if (stat(fname, &fn_stat) != 0) {
509 509 return (-1);
510 510 }
511 511
512 512 /* It's the same file if both st_ino and st_dev match */
513 513 if ((fd_stat.st_ino == fn_stat.st_ino) &&
514 514 (fd_stat.st_dev == fn_stat.st_dev)) {
515 515 *same = B_TRUE;
516 516 } else {
517 517 *same = B_FALSE;
518 518 }
519 519 return (0);
520 520 }
521 521
522 522 static int
523 523 acquire_file_lock(int *fd, char *fname, mode_t mode) {
524 524
525 525 boolean_t read_lock = B_TRUE, same_inode;
526 526
527 527 if ((mode == O_RDWR) || (mode == O_WRONLY)) {
528 528 read_lock = B_FALSE;
529 529 }
530 530
531 531 if (lock_file(*fd, read_lock, B_TRUE) != 0) {
532 532 return (-1);
533 533 }
534 534
535 535 /*
536 536 * make sure another process did not modify the file
537 537 * while we were trying to get the lock
538 538 */
539 539 if (is_inode_same(*fd, fname, &same_inode) != 0) {
540 540 (void) lock_file(*fd, B_TRUE, B_FALSE); /* unlock file */
541 541 return (-1);
542 542 }
543 543
544 544 while (!same_inode) {
545 545 /*
546 546 * need to unlock file, close, re-open the file,
547 547 * and re-acquire the lock
548 548 */
549 549
550 550 /* unlock file */
551 551 if (lock_file(*fd, B_TRUE, B_FALSE) != 0) {
552 552 return (-1);
553 553 }
554 554
555 555 (void) close(*fd);
556 556
557 557 /* re-open */
558 558 *fd = open_nointr(fname, mode|O_NONBLOCK);
559 559 if (*fd < 0) {
560 560 return (-1);
561 561 }
562 562
563 563 /* acquire lock again */
564 564 if (lock_file(*fd, read_lock, B_TRUE) != 0) {
565 565 return (-1);
566 566 }
567 567
568 568 if (is_inode_same(*fd, fname, &same_inode) != 0) {
569 569 (void) lock_file(*fd, B_TRUE, B_FALSE); /* unlock */
570 570 return (-1);
571 571 }
572 572
573 573 }
574 574
575 575 return (0);
576 576 }
577 577
578 578 /*
579 579 * Open the keystore description file in the specified mode.
580 580 * If the keystore doesn't exist, the "do_create_keystore"
581 581 * argument determines if the keystore should be created
582 582 */
583 583 static int
584 584 open_and_lock_keystore_desc(mode_t mode, boolean_t do_create_keystore,
585 585 boolean_t lock_held)
586 586 {
587 587
588 588 int fd;
589 589 char *fname, ks_desc_file[MAXPATHLEN];
590 590
591 591 /* open the keystore description file in requested mode */
592 592 fname = get_desc_file_path(ks_desc_file);
593 593 fd = open_nointr(fname, mode|O_NONBLOCK);
594 594 if (fd < 0) {
595 595 if ((errno == ENOENT) && (do_create_keystore)) {
596 596 if (create_keystore() < 0) {
597 597 goto done;
598 598 }
599 599 fd = open_nointr(fname, mode|O_NONBLOCK);
600 600 if (fd < 0) {
601 601 goto done;
602 602 }
603 603 } else {
604 604 goto done;
605 605 }
606 606 }
607 607
608 608 if (lock_held) {
609 609 /* already hold the lock */
610 610 return (fd);
611 611 }
612 612
613 613 if (acquire_file_lock(&fd, fname, mode) != 0) {
614 614 if (fd > 0) {
615 615 (void) close(fd);
616 616 }
617 617 return (-1);
618 618 }
619 619
620 620 done:
621 621 return (fd);
622 622 }
623 623
624 624
625 625 /*
626 626 * Set or remove read or write lock on keystore description file
627 627 *
628 628 * read_lock: true for read lock, false for write lock
629 629 * set_lock: true for set a lock, false to remove a lock
630 630 */
631 631 static int
632 632 lock_desc_file(boolean_t read_lock, boolean_t set_lock)
633 633 {
634 634
635 635 char ks_desc_file[MAXPATHLEN];
636 636
637 637 if (set_lock) {
638 638 int oflag;
639 639
640 640 /*
641 641 * make sure desc_fd is not already used. If used, it means
642 642 * some other lock is already set on the file
643 643 */
644 644 if (desc_fd > 0) {
645 645 return (-1);
646 646 }
647 647
648 648 (void) get_desc_file_path(ks_desc_file);
649 649
650 650 if (read_lock) {
651 651 oflag = O_RDONLY;
652 652 } else {
653 653 oflag = O_WRONLY;
654 654 }
655 655 if ((desc_fd = open_and_lock_keystore_desc(oflag,
656 656 B_FALSE, B_FALSE)) < 0) {
657 657 return (-1);
658 658 }
659 659 } else {
660 660 /* make sure we have a valid fd */
661 661 if (desc_fd <= 0) {
662 662 return (-1);
663 663 }
664 664
665 665 if (lock_file(desc_fd, read_lock, B_FALSE) == 1) {
666 666 return (-1);
667 667 }
668 668
669 669 (void) close(desc_fd);
670 670 desc_fd = 0;
671 671
672 672 }
673 673 return (0);
674 674 }
675 675
676 676 static int
677 677 open_and_lock_object_file(ks_obj_handle_t *ks_handle, int oflag,
678 678 boolean_t lock_held)
679 679 {
680 680 char obj_fname[MAXPATHLEN];
681 681 int fd;
682 682
683 683 if (ks_handle->public) {
684 684 char pub_obj_path[MAXPATHLEN];
685 685 (void) snprintf(obj_fname, MAXPATHLEN, "%s/%s",
686 686 get_pub_obj_path(pub_obj_path), ks_handle->name);
687 687 } else {
688 688 char pri_obj_path[MAXPATHLEN];
689 689 (void) snprintf(obj_fname, MAXPATHLEN, "%s/%s",
690 690 get_pri_obj_path(pri_obj_path), ks_handle->name);
691 691 }
692 692
693 693 fd = open_nointr(obj_fname, oflag|O_NONBLOCK);
694 694 if (fd < 0) {
695 695 return (-1);
696 696 }
697 697
698 698 if (lock_held) {
699 699 /* already hold the lock */
700 700 return (fd);
701 701 }
702 702
703 703 if (acquire_file_lock(&fd, obj_fname, oflag) != 0) {
704 704 if (fd > 0) {
705 705 (void) close(fd);
706 706 }
707 707 return (-1);
708 708 }
709 709
710 710
711 711 return (fd);
712 712 }
713 713
714 714
715 715 /*
716 716 * Update file version number in a temporary file that's
717 717 * a copy of the keystore description file.
718 718 * The update is NOT made to the original keystore description
719 719 * file. It makes the update in a tempoary file.
720 720 *
721 721 * Name of the temporary file is assumed to be provided, but
722 722 * the file is assumed to not exist.
723 723 *
724 724 * return 0 if creating temp file is successful, returns -1 otherwise
725 725 */
726 726 static int
727 727 create_updated_keystore_version(int fd, char *tmp_fname)
728 728 {
729 729 int version, tmp_fd;
730 730 char buf[BUFSIZ];
731 731 size_t nread;
732 732
733 733 /* first, create the tempoary file */
734 734 tmp_fd = open_nointr(tmp_fname,
735 735 O_WRONLY|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
736 736 if (tmp_fd < 0) {
737 737 return (-1);
738 738 }
739 739
740 740 /*
741 741 * copy everything from keystore version to temp file except
742 742 * the keystore version. Keystore version is updated
743 743 *
744 744 */
745 745
746 746 /* pkcs11 version */
747 747 if (readn_nointr(fd, buf, KS_PKCS11_VER_SIZE) != KS_PKCS11_VER_SIZE) {
748 748 goto cleanup;
749 749 }
750 750
751 751 if (writen_nointr(tmp_fd, buf, KS_PKCS11_VER_SIZE) !=
752 752 KS_PKCS11_VER_SIZE) {
753 753 goto cleanup;
754 754 }
755 755
756 756 /* version number, it needs to be updated */
757 757
758 758 /* read the current version number */
759 759 if (readn_nointr(fd, &version, KS_VER_SIZE) != KS_VER_SIZE) {
760 760 goto cleanup;
761 761 }
762 762
763 763 version = SWAP32(version);
764 764 version++;
765 765 version = SWAP32(version);
766 766
767 767 /* write the updated value to the tmp file */
768 768 if (writen_nointr(tmp_fd, (void *)&version, KS_VER_SIZE)
769 769 != KS_VER_SIZE) {
770 770 goto cleanup;
771 771 }
772 772
773 773 /* read rest of information, nothing needs to be updated */
774 774 nread = readn_nointr(fd, buf, BUFSIZ);
775 775 while (nread > 0) {
776 776 if (writen_nointr(tmp_fd, buf, nread) != nread) {
777 777 goto cleanup;
778 778 }
779 779 nread = readn_nointr(fd, buf, BUFSIZ);
780 780 }
781 781
782 782 (void) close(tmp_fd);
783 783 return (0); /* no error */
784 784
785 785 cleanup:
786 786 (void) close(tmp_fd);
787 787 (void) remove(tmp_fname);
788 788 return (-1);
789 789 }
790 790
791 791 static CK_RV
792 792 get_all_objs_in_dir(DIR *dirp, ks_obj_handle_t *ks_handle,
793 793 ks_obj_t **result_obj_list, boolean_t lock_held)
794 794 {
795 795 struct dirent *dp;
796 796 ks_obj_t *obj;
797 797 CK_RV rv;
798 798
799 799 while ((dp = readdir(dirp)) != NULL) {
800 800
801 801 if (strncmp(dp->d_name, OBJ_PREFIX, OBJ_PREFIX_LEN) != 0)
802 802 continue;
803 803
804 804 (void) strcpy((char *)ks_handle->name, dp->d_name);
805 805 rv = soft_keystore_get_single_obj(ks_handle, &obj, lock_held);
806 806 if (rv != CKR_OK) {
807 807 return (rv);
808 808 }
809 809 if (obj != NULL) {
810 810 if (*result_obj_list == NULL) {
811 811 *result_obj_list = obj;
812 812 } else {
813 813 obj->next = *result_obj_list;
814 814 *result_obj_list = obj;
815 815 }
816 816 }
817 817 }
818 818 return (CKR_OK);
819 819 }
820 820
821 821 /*
822 822 * This function prepares the obj data for encryption by prepending
823 823 * the FULL path of the file that will be used for storing
824 824 * the object. Having full path of the file as part of
825 825 * of the data for the object will prevent an attacker from
826 826 * copying a "bad" object into the keystore undetected.
827 827 *
828 828 * This function will always allocate:
829 829 * MAXPATHLEN + buf_len
830 830 * amount of data. If the full path of the filename doesn't occupy
831 831 * the whole MAXPATHLEN, the rest of the space will just be empty.
832 832 * It is the caller's responsibility to free the buffer allocated here.
833 833 *
834 834 * The allocated buffer is returned in the variable "prepared_buf"
835 835 * if there's no error.
836 836 *
837 837 * Returns 0 if there's no error, -1 otherwise.
838 838 */
839 839 static int
840 840 prepare_data_for_encrypt(char *obj_path, unsigned char *buf, CK_ULONG buf_len,
841 841 unsigned char **prepared_buf, CK_ULONG *prepared_len)
842 842 {
843 843 *prepared_len = MAXPATHLEN + buf_len;
844 844 *prepared_buf = malloc(*prepared_len);
845 845 if (*prepared_buf == NULL) {
846 846 return (-1);
847 847 }
848 848
849 849 /*
850 850 * only zero out the space for the path name. I could zero out
851 851 * the whole buffer, but that will be a waste of processing
852 852 * cycle since the rest of the buffer will be 100% filled all
853 853 * the time
854 854 */
855 855 bzero(*prepared_buf, MAXPATHLEN);
856 856 (void) memcpy(*prepared_buf, obj_path, strlen(obj_path));
857 857 (void) memcpy(*prepared_buf + MAXPATHLEN, buf, buf_len);
858 858 return (0);
859 859 }
860 860
861 861 /*
862 862 * retrieves the hashed pin from the keystore
863 863 */
864 864 static CK_RV
865 865 get_hashed_pin(int fd, char **hashed_pin)
866 866 {
867 867 uint64_t hashed_pin_size;
868 868
869 869 if (ks_hashed_pinlen_offset == -1) {
870 870 if (calculate_hashed_pin_offset(fd) != 0) {
871 871 return (CKR_FUNCTION_FAILED);
872 872 }
873 873 }
874 874
875 875 /* first, get size of the hashed pin */
876 876 if (lseek(fd, ks_hashed_pinlen_offset, SEEK_SET)
877 877 != ks_hashed_pinlen_offset) {
878 878 return (CKR_FUNCTION_FAILED);
879 879 }
880 880
881 881 if (readn_nointr(fd, (char *)&hashed_pin_size,
882 882 KS_HASHED_PINLEN_SIZE) != KS_HASHED_PINLEN_SIZE) {
883 883 return (CKR_FUNCTION_FAILED);
884 884 }
↓ open down ↓ |
400 lines elided |
↑ open up ↑ |
885 885
886 886 hashed_pin_size = SWAP64(hashed_pin_size);
887 887
888 888 *hashed_pin = malloc(hashed_pin_size + 1);
889 889 if (*hashed_pin == NULL) {
890 890 return (CKR_HOST_MEMORY);
891 891 }
892 892
893 893 if ((readn_nointr(fd, *hashed_pin, hashed_pin_size))
894 894 != (ssize_t)hashed_pin_size) {
895 - free(*hashed_pin);
895 + freezero(*hashed_pin, hashed_pin_size + 1);
896 896 *hashed_pin = NULL;
897 897 return (CKR_FUNCTION_FAILED);
898 898 }
899 899 (*hashed_pin)[hashed_pin_size] = '\0';
900 900 return (CKR_OK);
901 901 }
902 902
903 903
904 904 /*
905 905 * FUNCTION: soft_keystore_lock
906 906 *
907 907 * ARGUMENTS:
908 908 * set_lock: TRUE to set readlock on the keystore object file,
909 909 * FALSE to remove readlock on keystore object file.
910 910 *
911 911 * RETURN VALUE:
912 912 *
913 913 * 0: success
914 914 * -1: failure
915 915 *
916 916 * DESCRIPTION:
917 917 *
918 918 * set or remove readlock on the keystore description file.
919 919 */
920 920 int
921 921 soft_keystore_readlock(boolean_t set_lock)
922 922 {
923 923
924 924 return (lock_desc_file(B_TRUE, set_lock));
925 925 }
926 926
927 927
928 928 /*
929 929 * FUNCTION: soft_keystore_writelock
930 930 *
931 931 * ARGUMENTS:
932 932 * set_lock: TRUE to set writelock on the keystore description file
933 933 * FALSE to remove write lock on keystore description file.
934 934 *
935 935 * RETURN VALUE:
936 936 *
937 937 * 0: no error
938 938 * 1: some error occurred
939 939 *
940 940 * DESCRIPTION:
941 941 * set/reset writelock on the keystore description file.
942 942 */
943 943 int
944 944 soft_keystore_writelock(boolean_t set_lock)
945 945 {
946 946 return (lock_desc_file(B_FALSE, set_lock));
947 947
948 948 }
949 949
950 950 /*
951 951 *
952 952 * FUNCTION: soft_keystore_lock_object
953 953 *
954 954 * ARGUMENTS:
955 955 *
956 956 * ks_handle: handle of the keystore object file to be accessed.
957 957 * read_lock: TRUE to set readlock on the keystore object file,
958 958 * FALSE to set writelock on keystore object file.
959 959 *
960 960 * RETURN VALUE:
961 961 *
962 962 * If no error, file descriptor of locked file will be returned
963 963 * -1: some error occurred
964 964 *
965 965 * DESCRIPTION:
966 966 *
967 967 * set readlock or writelock on the keystore object file.
968 968 */
969 969 int
970 970 soft_keystore_lock_object(ks_obj_handle_t *ks_handle, boolean_t read_lock)
971 971 {
972 972 int fd;
973 973 int oflag;
974 974
975 975 if (read_lock) {
976 976 oflag = O_RDONLY;
977 977 } else {
978 978 oflag = O_WRONLY;
979 979 }
980 980
981 981 if ((fd = open_and_lock_object_file(ks_handle, oflag, B_FALSE)) < 0) {
982 982 return (-1);
983 983 }
984 984
985 985 return (fd);
986 986 }
987 987
988 988 /*
989 989 * FUNCTION: soft_keystore_unlock_object
990 990 *
991 991 * ARGUMENTS:
992 992 * fd: file descriptor returned from soft_keystore_lock_object
993 993 *
994 994 * RETURN VALUE:
995 995 * 0: no error
996 996 * 1: some error occurred while getting the pin
997 997 *
998 998 * DESCRIPTION:
999 999 * set/reset writelock on the keystore object file.
1000 1000 */
1001 1001 int
1002 1002 soft_keystore_unlock_object(int fd)
1003 1003 {
1004 1004 if (lock_file(fd, B_TRUE, B_FALSE) != 0) {
1005 1005 return (1);
1006 1006 }
1007 1007
1008 1008 (void) close(fd);
1009 1009 return (0);
1010 1010 }
1011 1011
1012 1012
1013 1013
1014 1014 /*
1015 1015 * FUNCTION: soft_keystore_get_version
1016 1016 *
1017 1017 * ARGUMENTS:
1018 1018 * version: pointer to caller allocated memory for storing
1019 1019 * the version of the keystore.
1020 1020 * lock_held: TRUE if the lock is held by caller.
1021 1021 *
1022 1022 * RETURN VALUE:
1023 1023 *
1024 1024 * 0: no error
1025 1025 * -1: some error occurred while getting the version number
1026 1026 *
1027 1027 * DESCRIPTION:
1028 1028 * get the version number of the keystore from keystore
1029 1029 * description file.
1030 1030 */
1031 1031 int
1032 1032 soft_keystore_get_version(uint_t *version, boolean_t lock_held)
1033 1033 {
1034 1034 int fd, ret_val = 0;
1035 1035 uint_t buf;
1036 1036
1037 1037 if ((fd = open_and_lock_keystore_desc(O_RDONLY,
1038 1038 B_FALSE, lock_held)) < 0) {
1039 1039 return (-1);
1040 1040 }
1041 1041
1042 1042 if (lseek(fd, KS_VER_OFFSET, SEEK_SET) != KS_VER_OFFSET) {
1043 1043 ret_val = -1;
1044 1044 goto cleanup;
1045 1045 }
1046 1046
1047 1047 if (readn_nointr(fd, (char *)&buf, KS_VER_SIZE) != KS_VER_SIZE) {
1048 1048 ret_val = -1;
1049 1049 goto cleanup;
1050 1050 }
1051 1051 *version = SWAP32(buf);
1052 1052
1053 1053 cleanup:
1054 1054
1055 1055 if (!lock_held) {
1056 1056 if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
1057 1057 ret_val = -1;
1058 1058 }
1059 1059 }
1060 1060
1061 1061 (void) close(fd);
1062 1062 return (ret_val);
1063 1063 }
1064 1064
1065 1065 /*
1066 1066 * FUNCTION: soft_keystore_get_object_version
1067 1067 *
1068 1068 * ARGUMENTS:
1069 1069 *
1070 1070 * ks_handle: handle of the key store object to be accessed.
1071 1071 * version:
1072 1072 * pointer to caller allocated memory for storing
1073 1073 * the version of the object.
1074 1074 * lock_held: TRUE if the lock is held by caller.
1075 1075 *
1076 1076 * RETURN VALUE:
1077 1077 *
1078 1078 * 0: no error
1079 1079 * -1: some error occurred while getting the pin
1080 1080 *
1081 1081 * DESCRIPTION:
1082 1082 * get the version number of the specified token object.
1083 1083 */
1084 1084 int
1085 1085 soft_keystore_get_object_version(ks_obj_handle_t *ks_handle,
1086 1086 uint_t *version, boolean_t lock_held)
1087 1087 {
1088 1088 int fd, ret_val = 0;
1089 1089 uint_t tmp;
1090 1090
1091 1091 if ((fd = open_and_lock_object_file(ks_handle, O_RDONLY,
1092 1092 lock_held)) < 0) {
1093 1093 return (-1);
1094 1094 }
1095 1095
1096 1096 /*
1097 1097 * read version. Version is always first item in object file
1098 1098 * so, no need to do lseek
1099 1099 */
1100 1100 if (readn_nointr(fd, (char *)&tmp, OBJ_VER_SIZE) != OBJ_VER_SIZE) {
1101 1101 ret_val = -1;
1102 1102 goto cleanup;
1103 1103 }
1104 1104
1105 1105 *version = SWAP32(tmp);
1106 1106
1107 1107 cleanup:
1108 1108 if (!lock_held) {
1109 1109 if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
1110 1110 ret_val = -1;
1111 1111 }
1112 1112 }
1113 1113
1114 1114
1115 1115 (void) close(fd);
1116 1116 return (ret_val);
1117 1117 }
1118 1118
1119 1119 /*
1120 1120 * FUNCTION: soft_keystore_getpin
1121 1121 *
1122 1122 * ARGUMENTS:
1123 1123 * hashed_pin: pointer to caller allocated memory
1124 1124 * for storing the pin to be returned.
1125 1125 * lock_held: TRUE if the lock is held by caller.
1126 1126 *
1127 1127 * RETURN VALUE:
1128 1128 *
1129 1129 * 0: no error
1130 1130 * -1: some error occurred while getting the pin
1131 1131 *
1132 1132 * DESCRIPTION:
1133 1133 *
1134 1134 * Reads the MD5 hash from the keystore description
1135 1135 * file and return it to the caller in the provided
1136 1136 * buffer. If there is no PIN in the description file
1137 1137 * because the file is just created, this function
1138 1138 * will get a MD5 digest of the string "changeme",
1139 1139 * store it in the file, and also return this
1140 1140 * string to the caller.
1141 1141 */
1142 1142 int
1143 1143 soft_keystore_getpin(char **hashed_pin, boolean_t lock_held)
1144 1144 {
1145 1145 int fd, ret_val = -1;
1146 1146 CK_RV rv;
1147 1147
1148 1148 if ((fd = open_and_lock_keystore_desc(O_RDONLY, B_FALSE,
1149 1149 lock_held)) < 0) {
1150 1150 return (-1);
1151 1151 }
1152 1152
1153 1153 rv = get_hashed_pin(fd, hashed_pin);
1154 1154 if (rv == CKR_OK) {
1155 1155 ret_val = 0;
1156 1156 }
1157 1157
1158 1158 cleanup:
1159 1159 if (!lock_held) {
1160 1160 if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
1161 1161 ret_val = -1;
1162 1162 }
1163 1163 }
1164 1164
1165 1165 (void) close(fd);
1166 1166 return (ret_val);
1167 1167 }
1168 1168
1169 1169
1170 1170 /*
1171 1171 * Generate a 16-byte Initialization Vector (IV).
1172 1172 */
1173 1173 CK_RV
1174 1174 soft_gen_iv(CK_BYTE *iv)
1175 1175 {
1176 1176 return (pkcs11_get_nzero_urandom(iv, 16) < 0 ?
1177 1177 CKR_DEVICE_ERROR : CKR_OK);
1178 1178 }
1179 1179
1180 1180
1181 1181 /*
1182 1182 * This function reads all the data until the end of the file, and
1183 1183 * put the data into the "buf" in argument. Memory for buf will
1184 1184 * be allocated in this function. It is the caller's responsibility
1185 1185 * to free it. The number of bytes read will be returned
1186 1186 * in the argument "bytes_read"
1187 1187 *
1188 1188 * returns CKR_OK if no error. Other CKR error codes if there's an error
1189 1189 */
1190 1190 static CK_RV
1191 1191 read_obj_data(int old_fd, char **buf, ssize_t *bytes_read)
1192 1192 {
1193 1193
1194 1194 ssize_t nread, loop_count;
1195 1195 char *buf1 = NULL;
1196 1196
1197 1197 *buf = malloc(BUFSIZ);
1198 1198 if (*buf == NULL) {
1199 1199 return (CKR_HOST_MEMORY);
1200 1200 }
1201 1201
1202 1202 nread = readn_nointr(old_fd, *buf, BUFSIZ);
1203 1203 if (nread < 0) {
1204 1204 free(*buf);
1205 1205 return (CKR_FUNCTION_FAILED);
1206 1206 }
1207 1207 loop_count = 1;
1208 1208 while (nread == (loop_count * BUFSIZ)) {
1209 1209 ssize_t nread_tmp;
1210 1210
1211 1211 loop_count++;
1212 1212 /* more than BUFSIZ of data */
1213 1213 buf1 = realloc(*buf, loop_count * BUFSIZ);
1214 1214 if (buf1 == NULL) {
1215 1215 free(*buf);
1216 1216 return (CKR_HOST_MEMORY);
1217 1217 }
1218 1218 *buf = buf1;
1219 1219 nread_tmp = readn_nointr(old_fd,
1220 1220 *buf + ((loop_count - 1) * BUFSIZ), BUFSIZ);
1221 1221 if (nread_tmp < 0) {
1222 1222 free(*buf);
1223 1223 return (CKR_FUNCTION_FAILED);
1224 1224 }
1225 1225 nread += nread_tmp;
1226 1226 }
1227 1227 *bytes_read = nread;
1228 1228 return (CKR_OK);
1229 1229 }
1230 1230
1231 1231 /*
1232 1232 * Re-encrypt an object using the provided new_enc_key. The new HMAC
1233 1233 * is calculated using the new_hmac_key. The global static variables
1234 1234 * enc_key, and hmac_key will be used for decrypting the original
1235 1235 * object, and verifying its signature.
1236 1236 *
1237 1237 * The re-encrypted object will be stored in the file named
1238 1238 * in the "new_obj_name" variable. The content of the "original"
1239 1239 * file named in "orig_obj_name" is not disturbed.
1240 1240 *
1241 1241 * Returns 0 if there's no error, returns -1 otherwise.
1242 1242 *
1243 1243 */
1244 1244 static int
1245 1245 reencrypt_obj(soft_object_t *new_enc_key, soft_object_t *new_hmac_key,
1246 1246 char *orig_obj_name, char *new_obj_name) {
1247 1247
1248 1248 int old_fd, new_fd, version, ret_val = -1;
1249 1249 CK_BYTE iv[OBJ_IV_SIZE], old_iv[OBJ_IV_SIZE];
1250 1250 ssize_t nread;
1251 1251 CK_ULONG decrypted_len, encrypted_len, hmac_len;
1252 1252 CK_BYTE hmac[OBJ_HMAC_SIZE], *decrypted_buf = NULL, *buf = NULL;
1253 1253
1254 1254 old_fd = open_nointr(orig_obj_name, O_RDONLY|O_NONBLOCK);
1255 1255 if (old_fd < 0) {
1256 1256 return (-1);
1257 1257 }
1258 1258
1259 1259 if (acquire_file_lock(&old_fd, orig_obj_name, O_RDONLY) != 0) {
1260 1260 if (old_fd > 0) {
1261 1261 (void) close(old_fd);
1262 1262 }
1263 1263 return (-1);
1264 1264 }
1265 1265
1266 1266 new_fd = open_nointr(new_obj_name,
1267 1267 O_WRONLY|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
1268 1268 if (new_fd < 0) {
1269 1269 (void) close(old_fd);
1270 1270 return (-1);
1271 1271 }
1272 1272
1273 1273 if (lock_file(new_fd, B_FALSE, B_TRUE) != 0) {
1274 1274 /* unlock old file */
1275 1275 (void) lock_file(old_fd, B_TRUE, B_FALSE);
1276 1276 (void) close(old_fd);
1277 1277 (void) close(new_fd);
1278 1278 return (-1);
1279 1279 }
1280 1280
1281 1281 /* read version, increment, and write to tmp file */
1282 1282 if (readn_nointr(old_fd, (char *)&version, OBJ_VER_SIZE)
1283 1283 != OBJ_VER_SIZE) {
1284 1284 goto cleanup;
1285 1285 }
1286 1286
1287 1287 version = SWAP32(version);
1288 1288 version++;
1289 1289 version = SWAP32(version);
1290 1290
1291 1291 if (writen_nointr(new_fd, (char *)&version, OBJ_VER_SIZE)
1292 1292 != OBJ_VER_SIZE) {
1293 1293 goto cleanup;
1294 1294 }
1295 1295
1296 1296 /* read old iv */
1297 1297 if (readn_nointr(old_fd, (char *)old_iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) {
1298 1298 goto cleanup;
1299 1299 }
1300 1300
1301 1301 /* generate new IV */
1302 1302 if (soft_gen_iv(iv) != CKR_OK) {
1303 1303 goto cleanup;
1304 1304 }
1305 1305
1306 1306 if (writen_nointr(new_fd, (char *)iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) {
1307 1307 goto cleanup;
1308 1308 }
1309 1309
1310 1310 /* seek to the original encrypted data, and read all of them */
1311 1311 if (lseek(old_fd, OBJ_DATA_OFFSET, SEEK_SET) != OBJ_DATA_OFFSET) {
1312 1312 goto cleanup;
↓ open down ↓ |
407 lines elided |
↑ open up ↑ |
1313 1313 }
1314 1314
1315 1315 if (read_obj_data(old_fd, (char **)&buf, &nread) != CKR_OK) {
1316 1316 goto cleanup;
1317 1317 }
1318 1318
1319 1319 /* decrypt data using old key */
1320 1320 decrypted_len = 0;
1321 1321 if (soft_keystore_crypt(enc_key, old_iv, B_FALSE, buf, nread,
1322 1322 NULL, &decrypted_len) != CKR_OK) {
1323 - free(buf);
1323 + freezero(buf, nread);
1324 1324 goto cleanup;
1325 1325 }
1326 1326
1327 1327 decrypted_buf = malloc(decrypted_len);
1328 1328 if (decrypted_buf == NULL) {
1329 - free(buf);
1329 + freezero(buf, nread);
1330 1330 goto cleanup;
1331 1331 }
1332 1332
1333 1333 if (soft_keystore_crypt(enc_key, old_iv, B_FALSE, buf, nread,
1334 1334 decrypted_buf, &decrypted_len) != CKR_OK) {
1335 - free(buf);
1336 - free(decrypted_buf);
1337 - goto cleanup;
1335 + freezero(buf, nread);
1336 + freezero(decrypted_buf, decrypted_len);
1338 1337 }
1339 1338
1340 - free(buf);
1339 + freezero(buf, nread);
1341 1340
1342 1341 /* re-encrypt with new key */
1343 1342 encrypted_len = 0;
1344 1343 if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf,
1345 1344 decrypted_len, NULL, &encrypted_len) != CKR_OK) {
1346 - free(decrypted_buf);
1345 + freezero(decrypted_buf, decrypted_len);
1347 1346 goto cleanup;
1348 1347 }
1349 1348
1350 1349 buf = malloc(encrypted_len);
1351 1350 if (buf == NULL) {
1352 - free(decrypted_buf);
1351 + freezero(decrypted_buf, decrypted_len);
1353 1352 goto cleanup;
1354 1353 }
1355 1354
1356 1355 if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf,
1357 1356 decrypted_len, buf, &encrypted_len) != CKR_OK) {
1358 - free(buf);
1359 - free(decrypted_buf);
1357 + freezero(buf, encrypted_len);
1358 + freezero(buf, decrypted_len);
1360 1359 goto cleanup;
1361 1360 }
1362 1361
1363 - free(decrypted_buf);
1362 + freezero(decrypted_buf, decrypted_len);
1364 1363
1365 1364 /* calculate hmac on re-encrypted data using new hmac key */
1366 1365 hmac_len = OBJ_HMAC_SIZE;
1367 1366 if (soft_keystore_hmac(new_hmac_key, B_TRUE, buf,
1368 1367 encrypted_len, hmac, &hmac_len) != CKR_OK) {
1369 - free(buf);
1368 + freezero(buf, encrypted_len);
1370 1369 goto cleanup;
1371 1370 }
1372 1371
1373 1372 /* just for sanity check */
1374 1373 if (hmac_len != OBJ_HMAC_SIZE) {
1375 - free(buf);
1374 + freezero(buf, encrypted_len);
1376 1375 goto cleanup;
1377 1376 }
1378 1377
1379 1378 /* write new hmac */
1380 1379 if (writen_nointr(new_fd, (char *)hmac, OBJ_HMAC_SIZE)
1381 1380 != OBJ_HMAC_SIZE) {
1382 - free(buf);
1381 + freezero(buf, encrypted_len);
1383 1382 goto cleanup;
1384 1383 }
1385 1384
1386 1385 /* write re-encrypted buffer to temp file */
1387 1386 if (writen_nointr(new_fd, (void *)buf, encrypted_len)
1388 1387 != encrypted_len) {
1389 - free(buf);
1388 + freezero(buf, encrypted_len);
1390 1389 goto cleanup;
1391 1390 }
1392 - free(buf);
1391 + freezero(buf, encrypted_len);
1393 1392 ret_val = 0;
1394 1393
1395 1394 cleanup:
1396 1395 /* unlock the files */
1397 1396 (void) lock_file(old_fd, B_TRUE, B_FALSE);
1398 1397 (void) lock_file(new_fd, B_FALSE, B_FALSE);
1399 1398
1400 1399 (void) close(old_fd);
1401 1400 (void) close(new_fd);
1402 1401 if (ret_val != 0) {
1403 1402 (void) remove(new_obj_name);
1404 1403 }
1405 1404 return (ret_val);
1406 1405 }
1407 1406
1408 1407 /*
1409 1408 * FUNCTION: soft_keystore_setpin
1410 1409 *
1411 1410 * ARGUMENTS:
1412 1411 * newpin: new pin entered by the user.
1413 1412 * lock_held: TRUE if the lock is held by caller.
1414 1413 *
1415 1414 * RETURN VALUE:
1416 1415 * 0: no error
1417 1416 * -1: failure
1418 1417 *
1419 1418 * DESCRIPTION:
1420 1419 *
1421 1420 * This function does the following:
1422 1421 *
1423 1422 * 1) Generates crypted value of newpin and store it
1424 1423 * in keystore description file.
1425 1424 * 2) Dervies the new encryption key from the newpin. This key
1426 1425 * will be used to re-encrypt the private token objects.
1427 1426 * 3) Re-encrypt all of this user's existing private token
1428 1427 * objects (if any).
1429 1428 * 4) Increments the keystore version number.
1430 1429 */
1431 1430 int
1432 1431 soft_keystore_setpin(uchar_t *oldpin, uchar_t *newpin, boolean_t lock_held)
1433 1432 {
1434 1433 int fd, tmp_ks_fd, version, ret_val = -1;
1435 1434 soft_object_t *new_crypt_key = NULL, *new_hmac_key = NULL;
1436 1435 char filebuf[BUFSIZ];
1437 1436 DIR *pri_dirp;
1438 1437 struct dirent *pri_ent;
1439 1438 char pri_obj_path[MAXPATHLEN], ks_desc_file[MAXPATHLEN],
1440 1439 tmp_ks_desc_name[MAXPATHLEN];
1441 1440 typedef struct priobjs {
1442 1441 char orig_name[MAXPATHLEN];
1443 1442 char tmp_name[MAXPATHLEN];
1444 1443 struct priobjs *next;
1445 1444 } priobjs_t;
1446 1445 priobjs_t *pri_objs = NULL, *tmp;
1447 1446 CK_BYTE *crypt_salt = NULL, *hmac_salt = NULL;
1448 1447 boolean_t pin_never_set = B_FALSE, user_logged_in;
1449 1448 char *new_hashed_pin = NULL;
1450 1449 uint64_t hashed_pin_salt_length, new_hashed_pin_len, swaped_val;
1451 1450 char *hashed_pin_salt = NULL;
1452 1451 priobjs_t *obj;
1453 1452
1454 1453 if ((enc_key == NULL) ||
1455 1454 (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
1456 1455 user_logged_in = B_FALSE;
1457 1456 } else {
1458 1457 user_logged_in = B_TRUE;
1459 1458 }
1460 1459
1461 1460 if ((fd = open_and_lock_keystore_desc(O_RDWR, B_TRUE,
1462 1461 lock_held)) < 0) {
1463 1462 return (-1);
1464 1463 }
1465 1464
1466 1465 (void) get_desc_file_path(ks_desc_file);
1467 1466 (void) get_tmp_desc_file_path(tmp_ks_desc_name);
1468 1467
1469 1468 /*
1470 1469 * create a tempoary file for the keystore description
1471 1470 * file for updating version and counter information
1472 1471 */
1473 1472 tmp_ks_fd = open_nointr(tmp_ks_desc_name,
1474 1473 O_RDWR|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
1475 1474 if (tmp_ks_fd < 0) {
1476 1475 (void) close(fd);
1477 1476 return (-1);
1478 1477 }
1479 1478
1480 1479 /* read and write PKCS version to temp file */
1481 1480 if (readn_nointr(fd, filebuf, KS_PKCS11_VER_SIZE)
1482 1481 != KS_PKCS11_VER_SIZE) {
1483 1482 goto cleanup;
1484 1483 }
1485 1484
1486 1485 if (writen_nointr(tmp_ks_fd, filebuf, KS_PKCS11_VER_SIZE)
1487 1486 != KS_PKCS11_VER_SIZE) {
1488 1487 goto cleanup;
1489 1488 }
1490 1489
1491 1490 /* get version number, and write updated number to temp file */
1492 1491 if (readn_nointr(fd, &version, KS_VER_SIZE) != KS_VER_SIZE) {
1493 1492 goto cleanup;
1494 1493 }
1495 1494
1496 1495 version = SWAP32(version);
1497 1496 version++;
1498 1497 version = SWAP32(version);
1499 1498
1500 1499 if (writen_nointr(tmp_ks_fd, (void *)&version, KS_VER_SIZE)
1501 1500 != KS_VER_SIZE) {
1502 1501 goto cleanup;
1503 1502 }
1504 1503
1505 1504
1506 1505 /* read and write counter, no modification necessary */
1507 1506 if (readn_nointr(fd, filebuf, KS_COUNTER_SIZE) != KS_COUNTER_SIZE) {
1508 1507 goto cleanup;
1509 1508 }
1510 1509
1511 1510 if (writen_nointr(tmp_ks_fd, filebuf, KS_COUNTER_SIZE)
1512 1511 != KS_COUNTER_SIZE) {
1513 1512 goto cleanup;
1514 1513 }
1515 1514
1516 1515 /* read old encryption salt */
1517 1516 crypt_salt = malloc(KS_KEY_SALT_SIZE);
1518 1517 if (crypt_salt == NULL) {
1519 1518 goto cleanup;
1520 1519 }
1521 1520 if (readn_nointr(fd, (char *)crypt_salt, KS_KEY_SALT_SIZE)
1522 1521 != KS_KEY_SALT_SIZE) {
1523 1522 goto cleanup;
1524 1523 }
1525 1524
1526 1525 /* read old hmac salt */
1527 1526 hmac_salt = malloc(KS_HMAC_SALT_SIZE);
1528 1527 if (hmac_salt == NULL) {
1529 1528 goto cleanup;
1530 1529 }
1531 1530 if (readn_nointr(fd, (char *)hmac_salt, KS_HMAC_SALT_SIZE)
1532 1531 != KS_HMAC_SALT_SIZE) {
1533 1532 goto cleanup;
1534 1533 }
1535 1534
1536 1535 /* just create some empty bytes */
1537 1536 bzero(filebuf, sizeof (filebuf));
1538 1537
1539 1538 if (memcmp(crypt_salt, filebuf, KS_KEY_SALT_SIZE) == 0) {
↓ open down ↓ |
137 lines elided |
↑ open up ↑ |
1540 1539 /* PIN as never been set */
1541 1540 CK_BYTE *new_crypt_salt = NULL, *new_hmac_salt = NULL;
1542 1541
1543 1542 pin_never_set = B_TRUE;
1544 1543 if (soft_gen_crypt_key(newpin, &new_crypt_key, &new_crypt_salt)
1545 1544 != CKR_OK) {
1546 1545 goto cleanup;
1547 1546 }
1548 1547 if (writen_nointr(tmp_ks_fd, (void *)new_crypt_salt,
1549 1548 KS_KEY_SALT_SIZE) != KS_KEY_SALT_SIZE) {
1550 - free(new_crypt_salt);
1549 + freezero(new_crypt_salt,
1550 + KS_KEY_SALT_SIZE);
1551 1551 (void) soft_cleanup_object(new_crypt_key);
1552 1552 goto cleanup;
1553 1553 }
1554 - free(new_crypt_salt);
1554 + freezero(new_crypt_salt, KS_KEY_SALT_SIZE);
1555 1555
1556 1556 if (soft_gen_hmac_key(newpin, &new_hmac_key, &new_hmac_salt)
1557 1557 != CKR_OK) {
1558 1558 (void) soft_cleanup_object(new_crypt_key);
1559 1559 goto cleanup;
1560 1560 }
1561 1561 if (writen_nointr(tmp_ks_fd, (void *)new_hmac_salt,
1562 1562 KS_HMAC_SALT_SIZE) != KS_HMAC_SALT_SIZE) {
1563 - free(new_hmac_salt);
1563 + freezero(new_hmac_salt,
1564 + KS_HMAC_SALT_SIZE);
1564 1565 goto cleanup3;
1565 1566 }
1566 - free(new_hmac_salt);
1567 + freezero(new_hmac_salt, KS_HMAC_SALT_SIZE);
1567 1568 } else {
1568 1569 if (soft_gen_crypt_key(newpin, &new_crypt_key,
1569 1570 (CK_BYTE **)&crypt_salt) != CKR_OK) {
1570 1571 goto cleanup;
1571 1572 }
1572 1573 /* no change to the encryption salt */
1573 1574 if (writen_nointr(tmp_ks_fd, (void *)crypt_salt,
1574 1575 KS_KEY_SALT_SIZE) != KS_KEY_SALT_SIZE) {
1575 1576 (void) soft_cleanup_object(new_crypt_key);
1576 1577 goto cleanup;
1577 1578 }
1578 1579
1579 1580 if (soft_gen_hmac_key(newpin, &new_hmac_key,
1580 1581 (CK_BYTE **)&hmac_salt) != CKR_OK) {
1581 1582 (void) soft_cleanup_object(new_crypt_key);
1582 1583 goto cleanup;
1583 1584 }
1584 1585
1585 1586 /* no change to the hmac salt */
1586 1587 if (writen_nointr(tmp_ks_fd, (void *)hmac_salt,
1587 1588 KS_HMAC_SALT_SIZE) != KS_HMAC_SALT_SIZE) {
1588 1589 goto cleanup3;
1589 1590 }
1590 1591 }
1591 1592
1592 1593 /*
1593 1594 * read hashed pin salt, and write to updated keystore description
1594 1595 * file unmodified.
1595 1596 */
1596 1597 if (readn_nointr(fd, (char *)&hashed_pin_salt_length,
1597 1598 KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
1598 1599 goto cleanup3;
1599 1600 }
1600 1601
1601 1602 if (writen_nointr(tmp_ks_fd, (void *)&hashed_pin_salt_length,
1602 1603 KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
1603 1604 goto cleanup3;
1604 1605 }
↓ open down ↓ |
28 lines elided |
↑ open up ↑ |
1605 1606
1606 1607 hashed_pin_salt_length = SWAP64(hashed_pin_salt_length);
1607 1608
1608 1609 hashed_pin_salt = malloc(hashed_pin_salt_length + 1);
1609 1610 if (hashed_pin_salt == NULL) {
1610 1611 goto cleanup3;
1611 1612 }
1612 1613
1613 1614 if ((readn_nointr(fd, hashed_pin_salt, hashed_pin_salt_length)) !=
1614 1615 (ssize_t)hashed_pin_salt_length) {
1615 - free(hashed_pin_salt);
1616 + freezero(hashed_pin_salt,
1617 + hashed_pin_salt_length + 1);
1616 1618 goto cleanup3;
1617 1619 }
1618 1620
1619 1621 if ((writen_nointr(tmp_ks_fd, hashed_pin_salt, hashed_pin_salt_length))
1620 1622 != (ssize_t)hashed_pin_salt_length) {
1621 - free(hashed_pin_salt);
1623 + freezero(hashed_pin_salt,
1624 + hashed_pin_salt_length + 1);
1622 1625 goto cleanup3;
1623 1626 }
1624 1627
1625 1628 hashed_pin_salt[hashed_pin_salt_length] = '\0';
1626 1629
1627 1630 /* old hashed pin length and value can be ignored, generate new one */
1628 1631 if (soft_gen_hashed_pin(newpin, &new_hashed_pin,
1629 1632 &hashed_pin_salt) < 0) {
1630 - free(hashed_pin_salt);
1633 + freezero(hashed_pin_salt,
1634 + hashed_pin_salt_length + 1);
1631 1635 goto cleanup3;
1632 1636 }
1633 1637
1634 - free(hashed_pin_salt);
1638 + freezero(hashed_pin_salt, hashed_pin_salt_length + 1);
1635 1639
1636 1640 if (new_hashed_pin == NULL) {
1637 1641 goto cleanup3;
1638 1642 }
1639 1643
1640 1644 new_hashed_pin_len = strlen(new_hashed_pin);
1641 1645
1642 1646 /* write new hashed pin length to file */
1643 1647 swaped_val = SWAP64(new_hashed_pin_len);
1644 1648 if (writen_nointr(tmp_ks_fd, (void *)&swaped_val,
1645 1649 KS_HASHED_PINLEN_SIZE) != KS_HASHED_PINLEN_SIZE) {
1646 1650 goto cleanup3;
1647 1651 }
1648 1652
1649 1653 if (writen_nointr(tmp_ks_fd, (void *)new_hashed_pin,
1650 1654 new_hashed_pin_len) != (ssize_t)new_hashed_pin_len) {
1651 1655 goto cleanup3;
1652 1656 }
1653 1657
1654 1658 if (pin_never_set) {
1655 1659 /* there was no private object, no need to re-encrypt them */
1656 1660 goto rename_desc_file;
1657 1661 }
1658 1662
1659 1663 /* re-encrypt all the private objects */
1660 1664 pri_dirp = opendir(get_pri_obj_path(pri_obj_path));
1661 1665 if (pri_dirp == NULL) {
1662 1666 /*
1663 1667 * this directory should exist, even if it doesn't contain
1664 1668 * any objects. Don't want to update the pin if the
1665 1669 * keystore is somehow messed up.
1666 1670 */
1667 1671
1668 1672 goto cleanup3;
1669 1673 }
1670 1674
1671 1675 /* if user did not login, need to set the old pin */
1672 1676 if (!user_logged_in) {
1673 1677 if (soft_keystore_authpin(oldpin) != 0) {
1674 1678 goto cleanup3;
1675 1679 }
1676 1680 }
1677 1681
1678 1682 while ((pri_ent = readdir(pri_dirp)) != NULL) {
1679 1683
1680 1684 if ((strcmp(pri_ent->d_name, ".") == 0) ||
1681 1685 (strcmp(pri_ent->d_name, "..") == 0) ||
1682 1686 (strncmp(pri_ent->d_name, TMP_OBJ_PREFIX,
1683 1687 strlen(TMP_OBJ_PREFIX)) == 0)) {
1684 1688 continue;
1685 1689 }
1686 1690
1687 1691 obj = malloc(sizeof (priobjs_t));
1688 1692 if (obj == NULL) {
1689 1693 goto cleanup2;
1690 1694 }
1691 1695 (void) snprintf(obj->orig_name, MAXPATHLEN,
1692 1696 "%s/%s", pri_obj_path, pri_ent->d_name);
1693 1697 (void) snprintf(obj->tmp_name, MAXPATHLEN, "%s/%s%s",
1694 1698 pri_obj_path, TMP_OBJ_PREFIX,
1695 1699 (pri_ent->d_name) + OBJ_PREFIX_LEN);
1696 1700 if (reencrypt_obj(new_crypt_key, new_hmac_key,
1697 1701 obj->orig_name, obj->tmp_name) != 0) {
1698 1702 free(obj);
1699 1703 goto cleanup2;
1700 1704 }
1701 1705
1702 1706 /* insert into list of file to be renamed */
1703 1707 if (pri_objs == NULL) {
1704 1708 obj->next = NULL;
1705 1709 pri_objs = obj;
1706 1710 } else {
1707 1711 obj->next = pri_objs;
1708 1712 pri_objs = obj;
1709 1713 }
1710 1714 }
1711 1715
1712 1716 /* rename all the private objects */
1713 1717 tmp = pri_objs;
1714 1718 while (tmp) {
1715 1719 (void) rename(tmp->tmp_name, tmp->orig_name);
1716 1720 tmp = tmp->next;
1717 1721 }
1718 1722
1719 1723 rename_desc_file:
1720 1724
1721 1725 /* destroy the old encryption key, and hmac key */
1722 1726 if ((!pin_never_set) && (user_logged_in)) {
1723 1727 (void) soft_cleanup_object(enc_key);
1724 1728 (void) soft_cleanup_object(hmac_key);
1725 1729 }
1726 1730
1727 1731 if (user_logged_in) {
1728 1732 enc_key = new_crypt_key;
1729 1733 hmac_key = new_hmac_key;
1730 1734 }
1731 1735 (void) rename(tmp_ks_desc_name, ks_desc_file);
1732 1736
1733 1737 ret_val = 0;
1734 1738
1735 1739 cleanup2:
1736 1740 if (pri_objs != NULL) {
1737 1741 priobjs_t *p = pri_objs;
1738 1742 while (p) {
1739 1743 tmp = p->next;
1740 1744 free(p);
1741 1745 p = tmp;
1742 1746 }
1743 1747 }
1744 1748 if (!pin_never_set) {
1745 1749 (void) closedir(pri_dirp);
1746 1750 }
1747 1751
1748 1752 if ((!user_logged_in) && (!pin_never_set)) {
1749 1753 (void) soft_cleanup_object(enc_key);
1750 1754 (void) soft_cleanup_object(hmac_key);
1751 1755 enc_key = NULL;
1752 1756 hmac_key = NULL;
1753 1757 }
1754 1758 cleanup3:
1755 1759 if ((ret_val != 0) || (!user_logged_in)) {
↓ open down ↓ |
111 lines elided |
↑ open up ↑ |
1756 1760 (void) soft_cleanup_object(new_crypt_key);
1757 1761 (void) soft_cleanup_object(new_hmac_key);
1758 1762 }
1759 1763
1760 1764 cleanup:
1761 1765 if (!lock_held) {
1762 1766 if (lock_file(fd, B_FALSE, B_FALSE) < 0) {
1763 1767 ret_val = 1;
1764 1768 }
1765 1769 }
1766 - if (crypt_salt != NULL) {
1767 - free(crypt_salt);
1768 - }
1769 - if (hmac_salt != NULL) {
1770 - free(hmac_salt);
1771 - }
1770 + freezero(crypt_salt, KS_KEY_SALT_SIZE);
1771 + freezero(hmac_salt, KS_HMAC_SALT_SIZE);
1772 1772 (void) close(fd);
1773 1773 (void) close(tmp_ks_fd);
1774 1774 if (ret_val != 0) {
1775 1775 (void) remove(tmp_ks_desc_name);
1776 1776 }
1777 1777 return (ret_val);
1778 1778 }
1779 1779
1780 1780 /*
1781 1781 * FUNCTION: soft_keystore_authpin
1782 1782 *
1783 1783 * ARGUMENTS:
1784 1784 * pin: pin specified by the user for logging into
1785 1785 * the keystore.
1786 1786 *
1787 1787 * RETURN VALUE:
1788 1788 * 0: if no error
1789 1789 * -1: if there is any error
1790 1790 *
1791 1791 * DESCRIPTION:
1792 1792 *
1793 1793 * This function takes the pin specified in the argument
1794 1794 * and generates an encryption key based on the pin.
1795 1795 * The generated encryption key will be used for
1796 1796 * all future encryption and decryption for private
1797 1797 * objects. Before this function is called, none
1798 1798 * of the keystore related interfaces is able
1799 1799 * to decrypt/encrypt any private object.
1800 1800 */
1801 1801 int
1802 1802 soft_keystore_authpin(uchar_t *pin)
1803 1803 {
1804 1804 int fd;
1805 1805 int ret_val = -1;
1806 1806 CK_BYTE *crypt_salt = NULL, *hmac_salt;
1807 1807
1808 1808 /* get the salt from the keystore description file */
1809 1809 if ((fd = open_and_lock_keystore_desc(O_RDONLY,
1810 1810 B_FALSE, B_FALSE)) < 0) {
1811 1811 return (-1);
1812 1812 }
1813 1813
1814 1814 crypt_salt = malloc(KS_KEY_SALT_SIZE);
1815 1815 if (crypt_salt == NULL) {
1816 1816 goto cleanup;
1817 1817 }
1818 1818
1819 1819 if (lseek(fd, KS_KEY_SALT_OFFSET, SEEK_SET) != KS_KEY_SALT_OFFSET) {
1820 1820 goto cleanup;
1821 1821 }
1822 1822
1823 1823 if (readn_nointr(fd, (char *)crypt_salt, KS_KEY_SALT_SIZE)
1824 1824 != KS_KEY_SALT_SIZE) {
1825 1825 goto cleanup;
1826 1826 }
1827 1827
1828 1828 if (soft_gen_crypt_key(pin, &enc_key, (CK_BYTE **)&crypt_salt)
1829 1829 != CKR_OK) {
1830 1830 goto cleanup;
1831 1831 }
1832 1832
1833 1833 hmac_salt = malloc(KS_HMAC_SALT_SIZE);
1834 1834 if (hmac_salt == NULL) {
1835 1835 goto cleanup;
1836 1836 }
1837 1837
1838 1838 if (lseek(fd, KS_HMAC_SALT_OFFSET, SEEK_SET) != KS_HMAC_SALT_OFFSET) {
1839 1839 goto cleanup;
1840 1840 }
1841 1841
1842 1842 if (readn_nointr(fd, (char *)hmac_salt, KS_HMAC_SALT_SIZE)
1843 1843 != KS_HMAC_SALT_SIZE) {
1844 1844 goto cleanup;
1845 1845 }
1846 1846
1847 1847 if (soft_gen_hmac_key(pin, &hmac_key, (CK_BYTE **)&hmac_salt)
↓ open down ↓ |
66 lines elided |
↑ open up ↑ |
1848 1848 != CKR_OK) {
1849 1849 goto cleanup;
1850 1850 }
1851 1851
1852 1852 ret_val = 0;
1853 1853
1854 1854 cleanup:
1855 1855 /* unlock the file */
1856 1856 (void) lock_file(fd, B_TRUE, B_FALSE);
1857 1857 (void) close(fd);
1858 - if (crypt_salt != NULL) {
1859 - free(crypt_salt);
1860 - }
1861 - if (hmac_salt != NULL) {
1862 - free(hmac_salt);
1863 - }
1858 + freezero(crypt_salt, KS_KEY_SALT_SIZE);
1859 + freezero(hmac_salt, KS_HMAC_SALT_SIZE);
1864 1860 return (ret_val);
1865 1861 }
1866 1862
1867 1863 /*
1868 - * FUNCTION: soft_keystore_get_objs
1864 + * FUNCTION: soft_keystore_get_objs
1869 1865 *
1870 1866 * ARGUMENTS:
1871 1867 *
1872 1868 * search_type: Specify type of objects to return.
1873 1869 * lock_held: TRUE if the lock is held by caller.
1874 1870 *
1875 1871 *
1876 1872 * RETURN VALUE:
1877 1873 *
1878 1874 * NULL: if there are no object in the database.
1879 1875 *
1880 1876 * Otherwise, linked list of objects as requested
1881 1877 * in search type.
1882 1878 *
1883 1879 * The linked list returned will need to be freed
1884 1880 * by the caller.
1885 1881 *
1886 1882 * DESCRIPTION:
1887 1883 *
1888 1884 * Returns objects as requested.
1889 1885 *
1890 1886 * If private objects is requested, and the caller
1891 1887 * has not previously passed in the pin or if the pin
1892 1888 * passed in is wrong, private objects will not
1893 1889 * be returned.
1894 1890 *
1895 1891 * The buffers returned for private objects are already
1896 1892 * decrypted.
1897 1893 */
1898 1894 CK_RV
1899 1895 soft_keystore_get_objs(ks_search_type_t search_type,
1900 1896 ks_obj_t **result_obj_list, boolean_t lock_held)
1901 1897 {
1902 1898 DIR *dirp;
1903 1899 ks_obj_handle_t ks_handle;
1904 1900 CK_RV rv;
1905 1901 ks_obj_t *tmp;
1906 1902 int ks_fd;
1907 1903
1908 1904 *result_obj_list = NULL;
1909 1905
1910 1906 /*
1911 1907 * lock the keystore description file in "read" mode so that
1912 1908 * objects won't get added/deleted/modified while we are
1913 1909 * doing the search
1914 1910 */
1915 1911 if ((ks_fd = open_and_lock_keystore_desc(O_RDONLY, B_FALSE,
1916 1912 B_FALSE)) < 0) {
1917 1913 return (CKR_FUNCTION_FAILED);
1918 1914 }
1919 1915
1920 1916 if ((search_type == ALL_TOKENOBJS) || (search_type == PUB_TOKENOBJS)) {
1921 1917
1922 1918 char pub_obj_path[MAXPATHLEN];
1923 1919
1924 1920 ks_handle.public = B_TRUE;
1925 1921
1926 1922 if ((dirp = opendir(get_pub_obj_path(pub_obj_path))) == NULL) {
1927 1923 (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1928 1924 (void) close(ks_fd);
1929 1925 return (CKR_FUNCTION_FAILED);
1930 1926 }
1931 1927 rv = get_all_objs_in_dir(dirp, &ks_handle, result_obj_list,
1932 1928 lock_held);
1933 1929 if (rv != CKR_OK) {
1934 1930 (void) closedir(dirp);
1935 1931 goto cleanup;
1936 1932 }
1937 1933
1938 1934 (void) closedir(dirp);
1939 1935 }
1940 1936
1941 1937 if ((search_type == ALL_TOKENOBJS) || (search_type == PRI_TOKENOBJS)) {
1942 1938
1943 1939 char pri_obj_path[MAXPATHLEN];
1944 1940
1945 1941 if ((enc_key == NULL) ||
1946 1942 (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
1947 1943 /* has not login - no need to go any further */
1948 1944 (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1949 1945 (void) close(ks_fd);
1950 1946 return (CKR_OK);
1951 1947 }
1952 1948
1953 1949 ks_handle.public = B_FALSE;
1954 1950
1955 1951 if ((dirp = opendir(get_pri_obj_path(pri_obj_path))) == NULL) {
1956 1952 (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1957 1953 (void) close(ks_fd);
1958 1954 return (CKR_OK);
1959 1955 }
1960 1956 rv = get_all_objs_in_dir(dirp, &ks_handle, result_obj_list,
1961 1957 lock_held);
1962 1958 if (rv != CKR_OK) {
1963 1959 (void) closedir(dirp);
1964 1960 goto cleanup;
1965 1961 }
1966 1962
1967 1963 (void) closedir(dirp);
1968 1964 }
1969 1965 /* close the keystore description file */
1970 1966 (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1971 1967 (void) close(ks_fd);
1972 1968 return (CKR_OK);
↓ open down ↓ |
94 lines elided |
↑ open up ↑ |
1973 1969 cleanup:
1974 1970
1975 1971 /* close the keystore description file */
1976 1972 (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1977 1973 (void) close(ks_fd);
1978 1974
1979 1975 /* free all the objects found before hitting the error */
1980 1976 tmp = *result_obj_list;
1981 1977 while (tmp) {
1982 1978 *result_obj_list = tmp->next;
1983 - free(tmp->buf);
1979 + freezero(tmp->buf, tmp->size);
1984 1980 free(tmp);
1985 1981 tmp = *result_obj_list;
1986 1982 }
1987 1983 *result_obj_list = NULL;
1988 1984 return (rv);
1989 1985 }
1990 1986
1991 1987
1992 1988 /*
1993 1989 * FUNCTION: soft_keystore_get_single_obj
1994 1990 *
1995 1991 * ARGUMENTS:
1996 1992 * ks_handle: handle of the key store object to be accessed
1997 1993 * lock_held: TRUE if the lock is held by caller.
1998 1994 *
1999 1995 * RETURN VALUE:
2000 1996 *
2001 1997 * NULL: if handle doesn't match any object
2002 1998 *
2003 1999 * Otherwise, the object is returned in
2004 2000 * the same structure used in soft_keystore_get_objs().
2005 2001 * The structure need to be freed by the caller.
2006 2002 *
2007 2003 * DESCRIPTION:
2008 2004 *
2009 2005 * Retrieves the object specified by the object
2010 2006 * handle to the caller.
2011 2007 *
2012 2008 * If a private object is requested, and the caller
2013 2009 * has not previously passed in the pin or if the pin
2014 2010 * passed in is wrong, the requested private object will not
2015 2011 * be returned.
2016 2012 *
2017 2013 * The buffer returned for the requested private object
2018 2014 * is already decrypted.
2019 2015 */
2020 2016 CK_RV
2021 2017 soft_keystore_get_single_obj(ks_obj_handle_t *ks_handle,
2022 2018 ks_obj_t **return_obj, boolean_t lock_held)
2023 2019 {
2024 2020
2025 2021 ks_obj_t *obj;
2026 2022 uchar_t iv[OBJ_IV_SIZE], obj_hmac[OBJ_HMAC_SIZE];
2027 2023 uchar_t *buf, *decrypted_buf;
2028 2024 int fd;
2029 2025 ssize_t nread;
2030 2026 CK_RV rv = CKR_FUNCTION_FAILED;
2031 2027
2032 2028 if (!(ks_handle->public)) {
2033 2029 if ((enc_key == NULL) ||
2034 2030 (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
2035 2031 return (CKR_FUNCTION_FAILED);
2036 2032 }
2037 2033 }
2038 2034
2039 2035 if ((fd = open_and_lock_object_file(ks_handle, O_RDONLY,
2040 2036 lock_held)) < 0) {
2041 2037 return (CKR_FUNCTION_FAILED);
2042 2038 }
2043 2039
2044 2040 obj = malloc(sizeof (ks_obj_t));
2045 2041 if (obj == NULL) {
2046 2042 return (CKR_HOST_MEMORY);
2047 2043 }
2048 2044
2049 2045 obj->next = NULL;
2050 2046
2051 2047 (void) strcpy((char *)((obj->ks_handle).name),
2052 2048 (char *)ks_handle->name);
2053 2049 (obj->ks_handle).public = ks_handle->public;
2054 2050
2055 2051 /* 1st get the version */
2056 2052 if (readn_nointr(fd, &(obj->obj_version), OBJ_VER_SIZE)
2057 2053 != OBJ_VER_SIZE) {
2058 2054 goto cleanup;
2059 2055 }
2060 2056 obj->obj_version = SWAP32(obj->obj_version);
2061 2057
2062 2058 /* Then, read the IV */
2063 2059 if (readn_nointr(fd, iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) {
2064 2060 goto cleanup;
2065 2061 }
2066 2062
2067 2063 /* Then, read the HMAC */
2068 2064 if (readn_nointr(fd, obj_hmac, OBJ_HMAC_SIZE) != OBJ_HMAC_SIZE) {
2069 2065 goto cleanup;
2070 2066 }
2071 2067
2072 2068 /* read the object */
2073 2069 rv = read_obj_data(fd, (char **)&buf, &nread);
2074 2070 if (rv != CKR_OK) {
2075 2071 goto cleanup;
2076 2072 }
2077 2073
2078 2074 if (ks_handle->public) {
2079 2075 obj->size = nread;
↓ open down ↓ |
86 lines elided |
↑ open up ↑ |
2080 2076 obj->buf = buf;
2081 2077 *return_obj = obj;
2082 2078 } else {
2083 2079
2084 2080 CK_ULONG out_len = 0, hmac_size;
2085 2081
2086 2082 /* verify HMAC of the object, make sure it matches */
2087 2083 hmac_size = OBJ_HMAC_SIZE;
2088 2084 if (soft_keystore_hmac(hmac_key, B_FALSE, buf,
2089 2085 nread, obj_hmac, &hmac_size) != CKR_OK) {
2090 - free(buf);
2086 + freezero(buf, nread);
2091 2087 rv = CKR_FUNCTION_FAILED;
2092 2088 goto cleanup;
2093 2089 }
2094 2090
2095 2091 /* decrypt object */
2096 2092 if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread,
2097 2093 NULL, &out_len) != CKR_OK) {
2098 - free(buf);
2094 + freezero(buf, nread);
2099 2095 rv = CKR_FUNCTION_FAILED;
2100 2096 goto cleanup;
2101 2097 }
2102 2098
2103 2099 decrypted_buf = malloc(sizeof (uchar_t) * out_len);
2104 2100 if (decrypted_buf == NULL) {
2105 - free(buf);
2101 + freezero(buf, nread);
2106 2102 rv = CKR_HOST_MEMORY;
2107 2103 goto cleanup;
2108 2104 }
2109 2105
2110 2106 if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread,
2111 2107 decrypted_buf, &out_len) != CKR_OK) {
2112 - free(decrypted_buf);
2113 - free(buf);
2108 + freezero(buf, nread);
2109 + freezero(decrypted_buf, out_len);
2114 2110 rv = CKR_FUNCTION_FAILED;
2115 2111 goto cleanup;
2116 2112 }
2117 2113
2118 2114 obj->size = out_len - MAXPATHLEN;
2119 2115
2120 2116 /*
2121 2117 * decrypted buf here actually contains full path name of
2122 2118 * object plus the actual data. so, need to skip the
2123 2119 * full pathname.
2124 2120 * See prepare_data_for_encrypt() function in the file
2125 2121 * to understand how and why the pathname is added.
2126 2122 */
2127 2123 obj->buf = malloc(sizeof (uchar_t) * (out_len - MAXPATHLEN));
2128 2124 if (obj->buf == NULL) {
2129 - free(decrypted_buf);
2130 - free(buf);
2125 + freezero(buf, nread);
2126 + freezero(decrypted_buf, out_len);
2131 2127 rv = CKR_HOST_MEMORY;
2132 2128 goto cleanup;
2133 2129 }
2134 2130 (void) memcpy(obj->buf, decrypted_buf + MAXPATHLEN, obj->size);
2135 - free(decrypted_buf);
2136 - free(buf);
2131 + freezero(buf, nread);
2132 + freezero(decrypted_buf, out_len);
2137 2133 *return_obj = obj;
2138 2134 }
2139 2135
2140 2136 cleanup:
2141 2137
2142 2138 if (rv != CKR_OK) {
2143 2139 free(obj);
2144 2140 }
2145 2141
2146 2142 /* unlock the file after reading */
2147 2143 if (!lock_held) {
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
2148 2144 (void) lock_file(fd, B_TRUE, B_FALSE);
2149 2145 }
2150 2146
2151 2147 (void) close(fd);
2152 2148
2153 2149 return (rv);
2154 2150 }
2155 2151
2156 2152
2157 2153 /*
2158 - * FUNCTION: soft_keystore_put_new_obj
2154 + * FUNCTION: soft_keystore_put_new_obj
2159 2155 *
2160 2156 * ARGUMENTS:
2161 2157 * buf: buffer containing un-encrypted data
2162 2158 * to be stored in keystore.
2163 2159 * len: length of data
2164 2160 * public: TRUE if it is a public object,
2165 2161 * FALSE if it is private obj
2166 2162 * lock_held: TRUE if the lock is held by caller.
2167 2163 * keyhandle: pointer to object handle to
2168 2164 * receive keyhandle for new object
2169 2165 *
2170 2166 * RETURN VALUE:
2171 2167 * 0: object successfully stored in file
2172 2168 * -1: some error occurred, object is not stored in file.
2173 2169 *
2174 2170 * DESCRIPTION:
2175 2171 * This API is used to write a newly created token object
2176 2172 * to keystore.
2177 2173 *
2178 2174 * This function does the following:
2179 2175 *
2180 2176 * 1) Creates a token object file based on "public" parameter.
2181 2177 * 2) Generates a new IV and stores it in obj_meta_data_t if it is
2182 2178 * private object.
2183 2179 * 3) Set object version number to 1.
2184 2180 * 4) If it is a private object, it will be encrypted before
2185 2181 * being written to the newly created keystore token object
2186 2182 * file.
2187 2183 * 5) Calculates the obj_chksum in obj_meta_data_t.
2188 2184 * 6) Calculates the pin_chksum in obj_meta_data_t.
2189 2185 * 7) Increments the keystore version number.
2190 2186 */
2191 2187 int
2192 2188 soft_keystore_put_new_obj(uchar_t *buf, size_t len, boolean_t public,
2193 2189 boolean_t lock_held, ks_obj_handle_t *keyhandle)
2194 2190 {
2195 2191
2196 2192 int fd, tmp_ks_fd, obj_fd;
2197 2193 unsigned int counter, version;
2198 2194 uchar_t obj_hmac[OBJ_HMAC_SIZE];
2199 2195 CK_BYTE iv[OBJ_IV_SIZE];
2200 2196 char obj_name[MAXPATHLEN], tmp_ks_desc_name[MAXPATHLEN];
2201 2197 char filebuf[BUFSIZ];
2202 2198 char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN],
2203 2199 ks_desc_file[MAXPATHLEN];
2204 2200 CK_ULONG hmac_size;
2205 2201 ssize_t nread;
2206 2202
2207 2203 if (keyhandle == NULL) {
2208 2204 return (-1);
2209 2205 }
2210 2206
2211 2207 /* if it is private object, make sure we have the key */
2212 2208 if (!public) {
2213 2209 if ((enc_key == NULL) ||
2214 2210 (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
2215 2211 return (-1);
2216 2212 }
2217 2213 }
2218 2214
2219 2215 /* open keystore, and set write lock */
2220 2216 if ((fd = open_and_lock_keystore_desc(O_RDWR, B_FALSE,
2221 2217 lock_held)) < 0) {
2222 2218 return (-1);
2223 2219 }
2224 2220
2225 2221 (void) get_desc_file_path(ks_desc_file);
2226 2222 (void) get_tmp_desc_file_path(tmp_ks_desc_name);
2227 2223
2228 2224 /*
2229 2225 * create a tempoary file for the keystore description
2230 2226 * file for updating version and counter information
2231 2227 */
2232 2228 tmp_ks_fd = open_nointr(tmp_ks_desc_name,
2233 2229 O_RDWR|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
2234 2230 if (tmp_ks_fd < 0) {
2235 2231 (void) close(fd);
2236 2232 return (-1);
2237 2233 }
2238 2234
2239 2235 /* read and write pkcs11 version */
2240 2236 if (readn_nointr(fd, filebuf, KS_PKCS11_VER_SIZE)
2241 2237 != KS_PKCS11_VER_SIZE) {
2242 2238 goto cleanup;
2243 2239 }
2244 2240
2245 2241 if (writen_nointr(tmp_ks_fd, filebuf, KS_PKCS11_VER_SIZE)
2246 2242 != KS_PKCS11_VER_SIZE) {
2247 2243 goto cleanup;
2248 2244 }
2249 2245
2250 2246 /* get version number, and write updated number to temp file */
2251 2247 if (readn_nointr(fd, &version, KS_VER_SIZE) != KS_VER_SIZE) {
2252 2248 goto cleanup;
2253 2249 }
2254 2250
2255 2251 version = SWAP32(version);
2256 2252 version++;
2257 2253 version = SWAP32(version);
2258 2254
2259 2255 if (writen_nointr(tmp_ks_fd, (void *)&version,
2260 2256 KS_VER_SIZE) != KS_VER_SIZE) {
2261 2257 goto cleanup;
2262 2258 }
2263 2259
2264 2260 /* get object count value */
2265 2261 if (readn_nointr(fd, &counter, KS_COUNTER_SIZE) != KS_COUNTER_SIZE) {
2266 2262 goto cleanup;
2267 2263 }
2268 2264 counter = SWAP32(counter);
2269 2265
2270 2266 bzero(obj_name, sizeof (obj_name));
2271 2267 if (public) {
2272 2268 (void) snprintf(obj_name, MAXPATHLEN, "%s/%s%d",
2273 2269 get_pub_obj_path(pub_obj_path), OBJ_PREFIX, counter);
2274 2270 } else {
2275 2271 (void) snprintf(obj_name, MAXPATHLEN, "%s/%s%d",
2276 2272 get_pri_obj_path(pri_obj_path), OBJ_PREFIX, counter);
2277 2273 }
2278 2274
2279 2275 /* create object file */
2280 2276 obj_fd = open_nointr(obj_name,
2281 2277 O_WRONLY|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
2282 2278 if (obj_fd < 0) {
2283 2279 /* can't create object file */
2284 2280 goto cleanup;
2285 2281 }
2286 2282
2287 2283 /* lock object file for writing */
2288 2284 if (lock_file(obj_fd, B_FALSE, B_TRUE) != 0) {
2289 2285 (void) close(obj_fd);
2290 2286 goto cleanup2;
2291 2287 }
2292 2288
2293 2289 /* write object meta data */
2294 2290 version = SWAP32(1);
2295 2291 if (writen_nointr(obj_fd, (void *)&version, sizeof (version))
2296 2292 != sizeof (version)) {
2297 2293 goto cleanup2;
2298 2294 }
2299 2295
2300 2296 if (public) {
2301 2297 bzero(iv, sizeof (iv));
2302 2298 } else {
2303 2299 /* generate an IV */
2304 2300 if (soft_gen_iv(iv) != CKR_OK) {
2305 2301 goto cleanup2;
2306 2302 }
2307 2303
2308 2304 }
2309 2305
2310 2306 if (writen_nointr(obj_fd, (void *)iv, sizeof (iv)) != sizeof (iv)) {
2311 2307 goto cleanup2;
2312 2308 }
2313 2309
2314 2310 if (public) {
2315 2311
2316 2312 bzero(obj_hmac, sizeof (obj_hmac));
2317 2313 if (writen_nointr(obj_fd, (void *)obj_hmac,
2318 2314 sizeof (obj_hmac)) != sizeof (obj_hmac)) {
2319 2315 goto cleanup2;
2320 2316 }
2321 2317
2322 2318 if (writen_nointr(obj_fd, (char *)buf, len) != len) {
2323 2319 goto cleanup2;
2324 2320 }
2325 2321
2326 2322 } else {
2327 2323
2328 2324 uchar_t *encrypted_buf, *prepared_buf;
↓ open down ↓ |
160 lines elided |
↑ open up ↑ |
2329 2325 CK_ULONG out_len = 0, prepared_len;
2330 2326
2331 2327 if (prepare_data_for_encrypt(obj_name, buf, len,
2332 2328 &prepared_buf, &prepared_len) != 0) {
2333 2329 goto cleanup2;
2334 2330 }
2335 2331
2336 2332 if (soft_keystore_crypt(enc_key, iv,
2337 2333 B_TRUE, prepared_buf, prepared_len,
2338 2334 NULL, &out_len) != CKR_OK) {
2339 - free(prepared_buf);
2335 + freezero(prepared_buf, prepared_len);
2340 2336 goto cleanup2;
2341 2337 }
2342 2338
2343 2339 encrypted_buf = malloc(out_len * sizeof (char));
2344 2340 if (encrypted_buf == NULL) {
2345 - free(prepared_buf);
2341 + freezero(prepared_buf, prepared_len);
2346 2342 goto cleanup2;
2347 2343 }
2348 2344
2349 2345 if (soft_keystore_crypt(enc_key, iv,
2350 2346 B_TRUE, prepared_buf, prepared_len,
2351 2347 encrypted_buf, &out_len) != CKR_OK) {
2352 - free(encrypted_buf);
2353 - free(prepared_buf);
2348 + freezero(encrypted_buf, out_len);
2349 + freezero(prepared_buf, prepared_len);
2354 2350 goto cleanup2;
2355 2351 }
2356 - free(prepared_buf);
2352 + freezero(prepared_buf, prepared_len);
2357 2353
2358 2354 /* calculate HMAC of encrypted object */
2359 2355 hmac_size = OBJ_HMAC_SIZE;
2360 2356 if (soft_keystore_hmac(hmac_key, B_TRUE, encrypted_buf,
2361 2357 out_len, obj_hmac, &hmac_size) != CKR_OK) {
2362 - free(encrypted_buf);
2358 + freezero(encrypted_buf, out_len);
2363 2359 goto cleanup2;
2364 2360 }
2365 2361
2366 2362 if (hmac_size != OBJ_HMAC_SIZE) {
2367 - free(encrypted_buf);
2363 + freezero(encrypted_buf, out_len);
2368 2364 goto cleanup2;
2369 2365 }
2370 2366
2371 2367 /* write hmac */
2372 2368 if (writen_nointr(obj_fd, (void *)obj_hmac,
2373 2369 sizeof (obj_hmac)) != sizeof (obj_hmac)) {
2374 - free(encrypted_buf);
2370 + freezero(encrypted_buf, out_len);
2375 2371 goto cleanup2;
2376 2372 }
2377 2373
2378 2374 /* write encrypted object */
2379 2375 if (writen_nointr(obj_fd, (void *)encrypted_buf, out_len)
2380 2376 != out_len) {
2381 - free(encrypted_buf);
2377 + freezero(encrypted_buf, out_len);
2382 2378 goto cleanup2;
2383 2379 }
2384 2380
2385 - free(encrypted_buf);
2381 + freezero(encrypted_buf, out_len);
2386 2382 }
2387 2383
2388 2384
2389 2385 (void) close(obj_fd);
2390 2386 (void) snprintf((char *)keyhandle->name, sizeof (keyhandle->name),
2391 2387 "obj%d", counter);
2392 2388 keyhandle->public = public;
2393 2389
2394 2390 /*
2395 2391 * store new counter to temp keystore description file.
2396 2392 */
2397 2393 counter++;
2398 2394 counter = SWAP32(counter);
2399 2395 if (writen_nointr(tmp_ks_fd, (void *)&counter,
2400 2396 sizeof (counter)) != sizeof (counter)) {
2401 2397 goto cleanup2;
2402 2398 }
2403 2399
2404 2400 /* read rest of keystore description file and store into temp file */
2405 2401 nread = readn_nointr(fd, filebuf, sizeof (filebuf));
2406 2402 while (nread > 0) {
2407 2403 if (writen_nointr(tmp_ks_fd, filebuf, nread) != nread) {
2408 2404 goto cleanup2;
2409 2405 }
2410 2406 nread = readn_nointr(fd, filebuf, sizeof (filebuf));
2411 2407 }
2412 2408
2413 2409 (void) close(tmp_ks_fd);
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
2414 2410 (void) rename(tmp_ks_desc_name, ks_desc_file);
2415 2411
2416 2412 if (!lock_held) {
2417 2413 /* release lock on description file */
2418 2414 if (lock_file(fd, B_FALSE, B_FALSE) != 0) {
2419 2415 (void) close(fd);
2420 2416 return (-1);
2421 2417 }
2422 2418 }
2423 2419 (void) close(fd);
2420 + explicit_bzero(obj_hmac, sizeof (obj_hmac));
2421 + explicit_bzero(iv, sizeof (iv));
2424 2422 return (0);
2425 2423
2426 2424 cleanup2:
2427 2425
2428 2426 /* remove object file. No need to remove lock first */
2429 2427 (void) unlink(obj_name);
2430 2428
2431 2429 cleanup:
2432 2430
2433 2431 (void) close(tmp_ks_fd);
2434 2432 (void) remove(tmp_ks_desc_name);
2435 2433 if (!lock_held) {
2436 2434 /* release lock on description file */
2437 2435 (void) lock_file(fd, B_FALSE, B_FALSE);
2438 2436 }
2439 2437
2440 2438 (void) close(fd);
2439 + explicit_bzero(obj_hmac, sizeof (obj_hmac));
2440 + explicit_bzero(iv, sizeof (iv));
2441 2441 return (-1);
2442 2442 }
2443 2443
2444 2444 /*
2445 2445 * FUNCTION: soft_keystore_modify_obj
2446 2446 *
2447 2447 * ARGUMENTS:
2448 2448 * ks_handle: handle of the key store object to be modified
2449 2449 * buf: buffer containing un-encrypted data
2450 2450 * to be modified in keystore.
2451 2451 * len: length of data
2452 2452 * lock_held: TRUE if the lock is held by caller.
2453 2453 *
2454 2454 * RETURN VALUE:
2455 2455 * -1: if any error occurred.
2456 2456 * Otherwise, 0 is returned.
2457 2457 *
2458 2458 * DESCRIPTION:
2459 2459 *
2460 2460 * This API is used to write a modified token object back
2461 2461 * to keystore. This function will do the following:
2462 2462 *
2463 2463 * 1) If it is a private object, it will be encrypted before
2464 2464 * being written to the corresponding keystore token
2465 2465 * object file.
2466 2466 * 2) Record incremented object version number.
2467 2467 * 3) Record incremented keystore version number.
2468 2468 */
2469 2469 int
2470 2470 soft_keystore_modify_obj(ks_obj_handle_t *ks_handle, uchar_t *buf,
2471 2471 size_t len, boolean_t lock_held)
2472 2472 {
2473 2473 int fd, ks_fd, tmp_fd, version;
2474 2474 char orig_name[MAXPATHLEN], tmp_name[MAXPATHLEN],
2475 2475 tmp_ks_name[MAXPATHLEN];
2476 2476 uchar_t iv[OBJ_IV_SIZE], obj_hmac[OBJ_HMAC_SIZE];
2477 2477 char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN],
2478 2478 ks_desc_file[MAXPATHLEN];
2479 2479 CK_ULONG hmac_size;
2480 2480
2481 2481 /* if it is private object, make sure we have the key */
2482 2482 if (!(ks_handle->public)) {
2483 2483 if ((enc_key == NULL) ||
2484 2484 (enc_key->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
2485 2485 return (-1);
2486 2486 }
2487 2487 }
2488 2488
2489 2489 /* open and lock keystore description file */
2490 2490 if ((ks_fd = open_and_lock_keystore_desc(O_RDWR, B_FALSE,
2491 2491 B_FALSE)) < 0) {
2492 2492 return (-1);
2493 2493 }
2494 2494
2495 2495 (void) get_desc_file_path(ks_desc_file);
2496 2496
2497 2497 /* update the version of for keystore file in tempoary file */
2498 2498 (void) get_tmp_desc_file_path(tmp_ks_name);
2499 2499 if (create_updated_keystore_version(ks_fd, tmp_ks_name) != 0) {
2500 2500 /* unlock keystore description file */
2501 2501 (void) lock_file(ks_fd, B_FALSE, B_FALSE);
2502 2502 (void) close(ks_fd);
2503 2503 return (-1);
2504 2504 }
2505 2505
2506 2506 /* open object file */
2507 2507 if ((fd = open_and_lock_object_file(ks_handle, O_RDWR,
2508 2508 lock_held)) < 0) {
2509 2509 goto cleanup;
2510 2510 }
2511 2511
2512 2512 /*
2513 2513 * make the change in a temporary file. Create the temp
2514 2514 * file in the same directory as the token object. That
2515 2515 * way, the "rename" later will be an atomic operation
2516 2516 */
2517 2517 if (ks_handle->public) {
2518 2518 (void) snprintf(orig_name, MAXPATHLEN, "%s/%s",
2519 2519 get_pub_obj_path(pub_obj_path), ks_handle->name);
2520 2520 (void) snprintf(tmp_name, MAXPATHLEN, "%s/%s%s",
2521 2521 pub_obj_path, TMP_OBJ_PREFIX,
2522 2522 (ks_handle->name) + OBJ_PREFIX_LEN);
2523 2523 } else {
2524 2524 (void) snprintf(orig_name, MAXPATHLEN, "%s/%s",
2525 2525 get_pri_obj_path(pri_obj_path), ks_handle->name);
2526 2526 (void) snprintf(tmp_name, MAXPATHLEN, "%s/%s%s",
2527 2527 pri_obj_path, TMP_OBJ_PREFIX,
2528 2528 (ks_handle->name) + OBJ_PREFIX_LEN);
2529 2529 }
2530 2530
2531 2531 tmp_fd = open_nointr(tmp_name,
2532 2532 O_WRONLY|O_CREAT|O_EXCL|O_NONBLOCK, S_IRUSR|S_IWUSR);
2533 2533 if (tmp_fd < 0) {
2534 2534 /* can't create tmp object file */
2535 2535 goto cleanup1;
2536 2536 }
2537 2537
2538 2538 /* read version, increment, and write to tmp file */
2539 2539 if (readn_nointr(fd, (char *)&version, OBJ_VER_SIZE) != OBJ_VER_SIZE) {
2540 2540 goto cleanup2;
2541 2541 }
2542 2542
2543 2543 version = SWAP32(version);
2544 2544 version++;
2545 2545 version = SWAP32(version);
2546 2546
2547 2547 if (writen_nointr(tmp_fd, (char *)&version, OBJ_VER_SIZE)
2548 2548 != OBJ_VER_SIZE) {
2549 2549 goto cleanup2;
2550 2550 }
2551 2551
2552 2552 /* generate a new IV for the object, old one can be ignored */
2553 2553 if (soft_gen_iv(iv) != CKR_OK) {
2554 2554 goto cleanup2;
2555 2555 }
2556 2556
2557 2557 if (writen_nointr(tmp_fd, (char *)iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) {
2558 2558 goto cleanup2;
2559 2559 }
2560 2560
2561 2561 if (ks_handle->public) {
2562 2562
2563 2563 /* hmac is always NULL for public objects */
2564 2564 bzero(obj_hmac, sizeof (obj_hmac));
2565 2565 if (writen_nointr(tmp_fd, (char *)obj_hmac, OBJ_HMAC_SIZE)
2566 2566 != OBJ_HMAC_SIZE) {
2567 2567 goto cleanup2;
2568 2568 }
2569 2569
2570 2570 /* write updated object */
2571 2571 if (writen_nointr(tmp_fd, (char *)buf, len) != len) {
2572 2572 goto cleanup2;
2573 2573 }
2574 2574
2575 2575 } else {
2576 2576
2577 2577 uchar_t *encrypted_buf, *prepared_buf;
2578 2578 CK_ULONG out_len = 0, prepared_len;
2579 2579
2580 2580 if (prepare_data_for_encrypt(orig_name, buf, len,
2581 2581 &prepared_buf, &prepared_len) != 0) {
2582 2582 goto cleanup2;
2583 2583 }
↓ open down ↓ |
133 lines elided |
↑ open up ↑ |
2584 2584
2585 2585 /* encrypt the data */
2586 2586 if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf,
2587 2587 prepared_len, NULL, &out_len) != CKR_OK) {
2588 2588 free(prepared_buf);
2589 2589 goto cleanup2;
2590 2590 }
2591 2591
2592 2592 encrypted_buf = malloc(out_len * sizeof (char));
2593 2593 if (encrypted_buf == NULL) {
2594 - free(prepared_buf);
2594 + freezero(prepared_buf, prepared_len);
2595 2595 goto cleanup2;
2596 2596 }
2597 2597
2598 2598 if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf,
2599 2599 prepared_len, encrypted_buf, &out_len) != CKR_OK) {
2600 - free(encrypted_buf);
2601 - free(prepared_buf);
2600 + freezero(prepared_buf, prepared_len);
2601 + freezero(encrypted_buf, out_len);
2602 2602 goto cleanup2;
2603 2603 }
2604 2604
2605 - free(prepared_buf);
2605 + freezero(prepared_buf, prepared_len);
2606 2606
2607 2607 /* calculate hmac on encrypted buf */
2608 2608 hmac_size = OBJ_HMAC_SIZE;
2609 2609 if (soft_keystore_hmac(hmac_key, B_TRUE, encrypted_buf,
2610 2610 out_len, obj_hmac, &hmac_size) != CKR_OK) {
2611 - free(encrypted_buf);
2611 + freezero(encrypted_buf, out_len);
2612 2612 goto cleanup2;
2613 2613 }
2614 2614
2615 2615 if (hmac_size != OBJ_HMAC_SIZE) {
2616 - free(encrypted_buf);
2616 + freezero(encrypted_buf, out_len);
2617 2617 goto cleanup2;
2618 2618 }
2619 2619
2620 2620 if (writen_nointr(tmp_fd, (char *)obj_hmac, OBJ_HMAC_SIZE)
2621 2621 != OBJ_HMAC_SIZE) {
2622 - free(encrypted_buf);
2622 + freezero(encrypted_buf, out_len);
2623 2623 goto cleanup2;
2624 2624 }
2625 2625
2626 2626 if (writen_nointr(tmp_fd, (void *)encrypted_buf, out_len)
2627 2627 != out_len) {
2628 - free(encrypted_buf);
2628 + freezero(encrypted_buf, out_len);
2629 2629 goto cleanup2;
2630 2630 }
2631 - free(encrypted_buf);
2631 + freezero(encrypted_buf, out_len);
2632 2632 }
2633 2633 (void) close(tmp_fd);
2634 2634
2635 2635 /* rename updated temporary object file */
2636 2636 if (rename(tmp_name, orig_name) != 0) {
2637 2637 (void) unlink(tmp_name);
2638 2638 return (-1);
2639 2639 }
2640 2640
2641 2641 /* rename updated keystore description file */
2642 2642 if (rename(tmp_ks_name, ks_desc_file) != 0) {
2643 2643 (void) unlink(tmp_name);
2644 2644 (void) unlink(tmp_ks_name);
2645 2645 return (-1);
2646 2646 }
2647 2647
2648 2648 /* determine need to unlock file or not */
2649 2649 if (!lock_held) {
2650 2650 if (lock_file(fd, B_FALSE, B_FALSE) < 0) {
2651 2651 (void) close(fd);
2652 2652 (void) unlink(tmp_name);
2653 2653 return (-1);
2654 2654 }
2655 2655 }
2656 2656
2657 2657 /* unlock keystore description file */
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
2658 2658 if (lock_file(ks_fd, B_FALSE, B_FALSE) != 0) {
2659 2659 (void) close(ks_fd);
2660 2660 (void) close(fd);
2661 2661 return (-1);
2662 2662 }
2663 2663
2664 2664 (void) close(ks_fd);
2665 2665
2666 2666 (void) close(fd);
2667 2667
2668 + explicit_bzero(iv, sizeof (iv));
2669 + explicit_bzero(obj_hmac, sizeof (obj_hmac));
2668 2670 return (0); /* All operations completed successfully */
2669 2671
2670 2672 cleanup2:
2671 2673 (void) close(tmp_fd);
2672 2674 (void) remove(tmp_name);
2673 2675
2674 2676 cleanup1:
2675 2677 (void) close(fd);
2676 2678
2677 2679 cleanup:
2678 2680 /* unlock keystore description file */
2679 2681 (void) lock_file(ks_fd, B_FALSE, B_FALSE);
2680 2682 (void) close(ks_fd);
2681 2683 (void) remove(tmp_ks_name);
2684 + explicit_bzero(iv, sizeof (iv));
2685 + explicit_bzero(obj_hmac, sizeof (obj_hmac));
2682 2686 return (-1);
2683 2687 }
2684 2688
2685 2689 /*
2686 2690 * FUNCTION: soft_keystore_del_obj
2687 2691 *
2688 2692 * ARGUMENTS:
2689 2693 * ks_handle: handle of the key store object to be deleted
2690 2694 * lock_held: TRUE if the lock is held by caller.
2691 2695 *
2692 2696 * RETURN VALUE:
2693 2697 * -1: if any error occurred.
2694 2698 * 0: object successfully deleted from keystore.
2695 2699 *
2696 2700 * DESCRIPTION:
2697 2701 * This API is used to delete a particular token object from
2698 2702 * the keystore. The corresponding token object file will be
2699 2703 * removed from the file system.
2700 2704 * Any future reference to the deleted file will
2701 2705 * return an CKR_OBJECT_HANDLE_INVALID error.
2702 2706 */
2703 2707 int
2704 2708 soft_keystore_del_obj(ks_obj_handle_t *ks_handle, boolean_t lock_held)
2705 2709 {
2706 2710 char objname[MAXPATHLEN], tmp_ks_name[MAXPATHLEN];
2707 2711 int fd;
2708 2712 char pub_obj_path[MAXPATHLEN], pri_obj_path[MAXPATHLEN],
2709 2713 ks_desc_file[MAXPATHLEN];
2710 2714 int ret_val = -1;
2711 2715 int obj_fd;
2712 2716
2713 2717 if ((fd = open_and_lock_keystore_desc(O_RDWR, B_FALSE,
2714 2718 lock_held)) < 0) {
2715 2719 return (-1);
2716 2720 }
2717 2721
2718 2722 (void) get_desc_file_path(ks_desc_file);
2719 2723 (void) get_tmp_desc_file_path(tmp_ks_name);
2720 2724 if (create_updated_keystore_version(fd, tmp_ks_name) != 0) {
2721 2725 goto cleanup;
2722 2726 }
2723 2727
2724 2728 if (ks_handle->public) {
2725 2729 (void) snprintf(objname, MAXPATHLEN, "%s/%s",
2726 2730 get_pub_obj_path(pub_obj_path), ks_handle->name);
2727 2731 } else {
2728 2732 (void) snprintf(objname, MAXPATHLEN, "%s/%s",
2729 2733 get_pri_obj_path(pri_obj_path), ks_handle->name);
2730 2734 }
2731 2735
2732 2736 /*
2733 2737 * make sure no other process is reading/writing the file
2734 2738 * by acquiring the lock on the file
2735 2739 */
2736 2740 if ((obj_fd = open_and_lock_object_file(ks_handle, O_WRONLY,
2737 2741 B_FALSE)) < 0) {
2738 2742 return (-1);
2739 2743 }
2740 2744
2741 2745 if (unlink(objname) != 0) {
2742 2746 (void) lock_file(obj_fd, B_FALSE, B_FALSE);
2743 2747 (void) close(obj_fd);
2744 2748 goto cleanup;
2745 2749 }
2746 2750
2747 2751 (void) lock_file(obj_fd, B_FALSE, B_FALSE);
2748 2752 (void) close(obj_fd);
2749 2753
2750 2754 if (rename(tmp_ks_name, ks_desc_file) != 0) {
2751 2755 goto cleanup;
2752 2756 }
2753 2757 ret_val = 0;
2754 2758
2755 2759 cleanup:
2756 2760 /* unlock keystore description file */
2757 2761 if (!lock_held) {
2758 2762 if (lock_file(fd, B_FALSE, B_FALSE) != 0) {
2759 2763 (void) close(fd);
2760 2764 return (-1);
2761 2765 }
2762 2766 }
2763 2767
2764 2768 (void) close(fd);
2765 2769 return (ret_val);
2766 2770 }
2767 2771
2768 2772 /*
2769 2773 * Get the salt used for generating hashed pin from the
2770 2774 * keystore description file.
2771 2775 *
2772 2776 * The result will be stored in the provided buffer "salt" passed
2773 2777 * in as an argument.
2774 2778 *
2775 2779 * Return 0 if no error, return -1 if there's any error.
2776 2780 */
2777 2781 int
2778 2782 soft_keystore_get_pin_salt(char **salt)
2779 2783 {
2780 2784 int fd, ret_val = -1;
2781 2785 uint64_t hashed_pin_salt_size;
2782 2786
2783 2787 if ((fd = open_and_lock_keystore_desc(O_RDONLY, B_FALSE,
2784 2788 B_FALSE)) < 0) {
2785 2789 return (-1);
2786 2790 }
2787 2791
2788 2792 if (lseek(fd, KS_HASHED_PIN_SALT_LEN_OFFSET, SEEK_SET)
2789 2793 != KS_HASHED_PIN_SALT_LEN_OFFSET) {
2790 2794 goto cleanup;
2791 2795 }
2792 2796
2793 2797 if (readn_nointr(fd, (char *)&hashed_pin_salt_size,
2794 2798 KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
2795 2799 goto cleanup;
↓ open down ↓ |
104 lines elided |
↑ open up ↑ |
2796 2800 }
2797 2801 hashed_pin_salt_size = SWAP64(hashed_pin_salt_size);
2798 2802
2799 2803 *salt = malloc(hashed_pin_salt_size + 1);
2800 2804 if (*salt == NULL) {
2801 2805 goto cleanup;
2802 2806 }
2803 2807
2804 2808 if ((readn_nointr(fd, *salt, hashed_pin_salt_size))
2805 2809 != (ssize_t)hashed_pin_salt_size) {
2806 - free(*salt);
2810 + freezero(*salt, hashed_pin_salt_size + 1);
2807 2811 goto cleanup;
2808 2812 }
2809 2813 (*salt)[hashed_pin_salt_size] = '\0';
2810 2814
2811 2815 ret_val = 0;
2812 2816
2813 2817 cleanup:
2814 2818 if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
2815 2819 ret_val = -1;
2816 2820 }
2817 2821
2818 2822 (void) close(fd);
2819 2823 return (ret_val);
2820 2824 }
2821 2825
2822 2826 /*
2823 2827 * FUNCTION: soft_keystore_pin_initialized
2824 2828 *
2825 2829 * ARGUMENTS:
2826 2830 * initialized: This value will be set to true if keystore is
2827 2831 * initialized, and false otherwise.
2828 2832 * hashed_pin: If the keystore is initialized, this will contain
2829 2833 * the hashed pin. It will be NULL if the keystore
2830 2834 * pin is not initialized. Memory allocated
2831 2835 * for the hashed pin needs to be freed by
2832 2836 * the caller.
2833 2837 * lock_held: TRUE if the lock is held by caller.
2834 2838 *
2835 2839 * RETURN VALUE:
2836 2840 * CKR_OK: No error
2837 2841 * any other appropriate CKR_value
2838 2842 *
2839 2843 * DESCRIPTION:
2840 2844 * This API is used to determine if the PIN in the keystore
2841 2845 * has been initialized or not.
2842 2846 * It makes the determination using the salt for generating the
2843 2847 * encryption key. The salt is stored in the keystore
2844 2848 * descryption file. The salt should be all zero if
2845 2849 * the keystore pin has not been initialized.
2846 2850 * If the pin has been initialized, it is returned in the
2847 2851 * hashed_pin argument.
2848 2852 */
2849 2853 CK_RV
2850 2854 soft_keystore_pin_initialized(boolean_t *initialized, char **hashed_pin,
2851 2855 boolean_t lock_held)
2852 2856 {
2853 2857 int fd;
2854 2858 CK_BYTE crypt_salt[KS_KEY_SALT_SIZE], tmp_buf[KS_KEY_SALT_SIZE];
2855 2859 CK_RV ret_val = CKR_OK;
2856 2860
2857 2861 if ((fd = open_and_lock_keystore_desc(O_RDONLY, B_FALSE,
2858 2862 lock_held)) < 0) {
2859 2863 return (CKR_FUNCTION_FAILED);
2860 2864 }
2861 2865
2862 2866 if (lseek(fd, KS_KEY_SALT_OFFSET, SEEK_SET) != KS_KEY_SALT_OFFSET) {
2863 2867 ret_val = CKR_FUNCTION_FAILED;
2864 2868 goto cleanup;
2865 2869 }
2866 2870
2867 2871 if (readn_nointr(fd, (char *)crypt_salt, KS_KEY_SALT_SIZE)
2868 2872 != KS_KEY_SALT_SIZE) {
2869 2873 ret_val = CKR_FUNCTION_FAILED;
2870 2874 goto cleanup;
2871 2875 }
2872 2876
2873 2877 (void) bzero(tmp_buf, KS_KEY_SALT_SIZE);
2874 2878
2875 2879 if (memcmp(crypt_salt, tmp_buf, KS_KEY_SALT_SIZE) == 0) {
2876 2880 *initialized = B_FALSE;
2877 2881 hashed_pin = NULL;
2878 2882 } else {
2879 2883 *initialized = B_TRUE;
2880 2884 ret_val = get_hashed_pin(fd, hashed_pin);
2881 2885 }
2882 2886
2883 2887 cleanup:
2884 2888
2885 2889 if (!lock_held) {
2886 2890 if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
2887 2891 ret_val = CKR_FUNCTION_FAILED;
2888 2892 }
2889 2893 }
2890 2894
2891 2895 (void) close(fd);
2892 2896 return (ret_val);
2893 2897 }
2894 2898
2895 2899 /*
2896 2900 * This checks if the keystore file exists
2897 2901 */
2898 2902
2899 2903 static int
2900 2904 soft_keystore_exists()
2901 2905 {
2902 2906 int ret;
2903 2907 struct stat fn_stat;
2904 2908 char *fname, ks_desc_file[MAXPATHLEN];
2905 2909
2906 2910 fname = get_desc_file_path(ks_desc_file);
2907 2911 ret = stat(fname, &fn_stat);
2908 2912 if (ret == 0)
2909 2913 return (0);
2910 2914 return (errno);
2911 2915 }
2912 2916
2913 2917 /*
2914 2918 * FUNCTION: soft_keystore_init
2915 2919 *
2916 2920 * ARGUMENTS:
2917 2921 * desired_state: The keystore state the caller would like
2918 2922 * it to be.
2919 2923 *
2920 2924 * RETURN VALUE:
2921 2925 * Returns the state the function is in. If it succeeded, it
2922 2926 * will be the same as the desired, if not it will be
2923 2927 * KEYSTORE_UNAVAILABLE.
2924 2928 *
2925 2929 * DESCRIPTION:
2926 2930 * This function will only load as much keystore data as is
2927 2931 * requested at that time. This is for performace by delaying the
2928 2932 * reading of token objects until they are needed or never at
2929 2933 * all if they are not used.
2930 2934 *
2931 2935 * Primary use is from C_InitToken().
2932 2936 * It is also called by soft_keystore_status() when the
2933 2937 * "desired_state" is not the the current load state of keystore.
2934 2938 *
2935 2939 */
2936 2940 int
2937 2941 soft_keystore_init(int desired_state)
2938 2942 {
2939 2943 int ret;
2940 2944
2941 2945 (void) pthread_mutex_lock(&soft_slot.keystore_mutex);
2942 2946
2943 2947 /*
2944 2948 * If more than one session tries to initialize the keystore, the
2945 2949 * second and other following sessions that were waiting for the lock
2946 2950 * will quickly exit if their requirements are satisfied.
2947 2951 */
2948 2952 if (desired_state <= soft_slot.keystore_load_status) {
2949 2953 (void) pthread_mutex_unlock(&soft_slot.keystore_mutex);
2950 2954 return (soft_slot.keystore_load_status);
2951 2955 }
2952 2956
2953 2957 /*
2954 2958 * With 'keystore_load_status' giving the current state of the
2955 2959 * process, this switch will bring it up to the desired state if
2956 2960 * possible.
2957 2961 */
2958 2962
2959 2963 switch (soft_slot.keystore_load_status) {
2960 2964 case KEYSTORE_UNINITIALIZED:
2961 2965 ret = soft_keystore_exists();
2962 2966 if (ret == 0)
2963 2967 soft_slot.keystore_load_status = KEYSTORE_PRESENT;
2964 2968 else if (ret == ENOENT)
2965 2969 if (create_keystore() == 0)
2966 2970 soft_slot.keystore_load_status =
2967 2971 KEYSTORE_PRESENT;
2968 2972 else {
2969 2973 soft_slot.keystore_load_status =
2970 2974 KEYSTORE_UNAVAILABLE;
2971 2975 cryptoerror(LOG_DEBUG,
2972 2976 "pkcs11_softtoken: "
2973 2977 "Cannot create keystore.");
2974 2978 break;
2975 2979 }
2976 2980
2977 2981 if (desired_state <= KEYSTORE_PRESENT)
2978 2982 break;
2979 2983
2980 2984 /* FALLTHRU */
2981 2985 case KEYSTORE_PRESENT:
2982 2986 if (soft_keystore_get_version(&soft_slot.ks_version, B_FALSE)
2983 2987 != 0) {
2984 2988 soft_slot.keystore_load_status = KEYSTORE_UNAVAILABLE;
2985 2989 cryptoerror(LOG_DEBUG,
2986 2990 "pkcs11_softtoken: Keystore access failed.");
2987 2991 break;
2988 2992 }
2989 2993
2990 2994 soft_slot.keystore_load_status = KEYSTORE_LOAD;
2991 2995 if (desired_state <= KEYSTORE_LOAD)
2992 2996 break;
2993 2997
2994 2998 /* FALLTHRU */
2995 2999 case KEYSTORE_LOAD:
2996 3000 /* Load all the public token objects from keystore */
2997 3001 if (soft_get_token_objects_from_keystore(PUB_TOKENOBJS)
2998 3002 != CKR_OK) {
2999 3003 (void) soft_destroy_token_session();
3000 3004 soft_slot.keystore_load_status = KEYSTORE_UNAVAILABLE;
3001 3005 cryptoerror(LOG_DEBUG,
3002 3006 "pkcs11_softtoken: Cannot initialize keystore.");
3003 3007 break;
3004 3008 }
3005 3009
3006 3010 soft_slot.keystore_load_status = KEYSTORE_INITIALIZED;
3007 3011 };
3008 3012
3009 3013 (void) pthread_mutex_unlock(&soft_slot.keystore_mutex);
3010 3014 return (soft_slot.keystore_load_status);
3011 3015 }
3012 3016
3013 3017 /*
3014 3018 * FUNCTION: soft_keystore_status
3015 3019 *
3016 3020 * ARGUMENTS:
3017 3021 * desired_state: The keystore state the caller would like
3018 3022 * it to be.
3019 3023 *
3020 3024 * RETURN VALUE:
3021 3025 * B_TRUE if keystore is ready and at the desired state.
3022 3026 * B_FALSE if keystore had an error and is not available.
3023 3027 *
3024 3028 * DESCRIPTION:
3025 3029 * The calling function wants to make sure the keystore load
3026 3030 * status to in a state it requires. If it is not at that
3027 3031 * state it will call the load function.
3028 3032 * If keystore is at the desired state or has just been
3029 3033 * loaded to that state, it will return TRUE. If there has been
3030 3034 * load failure, it will return FALSE.
3031 3035 *
3032 3036 */
3033 3037 boolean_t
3034 3038 soft_keystore_status(int desired_state)
3035 3039 {
3036 3040
3037 3041 if (soft_slot.keystore_load_status == KEYSTORE_UNAVAILABLE)
3038 3042 return (B_FALSE);
3039 3043
3040 3044 return ((desired_state <= soft_slot.keystore_load_status) ||
3041 3045 (soft_keystore_init(desired_state) == desired_state));
3042 3046 }
↓ open down ↓ |
226 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX