Print this page
5857 add -o option to lofiadm


   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)