Print this page
5857 lofiadm should ask passphrase once if the crypto is already set up
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Toomas Soome <tsoome@me.com>


 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)