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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012 Joyent, Inc. All rights reserved.
25 *
26 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
27 * Copyright (c) 2014 Gary Mills
28 */
29
30 /*
31 * lofiadm - administer lofi(7d). Very simple, add and remove file<->device
32 * associations, and display status. All the ioctls are private between
33 * lofi and lofiadm, and so are very simple - device information is
34 * communicated via a minor number.
35 */
36
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/lofi.h>
40 #include <sys/stat.h>
41 #include <sys/sysmacros.h>
42 #include <netinet/in.h>
43 #include <stdio.h>
44 #include <fcntl.h>
45 #include <locale.h>
46 #include <string.h>
47 #include <strings.h>
51 #include <stropts.h>
52 #include <libdevinfo.h>
53 #include <libgen.h>
54 #include <ctype.h>
55 #include <dlfcn.h>
56 #include <limits.h>
57 #include <security/cryptoki.h>
58 #include <cryptoutil.h>
59 #include <sys/crypto/ioctl.h>
60 #include <sys/crypto/ioctladmin.h>
61 #include "utils.h"
62 #include <LzmaEnc.h>
63
64 /* Only need the IV len #defines out of these files, nothing else. */
65 #include <aes/aes_impl.h>
66 #include <des/des_impl.h>
67 #include <blowfish/blowfish_impl.h>
68
69 static const char USAGE[] =
70 "Usage: %s [-r] -a file [ device ]\n"
71 " %s [-r] -c crypto_algorithm -a file [device]\n"
72 " %s [-r] -c crypto_algorithm -k raw_key_file -a file [device]\n"
73 " %s [-r] -c crypto_algorithm -T [token]:[manuf]:[serial]:key "
74 "-a file [device]\n"
75 " %s [-r] -c crypto_algorithm -T [token]:[manuf]:[serial]:key "
76 "-k wrapped_key_file -a file [device]\n"
77 " %s [-r] -c crypto_algorithm -e -a file [device]\n"
78 " %s -d file | device\n"
79 " %s -C [gzip|gzip-6|gzip-9|lzma] [-s segment_size] file\n"
80 " %s -U file\n"
81 " %s [ file | device ]\n";
82
83 typedef struct token_spec {
84 char *name;
85 char *mfr;
86 char *serno;
87 char *key;
88 } token_spec_t;
89
90 typedef struct mech_alias {
91 char *alias;
818 copyfield(ti->key, FLD_LABEL);
819
820 /*
821 * If token specified and it only contains a key label, then
822 * search all tokens for the key, otherwise only those with
823 * matching name, mfr, and serno are used.
824 */
825 /*
826 * That's how we'd like it to be, however, if only the key label
827 * is specified, default to using softtoken. It's easier.
828 */
829 if (ti->name == NULL && ti->mfr == NULL && ti->serno == NULL)
830 ti->name = strdup(pkcs11_default_token());
831 return (ti);
832 }
833
834 /*
835 * PBE the passphrase into a raw key
836 */
837 static void
838 getkeyfromuser(mech_alias_t *cipher, char **raw_key, size_t *raw_key_sz)
839 {
840 CK_SESSION_HANDLE sess;
841 CK_RV rv;
842 char *pass = NULL;
843 size_t passlen = 0;
844 void *salt = NULL; /* don't use NULL, see note on salt below */
845 size_t saltlen = 0;
846 CK_KEY_TYPE ktype;
847 void *kvalue;
848 size_t klen;
849
850 /* did init_crypto find a slot that supports this cipher? */
851 if (cipher->slot == (CK_SLOT_ID)-1 || cipher->max_keysize == 0) {
852 rv = CKR_MECHANISM_INVALID;
853 goto cleanup;
854 }
855
856 rv = pkcs11_mech2keytype(cipher->type, &ktype);
857 if (rv != CKR_OK)
858 goto cleanup;
859
860 /*
861 * use the passphrase to generate a PBE PKCS#5 secret key and
862 * retrieve the raw key data to eventually pass it to the kernel;
863 */
864 rv = C_OpenSession(cipher->slot, CKF_SERIAL_SESSION, NULL, NULL, &sess);
865 if (rv != CKR_OK)
866 goto cleanup;
867
868 /* get user passphrase with 8 byte minimum */
869 if (pkcs11_get_pass(NULL, &pass, &passlen, MIN_PASSLEN, B_TRUE) < 0) {
870 die(gettext("passphrases do not match\n"));
871 }
872
873 /*
874 * salt should not be NULL, or else pkcs11_PasswdToKey() will
875 * complain about CKR_MECHANISM_PARAM_INVALID; the following is
876 * to make up for not having a salt until a proper one is used
877 */
878 salt = pass;
879 saltlen = passlen;
880
881 klen = cipher->max_keysize;
882 rv = pkcs11_PasswdToKey(sess, pass, passlen, salt, saltlen, ktype,
883 cipher->max_keysize, &kvalue, &klen);
884
885 (void) C_CloseSession(sess);
886
887 if (rv != CKR_OK) {
888 goto cleanup;
889 }
1803 const char *devicename = NULL;
1804 const char *filename = NULL;
1805 const char *algname = COMPRESS_ALGORITHM;
1806 int openflag;
1807 int minor;
1808 int compress_index;
1809 uint32_t segsize = SEGSIZE;
1810 static char *lofictl = "/dev/" LOFI_CTL_NAME;
1811 boolean_t force = B_FALSE;
1812 const char *pname;
1813 boolean_t errflag = B_FALSE;
1814 boolean_t addflag = B_FALSE;
1815 boolean_t rdflag = B_FALSE;
1816 boolean_t deleteflag = B_FALSE;
1817 boolean_t ephflag = B_FALSE;
1818 boolean_t compressflag = B_FALSE;
1819 boolean_t uncompressflag = B_FALSE;
1820 /* the next two work together for -c, -k, -T, -e options only */
1821 boolean_t need_crypto = B_FALSE; /* if any -c, -k, -T, -e */
1822 boolean_t cipher_only = B_TRUE; /* if -c only */
1823 const char *keyfile = NULL;
1824 mech_alias_t *cipher = NULL;
1825 token_spec_t *token = NULL;
1826 char *rkey = NULL;
1827 size_t rksz = 0;
1828 char realfilename[MAXPATHLEN];
1829
1830 pname = getpname(argv[0]);
1831
1832 (void) setlocale(LC_ALL, "");
1833 (void) textdomain(TEXT_DOMAIN);
1834
1835 while ((c = getopt(argc, argv, "a:c:Cd:efk:o:rs:T:U")) != EOF) {
1836 switch (c) {
1837 case 'a':
1838 addflag = B_TRUE;
1839 if ((filename = realpath(optarg, realfilename)) == NULL)
1840 die("%s", optarg);
1841 if (((argc - optind) > 0) && (*argv[optind] != '-')) {
1842 /* optional device */
1843 devicename = argv[optind];
1844 optind++;
1845 }
1846 break;
1847 case 'C':
1848 compressflag = B_TRUE;
1849 if (((argc - optind) > 1) && (*argv[optind] != '-')) {
1850 /* optional algorithm */
1851 algname = argv[optind];
1852 optind++;
1853 }
1854 check_algorithm_validity(algname, &compress_index);
1855 break;
1893 case 's':
1894 segsize = convert_to_num(optarg);
1895 if (segsize < DEV_BSIZE || !ISP2(segsize))
1896 die(gettext("segment size %s is invalid "
1897 "or not a multiple of minimum block "
1898 "size %ld\n"), optarg, DEV_BSIZE);
1899 break;
1900 case 'T':
1901 if ((token = parsetoken(optarg)) == NULL) {
1902 errflag = B_TRUE;
1903 warn(
1904 gettext("invalid token key specifier %s\n"),
1905 optarg);
1906 }
1907 need_crypto = B_TRUE;
1908 cipher_only = B_FALSE; /* need to unset cipher_only */
1909 break;
1910 case 'U':
1911 uncompressflag = B_TRUE;
1912 break;
1913 case '?':
1914 default:
1915 errflag = B_TRUE;
1916 break;
1917 }
1918 }
1919
1920 /* Check for mutually exclusive combinations of options */
1921 if (errflag ||
1922 (addflag && deleteflag) ||
1923 (rdflag && !addflag) ||
1924 (!addflag && need_crypto) ||
1925 ((compressflag || uncompressflag) && (addflag || deleteflag)))
1926 usage(pname);
1927
1928 /* ephemeral key, and key from either file or token are incompatible */
1929 if (ephflag && (keyfile != NULL || token != NULL)) {
1930 die(gettext("ephemeral key cannot be used with keyfile"
1931 " or token key\n"));
1932 }
1933
1934 /*
1935 * "-c" but no "-k", "-T", "-e", or "-T -k" means derive key from
1936 * command line passphrase
1937 */
1938
1939 switch (argc - optind) {
1940 case 0: /* no more args */
1941 if (compressflag || uncompressflag) /* needs filename */
1942 usage(pname);
1943 break;
1944 case 1:
2004 * in which case the passphrase unlocks the token
2005 * If only the cipher is specified, reconfirm the passphrase
2006 * to ensure the user hasn't mis-entered it. Otherwise, the
2007 * token will enforce the token passphrase.
2008 */
2009 if (need_crypto) {
2010 CK_SESSION_HANDLE sess;
2011
2012 /* pick a cipher if none specified */
2013 if (cipher == NULL)
2014 cipher = DEFAULT_CIPHER;
2015
2016 if (!kernel_cipher_check(cipher))
2017 die(gettext(
2018 "use \"cryptoadm list -m\" to find available "
2019 "mechanisms\n"));
2020
2021 init_crypto(token, cipher, &sess);
2022
2023 if (cipher_only) {
2024 getkeyfromuser(cipher, &rkey, &rksz);
2025 } else if (token != NULL) {
2026 getkeyfromtoken(sess, token, keyfile, cipher,
2027 &rkey, &rksz);
2028 } else {
2029 /* this also handles ephemeral keys */
2030 getkeyfromfile(keyfile, cipher, &rkey, &rksz);
2031 }
2032
2033 end_crypto(sess);
2034 }
2035
2036 /*
2037 * Now to the real work.
2038 */
2039 if (addflag)
2040 add_mapping(lfd, devicename, filename, cipher, rkey, rksz,
2041 rdflag);
2042 else if (compressflag)
2043 lofi_compress(&lfd, filename, compress_index, segsize);
2044 else if (uncompressflag)
|
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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012 Joyent, Inc. All rights reserved.
25 *
26 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
27 * Copyright (c) 2014 Gary Mills
28 * Copyright (c) 2016 Andrey Sokolov
29 */
30
31 /*
32 * lofiadm - administer lofi(7d). Very simple, add and remove file<->device
33 * associations, and display status. All the ioctls are private between
34 * lofi and lofiadm, and so are very simple - device information is
35 * communicated via a minor number.
36 */
37
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/lofi.h>
41 #include <sys/stat.h>
42 #include <sys/sysmacros.h>
43 #include <netinet/in.h>
44 #include <stdio.h>
45 #include <fcntl.h>
46 #include <locale.h>
47 #include <string.h>
48 #include <strings.h>
52 #include <stropts.h>
53 #include <libdevinfo.h>
54 #include <libgen.h>
55 #include <ctype.h>
56 #include <dlfcn.h>
57 #include <limits.h>
58 #include <security/cryptoki.h>
59 #include <cryptoutil.h>
60 #include <sys/crypto/ioctl.h>
61 #include <sys/crypto/ioctladmin.h>
62 #include "utils.h"
63 #include <LzmaEnc.h>
64
65 /* Only need the IV len #defines out of these files, nothing else. */
66 #include <aes/aes_impl.h>
67 #include <des/des_impl.h>
68 #include <blowfish/blowfish_impl.h>
69
70 static const char USAGE[] =
71 "Usage: %s [-r] -a file [ device ]\n"
72 " %s [-r] [-o] -c crypto_algorithm -a file [device]\n"
73 " %s [-r] -c crypto_algorithm -k raw_key_file -a file [device]\n"
74 " %s [-r] -c crypto_algorithm -T [token]:[manuf]:[serial]:key "
75 "-a file [device]\n"
76 " %s [-r] -c crypto_algorithm -T [token]:[manuf]:[serial]:key "
77 "-k wrapped_key_file -a file [device]\n"
78 " %s [-r] -c crypto_algorithm -e -a file [device]\n"
79 " %s -d file | device\n"
80 " %s -C [gzip|gzip-6|gzip-9|lzma] [-s segment_size] file\n"
81 " %s -U file\n"
82 " %s [ file | device ]\n";
83
84 typedef struct token_spec {
85 char *name;
86 char *mfr;
87 char *serno;
88 char *key;
89 } token_spec_t;
90
91 typedef struct mech_alias {
92 char *alias;
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 boolean_t with_confirmation)
841 {
842 CK_SESSION_HANDLE sess;
843 CK_RV rv;
844 char *pass = NULL;
845 size_t passlen = 0;
846 void *salt = NULL; /* don't use NULL, see note on salt below */
847 size_t saltlen = 0;
848 CK_KEY_TYPE ktype;
849 void *kvalue;
850 size_t klen;
851
852 /* did init_crypto find a slot that supports this cipher? */
853 if (cipher->slot == (CK_SLOT_ID)-1 || cipher->max_keysize == 0) {
854 rv = CKR_MECHANISM_INVALID;
855 goto cleanup;
856 }
857
858 rv = pkcs11_mech2keytype(cipher->type, &ktype);
859 if (rv != CKR_OK)
860 goto cleanup;
861
862 /*
863 * use the passphrase to generate a PBE PKCS#5 secret key and
864 * retrieve the raw key data to eventually pass it to the kernel;
865 */
866 rv = C_OpenSession(cipher->slot, CKF_SERIAL_SESSION, NULL, NULL, &sess);
867 if (rv != CKR_OK)
868 goto cleanup;
869
870 /* get user passphrase with 8 byte minimum */
871 if (pkcs11_get_pass(NULL, &pass, &passlen, MIN_PASSLEN,
872 with_confirmation) < 0) {
873 die(gettext("passphrases do not match\n"));
874 }
875
876 /*
877 * salt should not be NULL, or else pkcs11_PasswdToKey() will
878 * complain about CKR_MECHANISM_PARAM_INVALID; the following is
879 * to make up for not having a salt until a proper one is used
880 */
881 salt = pass;
882 saltlen = passlen;
883
884 klen = cipher->max_keysize;
885 rv = pkcs11_PasswdToKey(sess, pass, passlen, salt, saltlen, ktype,
886 cipher->max_keysize, &kvalue, &klen);
887
888 (void) C_CloseSession(sess);
889
890 if (rv != CKR_OK) {
891 goto cleanup;
892 }
1806 const char *devicename = NULL;
1807 const char *filename = NULL;
1808 const char *algname = COMPRESS_ALGORITHM;
1809 int openflag;
1810 int minor;
1811 int compress_index;
1812 uint32_t segsize = SEGSIZE;
1813 static char *lofictl = "/dev/" LOFI_CTL_NAME;
1814 boolean_t force = B_FALSE;
1815 const char *pname;
1816 boolean_t errflag = B_FALSE;
1817 boolean_t addflag = B_FALSE;
1818 boolean_t rdflag = B_FALSE;
1819 boolean_t deleteflag = B_FALSE;
1820 boolean_t ephflag = B_FALSE;
1821 boolean_t compressflag = B_FALSE;
1822 boolean_t uncompressflag = B_FALSE;
1823 /* the next two work together for -c, -k, -T, -e options only */
1824 boolean_t need_crypto = B_FALSE; /* if any -c, -k, -T, -e */
1825 boolean_t cipher_only = B_TRUE; /* if -c only */
1826 boolean_t with_confirmation = B_TRUE;
1827 const char *keyfile = NULL;
1828 mech_alias_t *cipher = NULL;
1829 token_spec_t *token = NULL;
1830 char *rkey = NULL;
1831 size_t rksz = 0;
1832 char realfilename[MAXPATHLEN];
1833
1834 pname = getpname(argv[0]);
1835
1836 (void) setlocale(LC_ALL, "");
1837 (void) textdomain(TEXT_DOMAIN);
1838
1839 while ((c = getopt(argc, argv, "a:c:Cd:efk:ors:T:U")) != EOF) {
1840 switch (c) {
1841 case 'a':
1842 addflag = B_TRUE;
1843 if ((filename = realpath(optarg, realfilename)) == NULL)
1844 die("%s", optarg);
1845 if (((argc - optind) > 0) && (*argv[optind] != '-')) {
1846 /* optional device */
1847 devicename = argv[optind];
1848 optind++;
1849 }
1850 break;
1851 case 'C':
1852 compressflag = B_TRUE;
1853 if (((argc - optind) > 1) && (*argv[optind] != '-')) {
1854 /* optional algorithm */
1855 algname = argv[optind];
1856 optind++;
1857 }
1858 check_algorithm_validity(algname, &compress_index);
1859 break;
1897 case 's':
1898 segsize = convert_to_num(optarg);
1899 if (segsize < DEV_BSIZE || !ISP2(segsize))
1900 die(gettext("segment size %s is invalid "
1901 "or not a multiple of minimum block "
1902 "size %ld\n"), optarg, DEV_BSIZE);
1903 break;
1904 case 'T':
1905 if ((token = parsetoken(optarg)) == NULL) {
1906 errflag = B_TRUE;
1907 warn(
1908 gettext("invalid token key specifier %s\n"),
1909 optarg);
1910 }
1911 need_crypto = B_TRUE;
1912 cipher_only = B_FALSE; /* need to unset cipher_only */
1913 break;
1914 case 'U':
1915 uncompressflag = B_TRUE;
1916 break;
1917 case 'o':
1918 with_confirmation = B_FALSE;
1919 break;
1920 case '?':
1921 default:
1922 errflag = B_TRUE;
1923 break;
1924 }
1925 }
1926
1927 /* Check for mutually exclusive combinations of options */
1928 if (errflag ||
1929 (addflag && deleteflag) ||
1930 (rdflag && !addflag) ||
1931 (!addflag && need_crypto) ||
1932 (!with_confirmation && (!cipher_only || !need_crypto)) ||
1933 ((compressflag || uncompressflag) && (addflag || deleteflag)))
1934 usage(pname);
1935
1936 /* ephemeral key, and key from either file or token are incompatible */
1937 if (ephflag && (keyfile != NULL || token != NULL)) {
1938 die(gettext("ephemeral key cannot be used with keyfile"
1939 " or token key\n"));
1940 }
1941
1942 /*
1943 * "-c" but no "-k", "-T", "-e", or "-T -k" means derive key from
1944 * command line passphrase
1945 */
1946
1947 switch (argc - optind) {
1948 case 0: /* no more args */
1949 if (compressflag || uncompressflag) /* needs filename */
1950 usage(pname);
1951 break;
1952 case 1:
2012 * in which case the passphrase unlocks the token
2013 * If only the cipher is specified, reconfirm the passphrase
2014 * to ensure the user hasn't mis-entered it. Otherwise, the
2015 * token will enforce the token passphrase.
2016 */
2017 if (need_crypto) {
2018 CK_SESSION_HANDLE sess;
2019
2020 /* pick a cipher if none specified */
2021 if (cipher == NULL)
2022 cipher = DEFAULT_CIPHER;
2023
2024 if (!kernel_cipher_check(cipher))
2025 die(gettext(
2026 "use \"cryptoadm list -m\" to find available "
2027 "mechanisms\n"));
2028
2029 init_crypto(token, cipher, &sess);
2030
2031 if (cipher_only) {
2032 getkeyfromuser(cipher, &rkey, &rksz, with_confirmation);
2033 } else if (token != NULL) {
2034 getkeyfromtoken(sess, token, keyfile, cipher,
2035 &rkey, &rksz);
2036 } else {
2037 /* this also handles ephemeral keys */
2038 getkeyfromfile(keyfile, cipher, &rkey, &rksz);
2039 }
2040
2041 end_crypto(sess);
2042 }
2043
2044 /*
2045 * Now to the real work.
2046 */
2047 if (addflag)
2048 add_mapping(lfd, devicename, filename, cipher, rkey, rksz,
2049 rdflag);
2050 else if (compressflag)
2051 lofi_compress(&lfd, filename, compress_index, segsize);
2052 else if (uncompressflag)
|