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>


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.

  23  */
  24 
  25 /*
  26  * Functions used for manipulating the keystore
  27  */
  28 
  29 #include <stdio.h>
  30 #include <stdlib.h>
  31 #include <errno.h>
  32 #include <sys/stat.h>
  33 #include <fcntl.h>
  34 #include <time.h>
  35 #include <unistd.h>
  36 #include <pwd.h>
  37 #include <sys/types.h>
  38 #include <dirent.h>
  39 #include <limits.h>
  40 #include <libgen.h>
  41 #include <strings.h>
  42 #include <security/cryptoki.h>


 453         if (writen_nointr(fd, (void *)hashed_pin_salt,
 454             hashed_pin_salt_len) != hashed_pin_salt_len) {
 455                 goto cleanup;
 456         }
 457 
 458         /* write MD5 hashed pin of the default pin */
 459         ulong_buf = SWAP64(hashed_pin_len);
 460         if (writen_nointr(fd, (void *)&ulong_buf, KS_HASHED_PINLEN_SIZE)
 461             != KS_HASHED_PINLEN_SIZE) {
 462                 goto cleanup;
 463         }
 464 
 465         if (writen_nointr(fd, (void *)hashed_pin, hashed_pin_len)
 466             != hashed_pin_len) {
 467                 goto cleanup;
 468         }
 469 
 470         (void) lock_file(fd, B_FALSE, B_FALSE);
 471 
 472         (void) close(fd);
 473         if (hashed_pin_salt)
 474                 free(hashed_pin_salt);
 475         return (0);
 476 
 477 cleanup:
 478         (void) lock_file(fd, B_FALSE, B_FALSE);
 479         (void) unlink(ks_desc_file);
 480         (void) close(fd);
 481         (void) rmdir(get_keystore_path());
 482         (void) rmdir(pub_obj_path);
 483         (void) rmdir(pri_obj_path);
 484         return (-1);
 485 }
 486 
 487 /*
 488  * Determines if the file referenced by "fd" has the same
 489  * inode as the file referenced by "fname".
 490  *
 491  * The argument "same" contains the result of determining
 492  * if the inode is the same or not
 493  *
 494  * Returns 0 if there's no error.


 875         /* first, get size of the hashed pin */
 876         if (lseek(fd, ks_hashed_pinlen_offset, SEEK_SET)
 877             != ks_hashed_pinlen_offset) {
 878                 return (CKR_FUNCTION_FAILED);
 879         }
 880 
 881         if (readn_nointr(fd, (char *)&hashed_pin_size,
 882             KS_HASHED_PINLEN_SIZE) != KS_HASHED_PINLEN_SIZE) {
 883                 return (CKR_FUNCTION_FAILED);
 884         }
 885 
 886         hashed_pin_size = SWAP64(hashed_pin_size);
 887 
 888         *hashed_pin = malloc(hashed_pin_size + 1);
 889         if (*hashed_pin == NULL) {
 890                 return (CKR_HOST_MEMORY);
 891         }
 892 
 893         if ((readn_nointr(fd, *hashed_pin, hashed_pin_size))
 894             != (ssize_t)hashed_pin_size) {
 895                 free(*hashed_pin);
 896                 *hashed_pin = NULL;
 897                 return (CKR_FUNCTION_FAILED);
 898         }
 899         (*hashed_pin)[hashed_pin_size] = '\0';
 900         return (CKR_OK);
 901 }
 902 
 903 
 904 /*
 905  *      FUNCTION: soft_keystore_lock
 906  *
 907  *      ARGUMENTS:
 908  *              set_lock: TRUE to set readlock on the keystore object file,
 909  *                        FALSE to remove readlock on keystore object file.
 910  *
 911  *      RETURN VALUE:
 912  *
 913  *              0: success
 914  *              -1: failure
 915  *


1303                 goto cleanup;
1304         }
1305 
1306         if (writen_nointr(new_fd, (char *)iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) {
1307                 goto cleanup;
1308         }
1309 
1310         /* seek to the original encrypted data, and read all of them */
1311         if (lseek(old_fd, OBJ_DATA_OFFSET, SEEK_SET) != OBJ_DATA_OFFSET) {
1312                 goto cleanup;
1313         }
1314 
1315         if (read_obj_data(old_fd, (char **)&buf, &nread) != CKR_OK) {
1316                 goto cleanup;
1317         }
1318 
1319         /* decrypt data using old key */
1320         decrypted_len = 0;
1321         if (soft_keystore_crypt(enc_key, old_iv, B_FALSE, buf, nread,
1322             NULL, &decrypted_len) != CKR_OK) {
1323                 free(buf);
1324                 goto cleanup;
1325         }
1326 
1327         decrypted_buf = malloc(decrypted_len);
1328         if (decrypted_buf == NULL) {
1329                 free(buf);
1330                 goto cleanup;
1331         }
1332 
1333         if (soft_keystore_crypt(enc_key, old_iv, B_FALSE, buf, nread,
1334             decrypted_buf, &decrypted_len) != CKR_OK) {
1335                 free(buf);
1336                 free(decrypted_buf);
1337                 goto cleanup;
1338         }
1339 
1340         free(buf);
1341 
1342         /* re-encrypt with new key */
1343         encrypted_len = 0;
1344         if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf,
1345             decrypted_len, NULL, &encrypted_len) != CKR_OK) {
1346                 free(decrypted_buf);
1347                 goto cleanup;
1348         }
1349 
1350         buf = malloc(encrypted_len);
1351         if (buf == NULL) {
1352                 free(decrypted_buf);
1353                 goto cleanup;
1354         }
1355 
1356         if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf,
1357             decrypted_len, buf, &encrypted_len) != CKR_OK) {
1358                 free(buf);
1359                 free(decrypted_buf);
1360                 goto cleanup;
1361         }
1362 
1363         free(decrypted_buf);
1364 
1365         /* calculate hmac on re-encrypted data using new hmac key */
1366         hmac_len = OBJ_HMAC_SIZE;
1367         if (soft_keystore_hmac(new_hmac_key, B_TRUE, buf,
1368             encrypted_len, hmac, &hmac_len) != CKR_OK) {
1369                 free(buf);
1370                 goto cleanup;
1371         }
1372 
1373         /* just for sanity check */
1374         if (hmac_len != OBJ_HMAC_SIZE) {
1375                 free(buf);
1376                 goto cleanup;
1377         }
1378 
1379         /* write new hmac */
1380         if (writen_nointr(new_fd, (char *)hmac, OBJ_HMAC_SIZE)
1381             != OBJ_HMAC_SIZE) {
1382                 free(buf);
1383                 goto cleanup;
1384         }
1385 
1386         /* write re-encrypted buffer to temp file */
1387         if (writen_nointr(new_fd, (void *)buf, encrypted_len)
1388             != encrypted_len) {
1389                 free(buf);
1390                 goto cleanup;
1391         }
1392         free(buf);
1393         ret_val = 0;
1394 
1395 cleanup:
1396         /* unlock the files */
1397         (void) lock_file(old_fd, B_TRUE, B_FALSE);
1398         (void) lock_file(new_fd, B_FALSE, B_FALSE);
1399 
1400         (void) close(old_fd);
1401         (void) close(new_fd);
1402         if (ret_val != 0) {
1403                 (void) remove(new_obj_name);
1404         }
1405         return (ret_val);
1406 }
1407 
1408 /*
1409  *      FUNCTION: soft_keystore_setpin
1410  *
1411  *      ARGUMENTS:
1412  *              newpin: new pin entered by the user.


1530         }
1531         if (readn_nointr(fd, (char *)hmac_salt, KS_HMAC_SALT_SIZE)
1532             != KS_HMAC_SALT_SIZE) {
1533                 goto cleanup;
1534         }
1535 
1536         /* just create some empty bytes */
1537         bzero(filebuf, sizeof (filebuf));
1538 
1539         if (memcmp(crypt_salt, filebuf, KS_KEY_SALT_SIZE) == 0) {
1540                 /* PIN as never been set */
1541                 CK_BYTE *new_crypt_salt = NULL, *new_hmac_salt = NULL;
1542 
1543                 pin_never_set = B_TRUE;
1544                 if (soft_gen_crypt_key(newpin, &new_crypt_key, &new_crypt_salt)
1545                     != CKR_OK) {
1546                         goto cleanup;
1547                 }
1548                 if (writen_nointr(tmp_ks_fd, (void *)new_crypt_salt,
1549                     KS_KEY_SALT_SIZE) != KS_KEY_SALT_SIZE) {
1550                         free(new_crypt_salt);

1551                         (void) soft_cleanup_object(new_crypt_key);
1552                         goto cleanup;
1553                 }
1554                 free(new_crypt_salt);
1555 
1556                 if (soft_gen_hmac_key(newpin, &new_hmac_key, &new_hmac_salt)
1557                     != CKR_OK) {
1558                         (void) soft_cleanup_object(new_crypt_key);
1559                         goto cleanup;
1560                 }
1561                 if (writen_nointr(tmp_ks_fd, (void *)new_hmac_salt,
1562                     KS_HMAC_SALT_SIZE) != KS_HMAC_SALT_SIZE) {
1563                         free(new_hmac_salt);

1564                         goto cleanup3;
1565                 }
1566                 free(new_hmac_salt);
1567         } else {
1568                 if (soft_gen_crypt_key(newpin, &new_crypt_key,
1569                     (CK_BYTE **)&crypt_salt) != CKR_OK) {
1570                         goto cleanup;
1571                 }
1572                 /* no change to the encryption salt */
1573                 if (writen_nointr(tmp_ks_fd, (void *)crypt_salt,
1574                     KS_KEY_SALT_SIZE) != KS_KEY_SALT_SIZE) {
1575                         (void) soft_cleanup_object(new_crypt_key);
1576                         goto cleanup;
1577                 }
1578 
1579                 if (soft_gen_hmac_key(newpin, &new_hmac_key,
1580                     (CK_BYTE **)&hmac_salt) != CKR_OK) {
1581                         (void) soft_cleanup_object(new_crypt_key);
1582                         goto cleanup;
1583                 }
1584 
1585                 /* no change to the hmac salt */
1586                 if (writen_nointr(tmp_ks_fd, (void *)hmac_salt,


1595          */
1596         if (readn_nointr(fd, (char *)&hashed_pin_salt_length,
1597             KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
1598                 goto cleanup3;
1599         }
1600 
1601         if (writen_nointr(tmp_ks_fd, (void *)&hashed_pin_salt_length,
1602             KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
1603                 goto cleanup3;
1604         }
1605 
1606         hashed_pin_salt_length = SWAP64(hashed_pin_salt_length);
1607 
1608         hashed_pin_salt = malloc(hashed_pin_salt_length + 1);
1609         if (hashed_pin_salt == NULL) {
1610                 goto cleanup3;
1611         }
1612 
1613         if ((readn_nointr(fd, hashed_pin_salt, hashed_pin_salt_length)) !=
1614             (ssize_t)hashed_pin_salt_length) {
1615                 free(hashed_pin_salt);

1616                 goto cleanup3;
1617         }
1618 
1619         if ((writen_nointr(tmp_ks_fd, hashed_pin_salt, hashed_pin_salt_length))
1620             != (ssize_t)hashed_pin_salt_length) {
1621                 free(hashed_pin_salt);

1622                 goto cleanup3;
1623         }
1624 
1625         hashed_pin_salt[hashed_pin_salt_length] = '\0';
1626 
1627         /* old hashed pin length and value can be ignored, generate new one */
1628         if (soft_gen_hashed_pin(newpin, &new_hashed_pin,
1629             &hashed_pin_salt) < 0) {
1630                 free(hashed_pin_salt);

1631                 goto cleanup3;
1632         }
1633 
1634         free(hashed_pin_salt);
1635 
1636         if (new_hashed_pin == NULL) {
1637                 goto cleanup3;
1638         }
1639 
1640         new_hashed_pin_len = strlen(new_hashed_pin);
1641 
1642         /* write new hashed pin length to file */
1643         swaped_val = SWAP64(new_hashed_pin_len);
1644         if (writen_nointr(tmp_ks_fd, (void *)&swaped_val,
1645             KS_HASHED_PINLEN_SIZE) != KS_HASHED_PINLEN_SIZE) {
1646                 goto cleanup3;
1647         }
1648 
1649         if (writen_nointr(tmp_ks_fd, (void *)new_hashed_pin,
1650             new_hashed_pin_len) != (ssize_t)new_hashed_pin_len) {
1651                 goto cleanup3;
1652         }
1653 
1654         if (pin_never_set) {


1746         }
1747 
1748         if ((!user_logged_in) && (!pin_never_set)) {
1749                 (void) soft_cleanup_object(enc_key);
1750                 (void) soft_cleanup_object(hmac_key);
1751                 enc_key = NULL;
1752                 hmac_key = NULL;
1753         }
1754 cleanup3:
1755         if ((ret_val != 0) || (!user_logged_in)) {
1756                 (void) soft_cleanup_object(new_crypt_key);
1757                 (void) soft_cleanup_object(new_hmac_key);
1758         }
1759 
1760 cleanup:
1761         if (!lock_held) {
1762                 if (lock_file(fd, B_FALSE, B_FALSE) < 0) {
1763                         ret_val = 1;
1764                 }
1765         }
1766         if (crypt_salt != NULL) {
1767                 free(crypt_salt);
1768         }
1769         if (hmac_salt != NULL) {
1770                 free(hmac_salt);
1771         }
1772         (void) close(fd);
1773         (void) close(tmp_ks_fd);
1774         if (ret_val != 0) {
1775                 (void) remove(tmp_ks_desc_name);
1776         }
1777         return (ret_val);
1778 }
1779 
1780 /*
1781  *      FUNCTION: soft_keystore_authpin
1782  *
1783  *      ARGUMENTS:
1784  *              pin: pin specified by the user for logging into
1785  *                   the keystore.
1786  *
1787  *      RETURN VALUE:
1788  *              0: if no error
1789  *              -1: if there is any error
1790  *
1791  *      DESCRIPTION:


1838         if (lseek(fd, KS_HMAC_SALT_OFFSET, SEEK_SET) != KS_HMAC_SALT_OFFSET) {
1839                 goto cleanup;
1840         }
1841 
1842         if (readn_nointr(fd, (char *)hmac_salt, KS_HMAC_SALT_SIZE)
1843             != KS_HMAC_SALT_SIZE) {
1844                 goto cleanup;
1845         }
1846 
1847         if (soft_gen_hmac_key(pin, &hmac_key, (CK_BYTE **)&hmac_salt)
1848             != CKR_OK) {
1849                 goto cleanup;
1850         }
1851 
1852         ret_val = 0;
1853 
1854 cleanup:
1855         /* unlock the file */
1856         (void) lock_file(fd, B_TRUE, B_FALSE);
1857         (void) close(fd);
1858         if (crypt_salt != NULL) {
1859                 free(crypt_salt);
1860         }
1861         if (hmac_salt != NULL) {
1862                 free(hmac_salt);
1863         }
1864         return (ret_val);
1865 }
1866 
1867 /*
1868  *      FUNCTION: soft_keystore_get_objs
1869  *
1870  *      ARGUMENTS:
1871  *
1872  *              search_type: Specify type of objects to return.
1873  *              lock_held: TRUE if the lock is held by caller.
1874  *
1875  *
1876  *      RETURN VALUE:
1877  *
1878  *              NULL: if there are no object in the database.
1879  *
1880  *              Otherwise, linked list of objects as requested
1881  *              in search type.
1882  *
1883  *              The linked list returned will need to be freed


1963                         (void) closedir(dirp);
1964                         goto cleanup;
1965                 }
1966 
1967                 (void) closedir(dirp);
1968         }
1969         /* close the keystore description file */
1970         (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1971         (void) close(ks_fd);
1972         return (CKR_OK);
1973 cleanup:
1974 
1975         /* close the keystore description file */
1976         (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1977         (void) close(ks_fd);
1978 
1979         /* free all the objects found before hitting the error */
1980         tmp = *result_obj_list;
1981         while (tmp) {
1982                 *result_obj_list = tmp->next;
1983                 free(tmp->buf);
1984                 free(tmp);
1985                 tmp = *result_obj_list;
1986         }
1987         *result_obj_list = NULL;
1988         return (rv);
1989 }
1990 
1991 
1992 /*
1993  *      FUNCTION: soft_keystore_get_single_obj
1994  *
1995  *      ARGUMENTS:
1996  *              ks_handle: handle of the key store object to be accessed
1997  *              lock_held: TRUE if the lock is held by caller.
1998  *
1999  *      RETURN VALUE:
2000  *
2001  *              NULL: if handle doesn't match any object
2002  *
2003  *              Otherwise, the object is returned in


2070         }
2071 
2072         /* read the object */
2073         rv = read_obj_data(fd, (char **)&buf, &nread);
2074         if (rv != CKR_OK) {
2075                 goto cleanup;
2076         }
2077 
2078         if (ks_handle->public) {
2079                 obj->size = nread;
2080                 obj->buf = buf;
2081                 *return_obj = obj;
2082         } else {
2083 
2084                 CK_ULONG out_len = 0, hmac_size;
2085 
2086                 /* verify HMAC of the object, make sure it matches */
2087                 hmac_size = OBJ_HMAC_SIZE;
2088                 if (soft_keystore_hmac(hmac_key, B_FALSE, buf,
2089                     nread, obj_hmac, &hmac_size) != CKR_OK) {
2090                         free(buf);
2091                         rv = CKR_FUNCTION_FAILED;
2092                         goto cleanup;
2093                 }
2094 
2095                 /* decrypt object */
2096                 if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread,
2097                     NULL, &out_len) != CKR_OK) {
2098                         free(buf);
2099                         rv = CKR_FUNCTION_FAILED;
2100                         goto cleanup;
2101                 }
2102 
2103                 decrypted_buf = malloc(sizeof (uchar_t) * out_len);
2104                 if (decrypted_buf == NULL) {
2105                         free(buf);
2106                         rv = CKR_HOST_MEMORY;
2107                         goto cleanup;
2108                 }
2109 
2110                 if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread,
2111                     decrypted_buf, &out_len) != CKR_OK) {
2112                         free(decrypted_buf);
2113                         free(buf);
2114                         rv = CKR_FUNCTION_FAILED;
2115                         goto cleanup;
2116                 }
2117 
2118                 obj->size = out_len - MAXPATHLEN;
2119 
2120                 /*
2121                  * decrypted buf here actually contains full path name of
2122                  * object plus the actual data.  so, need to skip the
2123                  * full pathname.
2124                  * See prepare_data_for_encrypt() function in the file
2125                  * to understand how and why the pathname is added.
2126                  */
2127                 obj->buf = malloc(sizeof (uchar_t) * (out_len - MAXPATHLEN));
2128                 if (obj->buf == NULL) {
2129                         free(decrypted_buf);
2130                         free(buf);
2131                         rv = CKR_HOST_MEMORY;
2132                         goto cleanup;
2133                 }
2134                 (void) memcpy(obj->buf, decrypted_buf + MAXPATHLEN, obj->size);
2135                 free(decrypted_buf);
2136                 free(buf);
2137                 *return_obj = obj;
2138         }
2139 
2140 cleanup:
2141 
2142         if (rv != CKR_OK) {
2143                 free(obj);
2144         }
2145 
2146         /* unlock the file after reading */
2147         if (!lock_held) {
2148                 (void) lock_file(fd, B_TRUE, B_FALSE);
2149         }
2150 
2151         (void) close(fd);
2152 
2153         return (rv);
2154 }
2155 
2156 


