137
138 lofi_compress_info_t lofi_compress_table[LOFI_COMPRESS_FUNCTIONS] = {
139 {NULL, gzip_compress, 6, "gzip"}, /* default */
140 {NULL, gzip_compress, 6, "gzip-6"},
141 {NULL, gzip_compress, 9, "gzip-9"},
142 {NULL, lzma_compress, 0, "lzma"}
143 };
144
145 /* For displaying lofi mappings */
146 #define FORMAT "%-20s %-30s %s\n"
147
148 #define COMPRESS_ALGORITHM "gzip"
149 #define COMPRESS_THRESHOLD 2048
150 #define SEGSIZE 131072
151 #define BLOCK_SIZE 512
152 #define KILOBYTE 1024
153 #define MEGABYTE (KILOBYTE * KILOBYTE)
154 #define GIGABYTE (KILOBYTE * MEGABYTE)
155 #define LIBZ "libz.so.1"
156
157 static void
158 usage(const char *pname)
159 {
160 (void) fprintf(stderr, gettext(USAGE), pname, pname, pname,
161 pname, pname, pname, pname, pname, pname, pname);
162 exit(E_USAGE);
163 }
164
165 static int
166 gzip_compress(void *src, size_t srclen, void *dst, size_t *dstlen, int level)
167 {
168 static int (*compress2p)(void *, ulong_t *, void *, size_t, int) = NULL;
169 void *libz_hdl = NULL;
170
171 /*
172 * The first time we are called, attempt to dlopen()
173 * libz.so.1 and get a pointer to the compress2() function
174 */
175 if (compress2p == NULL) {
176 if ((libz_hdl = openlib(LIBZ)) == NULL)
819 copyfield(ti->key, FLD_LABEL);
820
821 /*
822 * If token specified and it only contains a key label, then
823 * search all tokens for the key, otherwise only those with
824 * matching name, mfr, and serno are used.
825 */
826 /*
827 * That's how we'd like it to be, however, if only the key label
828 * is specified, default to using softtoken. It's easier.
829 */
830 if (ti->name == NULL && ti->mfr == NULL && ti->serno == NULL)
831 ti->name = strdup(pkcs11_default_token());
832 return (ti);
833 }
834
835 /*
836 * PBE the passphrase into a raw key
837 */
838 static void
839 getkeyfromuser(mech_alias_t *cipher, char **raw_key, size_t *raw_key_sz)
840 {
841 CK_SESSION_HANDLE sess;
842 CK_RV rv;
843 char *pass = NULL;
844 size_t passlen = 0;
845 void *salt = NULL; /* don't use NULL, see note on salt below */
846 size_t saltlen = 0;
847 CK_KEY_TYPE ktype;
848 void *kvalue;
849 size_t klen;
850
851 /* did init_crypto find a slot that supports this cipher? */
852 if (cipher->slot == (CK_SLOT_ID)-1 || cipher->max_keysize == 0) {
853 rv = CKR_MECHANISM_INVALID;
854 goto cleanup;
855 }
856
857 rv = pkcs11_mech2keytype(cipher->type, &ktype);
858 if (rv != CKR_OK)
859 goto cleanup;
860
861 /*
862 * use the passphrase to generate a PBE PKCS#5 secret key and
863 * retrieve the raw key data to eventually pass it to the kernel;
864 */
865 rv = C_OpenSession(cipher->slot, CKF_SERIAL_SESSION, NULL, NULL, &sess);
866 if (rv != CKR_OK)
867 goto cleanup;
868
869 /* get user passphrase with 8 byte minimum */
870 if (pkcs11_get_pass(NULL, &pass, &passlen, MIN_PASSLEN, B_TRUE) < 0) {
871 die(gettext("passphrases do not match\n"));
872 }
873
874 /*
875 * salt should not be NULL, or else pkcs11_PasswdToKey() will
876 * complain about CKR_MECHANISM_PARAM_INVALID; the following is
877 * to make up for not having a salt until a proper one is used
878 */
879 salt = pass;
880 saltlen = passlen;
881
882 klen = cipher->max_keysize;
883 rv = pkcs11_PasswdToKey(sess, pass, passlen, salt, saltlen, ktype,
884 cipher->max_keysize, &kvalue, &klen);
885
886 (void) C_CloseSession(sess);
887
888 if (rv != CKR_OK) {
889 goto cleanup;
890 }
1743 die(gettext("open: %s"), filename);
1744 }
1745 error = fstat64(fd, &buf);
1746 if (error == -1) {
1747 die(gettext("fstat: %s"), filename);
1748 } else if (!S_ISLOFIABLE(buf.st_mode)) {
1749 die(gettext("%s is not a regular file, "
1750 "block, or character device\n"),
1751 filename);
1752 } else if ((buf.st_size % DEV_BSIZE) != 0) {
1753 die(gettext("size of %s is not a multiple of %d\n"),
1754 filename, DEV_BSIZE);
1755 }
1756 (void) close(fd);
1757
1758 if (name_to_minor(filename) != 0) {
1759 die(gettext("cannot use %s on itself\n"), LOFI_DRIVER_NAME);
1760 }
1761 }
1762
1763 static uint32_t
1764 convert_to_num(const char *str)
1765 {
1766 int len;
1767 uint32_t segsize, mult = 1;
1768
1769 len = strlen(str);
1770 if (len && isalpha(str[len - 1])) {
1771 switch (str[len - 1]) {
1772 case 'k':
1773 case 'K':
1774 mult = KILOBYTE;
1775 break;
1776 case 'b':
1777 case 'B':
1778 mult = BLOCK_SIZE;
1779 break;
1780 case 'm':
1781 case 'M':
1782 mult = MEGABYTE;
2005 * in which case the passphrase unlocks the token
2006 * If only the cipher is specified, reconfirm the passphrase
2007 * to ensure the user hasn't mis-entered it. Otherwise, the
2008 * token will enforce the token passphrase.
2009 */
2010 if (need_crypto) {
2011 CK_SESSION_HANDLE sess;
2012
2013 /* pick a cipher if none specified */
2014 if (cipher == NULL)
2015 cipher = DEFAULT_CIPHER;
2016
2017 if (!kernel_cipher_check(cipher))
2018 die(gettext(
2019 "use \"cryptoadm list -m\" to find available "
2020 "mechanisms\n"));
2021
2022 init_crypto(token, cipher, &sess);
2023
2024 if (cipher_only) {
2025 getkeyfromuser(cipher, &rkey, &rksz);
2026 } else if (token != NULL) {
2027 getkeyfromtoken(sess, token, keyfile, cipher,
2028 &rkey, &rksz);
2029 } else {
2030 /* this also handles ephemeral keys */
2031 getkeyfromfile(keyfile, cipher, &rkey, &rksz);
2032 }
2033
2034 end_crypto(sess);
2035 }
2036
2037 /*
2038 * Now to the real work.
2039 */
2040 if (addflag)
2041 add_mapping(lfd, devicename, filename, cipher, rkey, rksz,
2042 rdflag);
2043 else if (compressflag)
2044 lofi_compress(&lfd, filename, compress_index, segsize);
2045 else if (uncompressflag)
|
137
138 lofi_compress_info_t lofi_compress_table[LOFI_COMPRESS_FUNCTIONS] = {
139 {NULL, gzip_compress, 6, "gzip"}, /* default */
140 {NULL, gzip_compress, 6, "gzip-6"},
141 {NULL, gzip_compress, 9, "gzip-9"},
142 {NULL, lzma_compress, 0, "lzma"}
143 };
144
145 /* For displaying lofi mappings */
146 #define FORMAT "%-20s %-30s %s\n"
147
148 #define COMPRESS_ALGORITHM "gzip"
149 #define COMPRESS_THRESHOLD 2048
150 #define SEGSIZE 131072
151 #define BLOCK_SIZE 512
152 #define KILOBYTE 1024
153 #define MEGABYTE (KILOBYTE * KILOBYTE)
154 #define GIGABYTE (KILOBYTE * MEGABYTE)
155 #define LIBZ "libz.so.1"
156
157 const char lofi_crypto_magic[6] = LOFI_CRYPTO_MAGIC;
158
159 static void
160 usage(const char *pname)
161 {
162 (void) fprintf(stderr, gettext(USAGE), pname, pname, pname,
163 pname, pname, pname, pname, pname, pname, pname);
164 exit(E_USAGE);
165 }
166
167 static int
168 gzip_compress(void *src, size_t srclen, void *dst, size_t *dstlen, int level)
169 {
170 static int (*compress2p)(void *, ulong_t *, void *, size_t, int) = NULL;
171 void *libz_hdl = NULL;
172
173 /*
174 * The first time we are called, attempt to dlopen()
175 * libz.so.1 and get a pointer to the compress2() function
176 */
177 if (compress2p == NULL) {
178 if ((libz_hdl = openlib(LIBZ)) == NULL)
821 copyfield(ti->key, FLD_LABEL);
822
823 /*
824 * If token specified and it only contains a key label, then
825 * search all tokens for the key, otherwise only those with
826 * matching name, mfr, and serno are used.
827 */
828 /*
829 * That's how we'd like it to be, however, if only the key label
830 * is specified, default to using softtoken. It's easier.
831 */
832 if (ti->name == NULL && ti->mfr == NULL && ti->serno == NULL)
833 ti->name = strdup(pkcs11_default_token());
834 return (ti);
835 }
836
837 /*
838 * PBE the passphrase into a raw key
839 */
840 static void
841 getkeyfromuser(mech_alias_t *cipher, char **raw_key, size_t *raw_key_sz,
842 boolean_t with_confirmation)
843 {
844 CK_SESSION_HANDLE sess;
845 CK_RV rv;
846 char *pass = NULL;
847 size_t passlen = 0;
848 void *salt = NULL; /* don't use NULL, see note on salt below */
849 size_t saltlen = 0;
850 CK_KEY_TYPE ktype;
851 void *kvalue;
852 size_t klen;
853
854 /* did init_crypto find a slot that supports this cipher? */
855 if (cipher->slot == (CK_SLOT_ID)-1 || cipher->max_keysize == 0) {
856 rv = CKR_MECHANISM_INVALID;
857 goto cleanup;
858 }
859
860 rv = pkcs11_mech2keytype(cipher->type, &ktype);
861 if (rv != CKR_OK)
862 goto cleanup;
863
864 /*
865 * use the passphrase to generate a PBE PKCS#5 secret key and
866 * retrieve the raw key data to eventually pass it to the kernel;
867 */
868 rv = C_OpenSession(cipher->slot, CKF_SERIAL_SESSION, NULL, NULL, &sess);
869 if (rv != CKR_OK)
870 goto cleanup;
871
872 /* get user passphrase with 8 byte minimum */
873 if (pkcs11_get_pass(NULL, &pass, &passlen, MIN_PASSLEN,
874 with_confirmation) < 0) {
875 die(gettext("passphrases do not match\n"));
876 }
877
878 /*
879 * salt should not be NULL, or else pkcs11_PasswdToKey() will
880 * complain about CKR_MECHANISM_PARAM_INVALID; the following is
881 * to make up for not having a salt until a proper one is used
882 */
883 salt = pass;
884 saltlen = passlen;
885
886 klen = cipher->max_keysize;
887 rv = pkcs11_PasswdToKey(sess, pass, passlen, salt, saltlen, ktype,
888 cipher->max_keysize, &kvalue, &klen);
889
890 (void) C_CloseSession(sess);
891
892 if (rv != CKR_OK) {
893 goto cleanup;
894 }
1747 die(gettext("open: %s"), filename);
1748 }
1749 error = fstat64(fd, &buf);
1750 if (error == -1) {
1751 die(gettext("fstat: %s"), filename);
1752 } else if (!S_ISLOFIABLE(buf.st_mode)) {
1753 die(gettext("%s is not a regular file, "
1754 "block, or character device\n"),
1755 filename);
1756 } else if ((buf.st_size % DEV_BSIZE) != 0) {
1757 die(gettext("size of %s is not a multiple of %d\n"),
1758 filename, DEV_BSIZE);
1759 }
1760 (void) close(fd);
1761
1762 if (name_to_minor(filename) != 0) {
1763 die(gettext("cannot use %s on itself\n"), LOFI_DRIVER_NAME);
1764 }
1765 }
1766
1767 static boolean_t
1768 check_file_is_encrypted(const char *filename)
1769 {
1770 int fd;
1771 char buf[sizeof (lofi_crypto_magic)];
1772 int got;
1773 int rest = sizeof (lofi_crypto_magic);
1774
1775 fd = open64(filename, O_RDONLY);
1776 if (fd == -1)
1777 die(gettext("failed to open: %s"), filename);
1778
1779 if (lseek(fd, CRYOFF, SEEK_SET) != CRYOFF)
1780 die(gettext("failed to seek to offset 0x%lx in file %s"),
1781 CRYOFF, filename);
1782
1783 do {
1784 got = read(fd, buf + sizeof (lofi_crypto_magic) - rest, rest);
1785 if ((got == 0) || ((got == -1) && (errno != EINTR)))
1786 die(gettext("failed to read crypto header"
1787 " at offset 0x%lx in file %s"), CRYOFF, filename);
1788
1789 if (got > 0)
1790 rest -= got;
1791 } while (rest > 0);
1792
1793 while (close(fd) == -1) {
1794 if (errno != EINTR)
1795 die(gettext("failed to close file %s"), filename);
1796 }
1797
1798 return (strncmp(buf, lofi_crypto_magic,
1799 sizeof (lofi_crypto_magic)) == 0);
1800 }
1801
1802 static uint32_t
1803 convert_to_num(const char *str)
1804 {
1805 int len;
1806 uint32_t segsize, mult = 1;
1807
1808 len = strlen(str);
1809 if (len && isalpha(str[len - 1])) {
1810 switch (str[len - 1]) {
1811 case 'k':
1812 case 'K':
1813 mult = KILOBYTE;
1814 break;
1815 case 'b':
1816 case 'B':
1817 mult = BLOCK_SIZE;
1818 break;
1819 case 'm':
1820 case 'M':
1821 mult = MEGABYTE;
2044 * in which case the passphrase unlocks the token
2045 * If only the cipher is specified, reconfirm the passphrase
2046 * to ensure the user hasn't mis-entered it. Otherwise, the
2047 * token will enforce the token passphrase.
2048 */
2049 if (need_crypto) {
2050 CK_SESSION_HANDLE sess;
2051
2052 /* pick a cipher if none specified */
2053 if (cipher == NULL)
2054 cipher = DEFAULT_CIPHER;
2055
2056 if (!kernel_cipher_check(cipher))
2057 die(gettext(
2058 "use \"cryptoadm list -m\" to find available "
2059 "mechanisms\n"));
2060
2061 init_crypto(token, cipher, &sess);
2062
2063 if (cipher_only) {
2064 getkeyfromuser(cipher, &rkey, &rksz,
2065 !check_file_is_encrypted(filename));
2066 } else if (token != NULL) {
2067 getkeyfromtoken(sess, token, keyfile, cipher,
2068 &rkey, &rksz);
2069 } else {
2070 /* this also handles ephemeral keys */
2071 getkeyfromfile(keyfile, cipher, &rkey, &rksz);
2072 }
2073
2074 end_crypto(sess);
2075 }
2076
2077 /*
2078 * Now to the real work.
2079 */
2080 if (addflag)
2081 add_mapping(lfd, devicename, filename, cipher, rkey, rksz,
2082 rdflag);
2083 else if (compressflag)
2084 lofi_compress(&lfd, filename, compress_index, segsize);
2085 else if (uncompressflag)
|