2319                         goto cleanup2;
2320                 }
2321 
2322                 if (writen_nointr(obj_fd, (char *)buf, len) != len) {
2323                         goto cleanup2;
2324                 }
2325 
2326         } else {
2327 
2328                 uchar_t *encrypted_buf, *prepared_buf;
2329                 CK_ULONG out_len = 0, prepared_len;
2330 
2331                 if (prepare_data_for_encrypt(obj_name, buf, len,
2332                     &prepared_buf, &prepared_len) != 0) {
2333                         goto cleanup2;
2334                 }
2335 
2336                 if (soft_keystore_crypt(enc_key, iv,
2337                     B_TRUE, prepared_buf, prepared_len,
2338                     NULL, &out_len) != CKR_OK) {
2339                         free(prepared_buf);
2340                         goto cleanup2;
2341                 }
2342 
2343                 encrypted_buf = malloc(out_len * sizeof (char));
2344                 if (encrypted_buf == NULL) {
2345                         free(prepared_buf);
2346                         goto cleanup2;
2347                 }
2348 
2349                 if (soft_keystore_crypt(enc_key, iv,
2350                     B_TRUE, prepared_buf, prepared_len,
2351                     encrypted_buf, &out_len) != CKR_OK) {
2352                         free(encrypted_buf);
2353                         free(prepared_buf);
2354                         goto cleanup2;
2355                 }
2356                 free(prepared_buf);
2357 
2358                 /* calculate HMAC of encrypted object */
2359                 hmac_size = OBJ_HMAC_SIZE;
2360                 if (soft_keystore_hmac(hmac_key, B_TRUE, encrypted_buf,
2361                     out_len, obj_hmac, &hmac_size) != CKR_OK) {
2362                         free(encrypted_buf);
2363                         goto cleanup2;
2364                 }
2365 
2366                 if (hmac_size != OBJ_HMAC_SIZE) {
2367                         free(encrypted_buf);
2368                         goto cleanup2;
2369                 }
2370 
2371                 /* write hmac */
2372                 if (writen_nointr(obj_fd, (void *)obj_hmac,
2373                     sizeof (obj_hmac)) != sizeof (obj_hmac)) {
2374                         free(encrypted_buf);
2375                         goto cleanup2;
2376                 }
2377 
2378                 /* write encrypted object */
2379                 if (writen_nointr(obj_fd, (void *)encrypted_buf, out_len)
2380                     != out_len) {
2381                         free(encrypted_buf);
2382                         goto cleanup2;
2383                 }
2384 
2385                 free(encrypted_buf);
2386         }
2387 
2388 
2389         (void) close(obj_fd);
2390         (void) snprintf((char *)keyhandle->name, sizeof (keyhandle->name),
2391             "obj%d", counter);
2392         keyhandle->public = public;
2393 
2394         /*
2395          * store new counter to temp keystore description file.
2396          */
2397         counter++;
2398         counter = SWAP32(counter);
2399         if (writen_nointr(tmp_ks_fd, (void *)&counter,
2400             sizeof (counter)) != sizeof (counter)) {
2401                 goto cleanup2;
2402         }
2403 
2404         /* read rest of keystore description file and store into temp file */
2405         nread = readn_nointr(fd, filebuf, sizeof (filebuf));
2406         while (nread > 0) {
2407                 if (writen_nointr(tmp_ks_fd, filebuf, nread) != nread) {
2408                         goto cleanup2;
2409                 }
2410                 nread = readn_nointr(fd, filebuf, sizeof (filebuf));
2411         }
2412 
2413         (void) close(tmp_ks_fd);
2414         (void) rename(tmp_ks_desc_name, ks_desc_file);
2415 
2416         if (!lock_held) {
2417                 /* release lock on description file */
2418                 if (lock_file(fd, B_FALSE, B_FALSE) != 0) {
2419                         (void) close(fd);
2420                         return (-1);
2421                 }
2422         }
2423         (void) close(fd);


2424         return (0);
2425 
2426 cleanup2:
2427 
2428         /* remove object file.  No need to remove lock first */
2429         (void) unlink(obj_name);
2430 
2431 cleanup:
2432 
2433         (void) close(tmp_ks_fd);
2434         (void) remove(tmp_ks_desc_name);
2435         if (!lock_held) {
2436                 /* release lock on description file */
2437                 (void) lock_file(fd, B_FALSE, B_FALSE);
2438         }
2439 
2440         (void) close(fd);


2441         return (-1);
2442 }
2443 
2444 /*
2445  *      FUNCTION: soft_keystore_modify_obj
2446  *
2447  *      ARGUMENTS:
2448  *              ks_handle: handle of the key store object to be modified
2449  *              buf: buffer containing un-encrypted data
2450  *                   to be modified in keystore.
2451  *              len: length of data
2452  *              lock_held: TRUE if the lock is held by caller.
2453  *
2454  *      RETURN VALUE:
2455  *              -1: if any error occurred.
2456  *              Otherwise, 0 is returned.
2457  *
2458  *      DESCRIPTION:
2459  *
2460  *              This API is used to write a modified token object back


2574 
2575         } else {
2576 
2577                 uchar_t *encrypted_buf, *prepared_buf;
2578                 CK_ULONG out_len = 0, prepared_len;
2579 
2580                 if (prepare_data_for_encrypt(orig_name, buf, len,
2581                     &prepared_buf, &prepared_len) != 0) {
2582                         goto cleanup2;
2583                 }
2584 
2585                 /* encrypt the data */
2586                 if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf,
2587                     prepared_len, NULL, &out_len) != CKR_OK) {
2588                         free(prepared_buf);
2589                         goto cleanup2;
2590                 }
2591 
2592                 encrypted_buf = malloc(out_len * sizeof (char));
2593                 if (encrypted_buf == NULL) {
2594                         free(prepared_buf);
2595                         goto cleanup2;
2596                 }
2597 
2598                 if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf,
2599                     prepared_len, encrypted_buf, &out_len) != CKR_OK) {
2600                         free(encrypted_buf);
2601                         free(prepared_buf);
2602                         goto cleanup2;
2603                 }
2604 
2605                 free(prepared_buf);
2606 
2607                 /* calculate hmac on encrypted buf */
2608                 hmac_size = OBJ_HMAC_SIZE;
2609                 if (soft_keystore_hmac(hmac_key, B_TRUE, encrypted_buf,
2610                     out_len, obj_hmac, &hmac_size) != CKR_OK) {
2611                         free(encrypted_buf);
2612                         goto cleanup2;
2613                 }
2614 
2615                 if (hmac_size != OBJ_HMAC_SIZE) {
2616                         free(encrypted_buf);
2617                         goto cleanup2;
2618                 }
2619 
2620                 if (writen_nointr(tmp_fd, (char *)obj_hmac, OBJ_HMAC_SIZE)
2621                     != OBJ_HMAC_SIZE) {
2622                         free(encrypted_buf);
2623                         goto cleanup2;
2624                 }
2625 
2626                 if (writen_nointr(tmp_fd, (void *)encrypted_buf, out_len)
2627                     != out_len) {
2628                         free(encrypted_buf);
2629                         goto cleanup2;
2630                 }
2631                 free(encrypted_buf);
2632         }
2633         (void) close(tmp_fd);
2634 
2635         /* rename updated temporary object file */
2636         if (rename(tmp_name, orig_name) != 0) {
2637                 (void) unlink(tmp_name);
2638                 return (-1);
2639         }
2640 
2641         /* rename updated keystore description file */
2642         if (rename(tmp_ks_name, ks_desc_file) != 0) {
2643                 (void) unlink(tmp_name);
2644                 (void) unlink(tmp_ks_name);
2645                 return (-1);
2646         }
2647 
2648         /* determine need to unlock file or not */
2649         if (!lock_held) {
2650                 if (lock_file(fd, B_FALSE, B_FALSE) < 0) {
2651                         (void) close(fd);
2652                         (void) unlink(tmp_name);
2653                         return (-1);
2654                 }
2655         }
2656 
2657         /* unlock keystore description file */
2658         if (lock_file(ks_fd, B_FALSE, B_FALSE) != 0) {
2659                 (void) close(ks_fd);
2660                 (void) close(fd);
2661                 return (-1);
2662         }
2663 
2664         (void) close(ks_fd);
2665 
2666         (void) close(fd);
2667 


2668         return (0); /* All operations completed successfully */
2669 
2670 cleanup2:
2671         (void) close(tmp_fd);
2672         (void) remove(tmp_name);
2673 
2674 cleanup1:
2675         (void) close(fd);
2676 
2677 cleanup:
2678         /* unlock keystore description file */
2679         (void) lock_file(ks_fd, B_FALSE, B_FALSE);
2680         (void) close(ks_fd);
2681         (void) remove(tmp_ks_name);


2682         return (-1);
2683 }
2684 
2685 /*
2686  *      FUNCTION: soft_keystore_del_obj
2687  *
2688  *      ARGUMENTS:
2689  *              ks_handle: handle of the key store object to be deleted
2690  *              lock_held: TRUE if the lock is held by caller.
2691  *
2692  *      RETURN VALUE:
2693  *              -1: if any error occurred.
2694  *              0: object successfully deleted from keystore.
2695  *
2696  *      DESCRIPTION:
2697  *              This API is used to delete a particular token object from
2698  *              the keystore.  The corresponding token object file will be
2699  *              removed from the file system.
2700  *              Any future reference to the deleted file will
2701  *              return an CKR_OBJECT_HANDLE_INVALID error.


2786         }
2787 
2788         if (lseek(fd, KS_HASHED_PIN_SALT_LEN_OFFSET, SEEK_SET)
2789             != KS_HASHED_PIN_SALT_LEN_OFFSET) {
2790                 goto cleanup;
2791         }
2792 
2793         if (readn_nointr(fd, (char *)&hashed_pin_salt_size,
2794             KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
2795                 goto cleanup;
2796         }
2797         hashed_pin_salt_size = SWAP64(hashed_pin_salt_size);
2798 
2799         *salt = malloc(hashed_pin_salt_size + 1);
2800         if (*salt == NULL) {
2801                 goto cleanup;
2802         }
2803 
2804         if ((readn_nointr(fd, *salt, hashed_pin_salt_size))
2805             != (ssize_t)hashed_pin_salt_size) {
2806                 free(*salt);
2807                 goto cleanup;
2808         }
2809         (*salt)[hashed_pin_salt_size] = '\0';
2810 
2811         ret_val = 0;
2812 
2813 cleanup:
2814         if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
2815                 ret_val = -1;
2816         }
2817 
2818         (void) close(fd);
2819         return (ret_val);
2820 }
2821 
2822 /*
2823  *      FUNCTION: soft_keystore_pin_initialized
2824  *
2825  *      ARGUMENTS:
2826  *              initialized: This value will be set to true if keystore is




   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2018, Joyent, Inc.
  24  */
  25 
  26 /*
  27  * Functions used for manipulating the keystore
  28  */
  29 
  30 #include <stdio.h>
  31 #include <stdlib.h>
  32 #include <errno.h>
  33 #include <sys/stat.h>
  34 #include <fcntl.h>
  35 #include <time.h>
  36 #include <unistd.h>
  37 #include <pwd.h>
  38 #include <sys/types.h>
  39 #include <dirent.h>
  40 #include <limits.h>
  41 #include <libgen.h>
  42 #include <strings.h>
  43 #include <security/cryptoki.h>


 454         if (writen_nointr(fd, (void *)hashed_pin_salt,
 455             hashed_pin_salt_len) != hashed_pin_salt_len) {
 456                 goto cleanup;
 457         }
 458 
 459         /* write MD5 hashed pin of the default pin */
 460         ulong_buf = SWAP64(hashed_pin_len);
 461         if (writen_nointr(fd, (void *)&ulong_buf, KS_HASHED_PINLEN_SIZE)
 462             != KS_HASHED_PINLEN_SIZE) {
 463                 goto cleanup;
 464         }
 465 
 466         if (writen_nointr(fd, (void *)hashed_pin, hashed_pin_len)
 467             != hashed_pin_len) {
 468                 goto cleanup;
 469         }
 470 
 471         (void) lock_file(fd, B_FALSE, B_FALSE);
 472 
 473         (void) close(fd);
 474         freezero(hashed_pin_salt, hashed_pin_salt_len);

 475         return (0);
 476 
 477 cleanup:
 478         (void) lock_file(fd, B_FALSE, B_FALSE);
 479         (void) unlink(ks_desc_file);
 480         (void) close(fd);
 481         (void) rmdir(get_keystore_path());
 482         (void) rmdir(pub_obj_path);
 483         (void) rmdir(pri_obj_path);
 484         return (-1);
 485 }
 486 
 487 /*
 488  * Determines if the file referenced by "fd" has the same
 489  * inode as the file referenced by "fname".
 490  *
 491  * The argument "same" contains the result of determining
 492  * if the inode is the same or not
 493  *
 494  * Returns 0 if there's no error.


 875         /* first, get size of the hashed pin */
 876         if (lseek(fd, ks_hashed_pinlen_offset, SEEK_SET)
 877             != ks_hashed_pinlen_offset) {
 878                 return (CKR_FUNCTION_FAILED);
 879         }
 880 
 881         if (readn_nointr(fd, (char *)&hashed_pin_size,
 882             KS_HASHED_PINLEN_SIZE) != KS_HASHED_PINLEN_SIZE) {
 883                 return (CKR_FUNCTION_FAILED);
 884         }
 885 
 886         hashed_pin_size = SWAP64(hashed_pin_size);
 887 
 888         *hashed_pin = malloc(hashed_pin_size + 1);
 889         if (*hashed_pin == NULL) {
 890                 return (CKR_HOST_MEMORY);
 891         }
 892 
 893         if ((readn_nointr(fd, *hashed_pin, hashed_pin_size))
 894             != (ssize_t)hashed_pin_size) {
 895                 freezero(*hashed_pin, hashed_pin_size + 1);
 896                 *hashed_pin = NULL;
 897                 return (CKR_FUNCTION_FAILED);
 898         }
 899         (*hashed_pin)[hashed_pin_size] = '\0';
 900         return (CKR_OK);
 901 }
 902 
 903 
 904 /*
 905  *      FUNCTION: soft_keystore_lock
 906  *
 907  *      ARGUMENTS:
 908  *              set_lock: TRUE to set readlock on the keystore object file,
 909  *                        FALSE to remove readlock on keystore object file.
 910  *
 911  *      RETURN VALUE:
 912  *
 913  *              0: success
 914  *              -1: failure
 915  *


1303                 goto cleanup;
1304         }
1305 
1306         if (writen_nointr(new_fd, (char *)iv, OBJ_IV_SIZE) != OBJ_IV_SIZE) {
1307                 goto cleanup;
1308         }
1309 
1310         /* seek to the original encrypted data, and read all of them */
1311         if (lseek(old_fd, OBJ_DATA_OFFSET, SEEK_SET) != OBJ_DATA_OFFSET) {
1312                 goto cleanup;
1313         }
1314 
1315         if (read_obj_data(old_fd, (char **)&buf, &nread) != CKR_OK) {
1316                 goto cleanup;
1317         }
1318 
1319         /* decrypt data using old key */
1320         decrypted_len = 0;
1321         if (soft_keystore_crypt(enc_key, old_iv, B_FALSE, buf, nread,
1322             NULL, &decrypted_len) != CKR_OK) {
1323                 freezero(buf, nread);
1324                 goto cleanup;
1325         }
1326 
1327         decrypted_buf = malloc(decrypted_len);
1328         if (decrypted_buf == NULL) {
1329                 freezero(buf, nread);
1330                 goto cleanup;
1331         }
1332 
1333         if (soft_keystore_crypt(enc_key, old_iv, B_FALSE, buf, nread,
1334             decrypted_buf, &decrypted_len) != CKR_OK) {
1335                 freezero(buf, nread);
1336                 freezero(decrypted_buf, decrypted_len);

1337         }
1338 
1339         freezero(buf, nread);
1340 
1341         /* re-encrypt with new key */
1342         encrypted_len = 0;
1343         if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf,
1344             decrypted_len, NULL, &encrypted_len) != CKR_OK) {
1345                 freezero(decrypted_buf, decrypted_len);
1346                 goto cleanup;
1347         }
1348 
1349         buf = malloc(encrypted_len);
1350         if (buf == NULL) {
1351                 freezero(decrypted_buf, decrypted_len);
1352                 goto cleanup;
1353         }
1354 
1355         if (soft_keystore_crypt(new_enc_key, iv, B_TRUE, decrypted_buf,
1356             decrypted_len, buf, &encrypted_len) != CKR_OK) {
1357                 freezero(buf, encrypted_len);
1358                 freezero(buf, decrypted_len);
1359                 goto cleanup;
1360         }
1361 
1362         freezero(decrypted_buf, decrypted_len);
1363 
1364         /* calculate hmac on re-encrypted data using new hmac key */
1365         hmac_len = OBJ_HMAC_SIZE;
1366         if (soft_keystore_hmac(new_hmac_key, B_TRUE, buf,
1367             encrypted_len, hmac, &hmac_len) != CKR_OK) {
1368                 freezero(buf, encrypted_len);
1369                 goto cleanup;
1370         }
1371 
1372         /* just for sanity check */
1373         if (hmac_len != OBJ_HMAC_SIZE) {
1374                 freezero(buf, encrypted_len);
1375                 goto cleanup;
1376         }
1377 
1378         /* write new hmac */
1379         if (writen_nointr(new_fd, (char *)hmac, OBJ_HMAC_SIZE)
1380             != OBJ_HMAC_SIZE) {
1381                 freezero(buf, encrypted_len);
1382                 goto cleanup;
1383         }
1384 
1385         /* write re-encrypted buffer to temp file */
1386         if (writen_nointr(new_fd, (void *)buf, encrypted_len)
1387             != encrypted_len) {
1388                 freezero(buf, encrypted_len);
1389                 goto cleanup;
1390         }
1391         freezero(buf, encrypted_len);
1392         ret_val = 0;
1393 
1394 cleanup:
1395         /* unlock the files */
1396         (void) lock_file(old_fd, B_TRUE, B_FALSE);
1397         (void) lock_file(new_fd, B_FALSE, B_FALSE);
1398 
1399         (void) close(old_fd);
1400         (void) close(new_fd);
1401         if (ret_val != 0) {
1402                 (void) remove(new_obj_name);
1403         }
1404         return (ret_val);
1405 }
1406 
1407 /*
1408  *      FUNCTION: soft_keystore_setpin
1409  *
1410  *      ARGUMENTS:
1411  *              newpin: new pin entered by the user.


1529         }
1530         if (readn_nointr(fd, (char *)hmac_salt, KS_HMAC_SALT_SIZE)
1531             != KS_HMAC_SALT_SIZE) {
1532                 goto cleanup;
1533         }
1534 
1535         /* just create some empty bytes */
1536         bzero(filebuf, sizeof (filebuf));
1537 
1538         if (memcmp(crypt_salt, filebuf, KS_KEY_SALT_SIZE) == 0) {
1539                 /* PIN as never been set */
1540                 CK_BYTE *new_crypt_salt = NULL, *new_hmac_salt = NULL;
1541 
1542                 pin_never_set = B_TRUE;
1543                 if (soft_gen_crypt_key(newpin, &new_crypt_key, &new_crypt_salt)
1544                     != CKR_OK) {
1545                         goto cleanup;
1546                 }
1547                 if (writen_nointr(tmp_ks_fd, (void *)new_crypt_salt,
1548                     KS_KEY_SALT_SIZE) != KS_KEY_SALT_SIZE) {
1549                         freezero(new_crypt_salt,
1550                             KS_KEY_SALT_SIZE);
1551                         (void) soft_cleanup_object(new_crypt_key);
1552                         goto cleanup;
1553                 }
1554                 freezero(new_crypt_salt, KS_KEY_SALT_SIZE);
1555 
1556                 if (soft_gen_hmac_key(newpin, &new_hmac_key, &new_hmac_salt)
1557                     != CKR_OK) {
1558                         (void) soft_cleanup_object(new_crypt_key);
1559                         goto cleanup;
1560                 }
1561                 if (writen_nointr(tmp_ks_fd, (void *)new_hmac_salt,
1562                     KS_HMAC_SALT_SIZE) != KS_HMAC_SALT_SIZE) {
1563                         freezero(new_hmac_salt,
1564                             KS_HMAC_SALT_SIZE);
1565                         goto cleanup3;
1566                 }
1567                 freezero(new_hmac_salt, KS_HMAC_SALT_SIZE);
1568         } else {
1569                 if (soft_gen_crypt_key(newpin, &new_crypt_key,
1570                     (CK_BYTE **)&crypt_salt) != CKR_OK) {
1571                         goto cleanup;
1572                 }
1573                 /* no change to the encryption salt */
1574                 if (writen_nointr(tmp_ks_fd, (void *)crypt_salt,
1575                     KS_KEY_SALT_SIZE) != KS_KEY_SALT_SIZE) {
1576                         (void) soft_cleanup_object(new_crypt_key);
1577                         goto cleanup;
1578                 }
1579 
1580                 if (soft_gen_hmac_key(newpin, &new_hmac_key,
1581                     (CK_BYTE **)&hmac_salt) != CKR_OK) {
1582                         (void) soft_cleanup_object(new_crypt_key);
1583                         goto cleanup;
1584                 }
1585 
1586                 /* no change to the hmac salt */
1587                 if (writen_nointr(tmp_ks_fd, (void *)hmac_salt,


1596          */
1597         if (readn_nointr(fd, (char *)&hashed_pin_salt_length,
1598             KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
1599                 goto cleanup3;
1600         }
1601 
1602         if (writen_nointr(tmp_ks_fd, (void *)&hashed_pin_salt_length,
1603             KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
1604                 goto cleanup3;
1605         }
1606 
1607         hashed_pin_salt_length = SWAP64(hashed_pin_salt_length);
1608 
1609         hashed_pin_salt = malloc(hashed_pin_salt_length + 1);
1610         if (hashed_pin_salt == NULL) {
1611                 goto cleanup3;
1612         }
1613 
1614         if ((readn_nointr(fd, hashed_pin_salt, hashed_pin_salt_length)) !=
1615             (ssize_t)hashed_pin_salt_length) {
1616                 freezero(hashed_pin_salt,
1617                     hashed_pin_salt_length + 1);
1618                 goto cleanup3;
1619         }
1620 
1621         if ((writen_nointr(tmp_ks_fd, hashed_pin_salt, hashed_pin_salt_length))
1622             != (ssize_t)hashed_pin_salt_length) {
1623                 freezero(hashed_pin_salt,
1624                     hashed_pin_salt_length + 1);
1625                 goto cleanup3;
1626         }
1627 
1628         hashed_pin_salt[hashed_pin_salt_length] = '\0';
1629 
1630         /* old hashed pin length and value can be ignored, generate new one */
1631         if (soft_gen_hashed_pin(newpin, &new_hashed_pin,
1632             &hashed_pin_salt) < 0) {
1633                 freezero(hashed_pin_salt,
1634                     hashed_pin_salt_length + 1);
1635                 goto cleanup3;
1636         }
1637 
1638         freezero(hashed_pin_salt, hashed_pin_salt_length + 1);
1639 
1640         if (new_hashed_pin == NULL) {
1641                 goto cleanup3;
1642         }
1643 
1644         new_hashed_pin_len = strlen(new_hashed_pin);
1645 
1646         /* write new hashed pin length to file */
1647         swaped_val = SWAP64(new_hashed_pin_len);
1648         if (writen_nointr(tmp_ks_fd, (void *)&swaped_val,
1649             KS_HASHED_PINLEN_SIZE) != KS_HASHED_PINLEN_SIZE) {
1650                 goto cleanup3;
1651         }
1652 
1653         if (writen_nointr(tmp_ks_fd, (void *)new_hashed_pin,
1654             new_hashed_pin_len) != (ssize_t)new_hashed_pin_len) {
1655                 goto cleanup3;
1656         }
1657 
1658         if (pin_never_set) {


1750         }
1751 
1752         if ((!user_logged_in) && (!pin_never_set)) {
1753                 (void) soft_cleanup_object(enc_key);
1754                 (void) soft_cleanup_object(hmac_key);
1755                 enc_key = NULL;
1756                 hmac_key = NULL;
1757         }
1758 cleanup3:
1759         if ((ret_val != 0) || (!user_logged_in)) {
1760                 (void) soft_cleanup_object(new_crypt_key);
1761                 (void) soft_cleanup_object(new_hmac_key);
1762         }
1763 
1764 cleanup:
1765         if (!lock_held) {
1766                 if (lock_file(fd, B_FALSE, B_FALSE) < 0) {
1767                         ret_val = 1;
1768                 }
1769         }
1770         freezero(crypt_salt, KS_KEY_SALT_SIZE);
1771         freezero(hmac_salt, KS_HMAC_SALT_SIZE);




1772         (void) close(fd);
1773         (void) close(tmp_ks_fd);
1774         if (ret_val != 0) {
1775                 (void) remove(tmp_ks_desc_name);
1776         }
1777         return (ret_val);
1778 }
1779 
1780 /*
1781  *      FUNCTION: soft_keystore_authpin
1782  *
1783  *      ARGUMENTS:
1784  *              pin: pin specified by the user for logging into
1785  *                   the keystore.
1786  *
1787  *      RETURN VALUE:
1788  *              0: if no error
1789  *              -1: if there is any error
1790  *
1791  *      DESCRIPTION:


1838         if (lseek(fd, KS_HMAC_SALT_OFFSET, SEEK_SET) != KS_HMAC_SALT_OFFSET) {
1839                 goto cleanup;
1840         }
1841 
1842         if (readn_nointr(fd, (char *)hmac_salt, KS_HMAC_SALT_SIZE)
1843             != KS_HMAC_SALT_SIZE) {
1844                 goto cleanup;
1845         }
1846 
1847         if (soft_gen_hmac_key(pin, &hmac_key, (CK_BYTE **)&hmac_salt)
1848             != CKR_OK) {
1849                 goto cleanup;
1850         }
1851 
1852         ret_val = 0;
1853 
1854 cleanup:
1855         /* unlock the file */
1856         (void) lock_file(fd, B_TRUE, B_FALSE);
1857         (void) close(fd);
1858         freezero(crypt_salt, KS_KEY_SALT_SIZE);
1859         freezero(hmac_salt, KS_HMAC_SALT_SIZE);




1860         return (ret_val);
1861 }
1862 
1863 /*
1864  *      FUNCTION: soft_keystore_get_objs
1865  *
1866  *      ARGUMENTS:
1867  *
1868  *              search_type: Specify type of objects to return.
1869  *              lock_held: TRUE if the lock is held by caller.
1870  *
1871  *
1872  *      RETURN VALUE:
1873  *
1874  *              NULL: if there are no object in the database.
1875  *
1876  *              Otherwise, linked list of objects as requested
1877  *              in search type.
1878  *
1879  *              The linked list returned will need to be freed


1959                         (void) closedir(dirp);
1960                         goto cleanup;
1961                 }
1962 
1963                 (void) closedir(dirp);
1964         }
1965         /* close the keystore description file */
1966         (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1967         (void) close(ks_fd);
1968         return (CKR_OK);
1969 cleanup:
1970 
1971         /* close the keystore description file */
1972         (void) lock_file(ks_fd, B_TRUE, B_FALSE);
1973         (void) close(ks_fd);
1974 
1975         /* free all the objects found before hitting the error */
1976         tmp = *result_obj_list;
1977         while (tmp) {
1978                 *result_obj_list = tmp->next;
1979                 freezero(tmp->buf, tmp->size);
1980                 free(tmp);
1981                 tmp = *result_obj_list;
1982         }
1983         *result_obj_list = NULL;
1984         return (rv);
1985 }
1986 
1987 
1988 /*
1989  *      FUNCTION: soft_keystore_get_single_obj
1990  *
1991  *      ARGUMENTS:
1992  *              ks_handle: handle of the key store object to be accessed
1993  *              lock_held: TRUE if the lock is held by caller.
1994  *
1995  *      RETURN VALUE:
1996  *
1997  *              NULL: if handle doesn't match any object
1998  *
1999  *              Otherwise, the object is returned in


2066         }
2067 
2068         /* read the object */
2069         rv = read_obj_data(fd, (char **)&buf, &nread);
2070         if (rv != CKR_OK) {
2071                 goto cleanup;
2072         }
2073 
2074         if (ks_handle->public) {
2075                 obj->size = nread;
2076                 obj->buf = buf;
2077                 *return_obj = obj;
2078         } else {
2079 
2080                 CK_ULONG out_len = 0, hmac_size;
2081 
2082                 /* verify HMAC of the object, make sure it matches */
2083                 hmac_size = OBJ_HMAC_SIZE;
2084                 if (soft_keystore_hmac(hmac_key, B_FALSE, buf,
2085                     nread, obj_hmac, &hmac_size) != CKR_OK) {
2086                         freezero(buf, nread);
2087                         rv = CKR_FUNCTION_FAILED;
2088                         goto cleanup;
2089                 }
2090 
2091                 /* decrypt object */
2092                 if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread,
2093                     NULL, &out_len) != CKR_OK) {
2094                         freezero(buf, nread);
2095                         rv = CKR_FUNCTION_FAILED;
2096                         goto cleanup;
2097                 }
2098 
2099                 decrypted_buf = malloc(sizeof (uchar_t) * out_len);
2100                 if (decrypted_buf == NULL) {
2101                         freezero(buf, nread);
2102                         rv = CKR_HOST_MEMORY;
2103                         goto cleanup;
2104                 }
2105 
2106                 if (soft_keystore_crypt(enc_key, iv, B_FALSE, buf, nread,
2107                     decrypted_buf, &out_len) != CKR_OK) {
2108                         freezero(buf, nread);
2109                         freezero(decrypted_buf, out_len);
2110                         rv = CKR_FUNCTION_FAILED;
2111                         goto cleanup;
2112                 }
2113 
2114                 obj->size = out_len - MAXPATHLEN;
2115 
2116                 /*
2117                  * decrypted buf here actually contains full path name of
2118                  * object plus the actual data.  so, need to skip the
2119                  * full pathname.
2120                  * See prepare_data_for_encrypt() function in the file
2121                  * to understand how and why the pathname is added.
2122                  */
2123                 obj->buf = malloc(sizeof (uchar_t) * (out_len - MAXPATHLEN));
2124                 if (obj->buf == NULL) {
2125                         freezero(buf, nread);
2126                         freezero(decrypted_buf, out_len);
2127                         rv = CKR_HOST_MEMORY;
2128                         goto cleanup;
2129                 }
2130                 (void) memcpy(obj->buf, decrypted_buf + MAXPATHLEN, obj->size);
2131                 freezero(buf, nread);
2132                 freezero(decrypted_buf, out_len);
2133                 *return_obj = obj;
2134         }
2135 
2136 cleanup:
2137 
2138         if (rv != CKR_OK) {
2139                 free(obj);
2140         }
2141 
2142         /* unlock the file after reading */
2143         if (!lock_held) {
2144                 (void) lock_file(fd, B_TRUE, B_FALSE);
2145         }
2146 
2147         (void) close(fd);
2148 
2149         return (rv);
2150 }
2151 
2152 


2315                         goto cleanup2;
2316                 }
2317 
2318                 if (writen_nointr(obj_fd, (char *)buf, len) != len) {
2319                         goto cleanup2;
2320                 }
2321 
2322         } else {
2323 
2324                 uchar_t *encrypted_buf, *prepared_buf;
2325                 CK_ULONG out_len = 0, prepared_len;
2326 
2327                 if (prepare_data_for_encrypt(obj_name, buf, len,
2328                     &prepared_buf, &prepared_len) != 0) {
2329                         goto cleanup2;
2330                 }
2331 
2332                 if (soft_keystore_crypt(enc_key, iv,
2333                     B_TRUE, prepared_buf, prepared_len,
2334                     NULL, &out_len) != CKR_OK) {
2335                         freezero(prepared_buf, prepared_len);
2336                         goto cleanup2;
2337                 }
2338 
2339                 encrypted_buf = malloc(out_len * sizeof (char));
2340                 if (encrypted_buf == NULL) {
2341                         freezero(prepared_buf, prepared_len);
2342                         goto cleanup2;
2343                 }
2344 
2345                 if (soft_keystore_crypt(enc_key, iv,
2346                     B_TRUE, prepared_buf, prepared_len,
2347                     encrypted_buf, &out_len) != CKR_OK) {
2348                         freezero(encrypted_buf, out_len);
2349                         freezero(prepared_buf, prepared_len);
2350                         goto cleanup2;
2351                 }
2352                 freezero(prepared_buf, prepared_len);
2353 
2354                 /* calculate HMAC of encrypted object */
2355                 hmac_size = OBJ_HMAC_SIZE;
2356                 if (soft_keystore_hmac(hmac_key, B_TRUE, encrypted_buf,
2357                     out_len, obj_hmac, &hmac_size) != CKR_OK) {
2358                         freezero(encrypted_buf, out_len);
2359                         goto cleanup2;
2360                 }
2361 
2362                 if (hmac_size != OBJ_HMAC_SIZE) {
2363                         freezero(encrypted_buf, out_len);
2364                         goto cleanup2;
2365                 }
2366 
2367                 /* write hmac */
2368                 if (writen_nointr(obj_fd, (void *)obj_hmac,
2369                     sizeof (obj_hmac)) != sizeof (obj_hmac)) {
2370                         freezero(encrypted_buf, out_len);
2371                         goto cleanup2;
2372                 }
2373 
2374                 /* write encrypted object */
2375                 if (writen_nointr(obj_fd, (void *)encrypted_buf, out_len)
2376                     != out_len) {
2377                         freezero(encrypted_buf, out_len);
2378                         goto cleanup2;
2379                 }
2380 
2381                 freezero(encrypted_buf, out_len);
2382         }
2383 
2384 
2385         (void) close(obj_fd);
2386         (void) snprintf((char *)keyhandle->name, sizeof (keyhandle->name),
2387             "obj%d", counter);
2388         keyhandle->public = public;
2389 
2390         /*
2391          * store new counter to temp keystore description file.
2392          */
2393         counter++;
2394         counter = SWAP32(counter);
2395         if (writen_nointr(tmp_ks_fd, (void *)&counter,
2396             sizeof (counter)) != sizeof (counter)) {
2397                 goto cleanup2;
2398         }
2399 
2400         /* read rest of keystore description file and store into temp file */
2401         nread = readn_nointr(fd, filebuf, sizeof (filebuf));
2402         while (nread > 0) {
2403                 if (writen_nointr(tmp_ks_fd, filebuf, nread) != nread) {
2404                         goto cleanup2;
2405                 }
2406                 nread = readn_nointr(fd, filebuf, sizeof (filebuf));
2407         }
2408 
2409         (void) close(tmp_ks_fd);
2410         (void) rename(tmp_ks_desc_name, ks_desc_file);
2411 
2412         if (!lock_held) {
2413                 /* release lock on description file */
2414                 if (lock_file(fd, B_FALSE, B_FALSE) != 0) {
2415                         (void) close(fd);
2416                         return (-1);
2417                 }
2418         }
2419         (void) close(fd);
2420         explicit_bzero(obj_hmac, sizeof (obj_hmac));
2421         explicit_bzero(iv, sizeof (iv));
2422         return (0);
2423 
2424 cleanup2:
2425 
2426         /* remove object file.  No need to remove lock first */
2427         (void) unlink(obj_name);
2428 
2429 cleanup:
2430 
2431         (void) close(tmp_ks_fd);
2432         (void) remove(tmp_ks_desc_name);
2433         if (!lock_held) {
2434                 /* release lock on description file */
2435                 (void) lock_file(fd, B_FALSE, B_FALSE);
2436         }
2437 
2438         (void) close(fd);
2439         explicit_bzero(obj_hmac, sizeof (obj_hmac));
2440         explicit_bzero(iv, sizeof (iv));
2441         return (-1);
2442 }
2443 
2444 /*
2445  *      FUNCTION: soft_keystore_modify_obj
2446  *
2447  *      ARGUMENTS:
2448  *              ks_handle: handle of the key store object to be modified
2449  *              buf: buffer containing un-encrypted data
2450  *                   to be modified in keystore.
2451  *              len: length of data
2452  *              lock_held: TRUE if the lock is held by caller.
2453  *
2454  *      RETURN VALUE:
2455  *              -1: if any error occurred.
2456  *              Otherwise, 0 is returned.
2457  *
2458  *      DESCRIPTION:
2459  *
2460  *              This API is used to write a modified token object back


2574 
2575         } else {
2576 
2577                 uchar_t *encrypted_buf, *prepared_buf;
2578                 CK_ULONG out_len = 0, prepared_len;
2579 
2580                 if (prepare_data_for_encrypt(orig_name, buf, len,
2581                     &prepared_buf, &prepared_len) != 0) {
2582                         goto cleanup2;
2583                 }
2584 
2585                 /* encrypt the data */
2586                 if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf,
2587                     prepared_len, NULL, &out_len) != CKR_OK) {
2588                         free(prepared_buf);
2589                         goto cleanup2;
2590                 }
2591 
2592                 encrypted_buf = malloc(out_len * sizeof (char));
2593                 if (encrypted_buf == NULL) {
2594                         freezero(prepared_buf, prepared_len);
2595                         goto cleanup2;
2596                 }
2597 
2598                 if (soft_keystore_crypt(enc_key, iv, B_TRUE, prepared_buf,
2599                     prepared_len, encrypted_buf, &out_len) != CKR_OK) {
2600                         freezero(prepared_buf, prepared_len);
2601                         freezero(encrypted_buf, out_len);
2602                         goto cleanup2;
2603                 }
2604 
2605                 freezero(prepared_buf, prepared_len);
2606 
2607                 /* calculate hmac on encrypted buf */
2608                 hmac_size = OBJ_HMAC_SIZE;
2609                 if (soft_keystore_hmac(hmac_key, B_TRUE, encrypted_buf,
2610                     out_len, obj_hmac, &hmac_size) != CKR_OK) {
2611                         freezero(encrypted_buf, out_len);
2612                         goto cleanup2;
2613                 }
2614 
2615                 if (hmac_size != OBJ_HMAC_SIZE) {
2616                         freezero(encrypted_buf, out_len);
2617                         goto cleanup2;
2618                 }
2619 
2620                 if (writen_nointr(tmp_fd, (char *)obj_hmac, OBJ_HMAC_SIZE)
2621                     != OBJ_HMAC_SIZE) {
2622                         freezero(encrypted_buf, out_len);
2623                         goto cleanup2;
2624                 }
2625 
2626                 if (writen_nointr(tmp_fd, (void *)encrypted_buf, out_len)
2627                     != out_len) {
2628                         freezero(encrypted_buf, out_len);
2629                         goto cleanup2;
2630                 }
2631                 freezero(encrypted_buf, out_len);
2632         }
2633         (void) close(tmp_fd);
2634 
2635         /* rename updated temporary object file */
2636         if (rename(tmp_name, orig_name) != 0) {
2637                 (void) unlink(tmp_name);
2638                 return (-1);
2639         }
2640 
2641         /* rename updated keystore description file */
2642         if (rename(tmp_ks_name, ks_desc_file) != 0) {
2643                 (void) unlink(tmp_name);
2644                 (void) unlink(tmp_ks_name);
2645                 return (-1);
2646         }
2647 
2648         /* determine need to unlock file or not */
2649         if (!lock_held) {
2650                 if (lock_file(fd, B_FALSE, B_FALSE) < 0) {
2651                         (void) close(fd);
2652                         (void) unlink(tmp_name);
2653                         return (-1);
2654                 }
2655         }
2656 
2657         /* unlock keystore description file */
2658         if (lock_file(ks_fd, B_FALSE, B_FALSE) != 0) {
2659                 (void) close(ks_fd);
2660                 (void) close(fd);
2661                 return (-1);
2662         }
2663 
2664         (void) close(ks_fd);
2665 
2666         (void) close(fd);
2667 
2668         explicit_bzero(iv, sizeof (iv));
2669         explicit_bzero(obj_hmac, sizeof (obj_hmac));
2670         return (0); /* All operations completed successfully */
2671 
2672 cleanup2:
2673         (void) close(tmp_fd);
2674         (void) remove(tmp_name);
2675 
2676 cleanup1:
2677         (void) close(fd);
2678 
2679 cleanup:
2680         /* unlock keystore description file */
2681         (void) lock_file(ks_fd, B_FALSE, B_FALSE);
2682         (void) close(ks_fd);
2683         (void) remove(tmp_ks_name);
2684         explicit_bzero(iv, sizeof (iv));
2685         explicit_bzero(obj_hmac, sizeof (obj_hmac));
2686         return (-1);
2687 }
2688 
2689 /*
2690  *      FUNCTION: soft_keystore_del_obj
2691  *
2692  *      ARGUMENTS:
2693  *              ks_handle: handle of the key store object to be deleted
2694  *              lock_held: TRUE if the lock is held by caller.
2695  *
2696  *      RETURN VALUE:
2697  *              -1: if any error occurred.
2698  *              0: object successfully deleted from keystore.
2699  *
2700  *      DESCRIPTION:
2701  *              This API is used to delete a particular token object from
2702  *              the keystore.  The corresponding token object file will be
2703  *              removed from the file system.
2704  *              Any future reference to the deleted file will
2705  *              return an CKR_OBJECT_HANDLE_INVALID error.


2790         }
2791 
2792         if (lseek(fd, KS_HASHED_PIN_SALT_LEN_OFFSET, SEEK_SET)
2793             != KS_HASHED_PIN_SALT_LEN_OFFSET) {
2794                 goto cleanup;
2795         }
2796 
2797         if (readn_nointr(fd, (char *)&hashed_pin_salt_size,
2798             KS_HASHED_PIN_SALT_LEN_SIZE) != KS_HASHED_PIN_SALT_LEN_SIZE) {
2799                 goto cleanup;
2800         }
2801         hashed_pin_salt_size = SWAP64(hashed_pin_salt_size);
2802 
2803         *salt = malloc(hashed_pin_salt_size + 1);
2804         if (*salt == NULL) {
2805                 goto cleanup;
2806         }
2807 
2808         if ((readn_nointr(fd, *salt, hashed_pin_salt_size))
2809             != (ssize_t)hashed_pin_salt_size) {
2810                 freezero(*salt, hashed_pin_salt_size + 1);
2811                 goto cleanup;
2812         }
2813         (*salt)[hashed_pin_salt_size] = '\0';
2814 
2815         ret_val = 0;
2816 
2817 cleanup:
2818         if (lock_file(fd, B_TRUE, B_FALSE) < 0) {
2819                 ret_val = -1;
2820         }
2821 
2822         (void) close(fd);
2823         return (ret_val);
2824 }
2825 
2826 /*
2827  *      FUNCTION: soft_keystore_pin_initialized
2828  *
2829  *      ARGUMENTS:
2830  *              initialized: This value will be set to true if keystore is