LCOV - code coverage report
Current view: top level - fs/crypto - fname.c (source / functions) Hit Total Coverage
Test: Real Lines: 12 139 8.6 %
Date: 2020-10-17 15:46:43 Functions: 0 10 0.0 %
Legend: Neither, QEMU, Real, Both Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * This contains functions for filename crypto management
       4                 :            :  *
       5                 :            :  * Copyright (C) 2015, Google, Inc.
       6                 :            :  * Copyright (C) 2015, Motorola Mobility
       7                 :            :  *
       8                 :            :  * Written by Uday Savagaonkar, 2014.
       9                 :            :  * Modified by Jaegeuk Kim, 2015.
      10                 :            :  *
      11                 :            :  * This has not yet undergone a rigorous security audit.
      12                 :            :  */
      13                 :            : 
      14                 :            : #include <linux/scatterlist.h>
      15                 :            : #include <crypto/skcipher.h>
      16                 :            : #include "fscrypt_private.h"
      17                 :            : 
      18                 :          0 : static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
      19                 :            : {
      20                 :          0 :         if (str->len == 1 && str->name[0] == '.')
      21                 :            :                 return true;
      22                 :            : 
      23                 :          0 :         if (str->len == 2 && str->name[0] == '.' && str->name[1] == '.')
      24                 :            :                 return true;
      25                 :            : 
      26                 :          0 :         return false;
      27                 :            : }
      28                 :            : 
      29                 :            : /**
      30                 :            :  * fname_encrypt() - encrypt a filename
      31                 :            :  *
      32                 :            :  * The output buffer must be at least as large as the input buffer.
      33                 :            :  * Any extra space is filled with NUL padding before encryption.
      34                 :            :  *
      35                 :            :  * Return: 0 on success, -errno on failure
      36                 :            :  */
      37                 :          0 : int fname_encrypt(struct inode *inode, const struct qstr *iname,
      38                 :            :                   u8 *out, unsigned int olen)
      39                 :            : {
      40                 :            :         struct skcipher_request *req = NULL;
      41                 :          0 :         DECLARE_CRYPTO_WAIT(wait);
      42                 :          0 :         struct fscrypt_info *ci = inode->i_crypt_info;
      43                 :          0 :         struct crypto_skcipher *tfm = ci->ci_ctfm;
      44                 :            :         union fscrypt_iv iv;
      45                 :            :         struct scatterlist sg;
      46                 :            :         int res;
      47                 :            : 
      48                 :            :         /*
      49                 :            :          * Copy the filename to the output buffer for encrypting in-place and
      50                 :            :          * pad it with the needed number of NUL bytes.
      51                 :            :          */
      52                 :          0 :         if (WARN_ON(olen < iname->len))
      53                 :            :                 return -ENOBUFS;
      54                 :          0 :         memcpy(out, iname->name, iname->len);
      55                 :          0 :         memset(out + iname->len, 0, olen - iname->len);
      56                 :            : 
      57                 :            :         /* Initialize the IV */
      58                 :          0 :         fscrypt_generate_iv(&iv, 0, ci);
      59                 :            : 
      60                 :            :         /* Set up the encryption request */
      61                 :          0 :         req = skcipher_request_alloc(tfm, GFP_NOFS);
      62                 :          0 :         if (!req)
      63                 :            :                 return -ENOMEM;
      64                 :            :         skcipher_request_set_callback(req,
      65                 :            :                         CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
      66                 :            :                         crypto_req_done, &wait);
      67                 :          0 :         sg_init_one(&sg, out, olen);
      68                 :            :         skcipher_request_set_crypt(req, &sg, &sg, olen, &iv);
      69                 :            : 
      70                 :            :         /* Do the encryption */
      71                 :          0 :         res = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
      72                 :            :         skcipher_request_free(req);
      73                 :          0 :         if (res < 0) {
      74                 :          0 :                 fscrypt_err(inode, "Filename encryption failed: %d", res);
      75                 :          0 :                 return res;
      76                 :            :         }
      77                 :            : 
      78                 :            :         return 0;
      79                 :            : }
      80                 :            : 
      81                 :            : /**
      82                 :            :  * fname_decrypt() - decrypt a filename
      83                 :            :  *
      84                 :            :  * The caller must have allocated sufficient memory for the @oname string.
      85                 :            :  *
      86                 :            :  * Return: 0 on success, -errno on failure
      87                 :            :  */
      88                 :          0 : static int fname_decrypt(struct inode *inode,
      89                 :            :                                 const struct fscrypt_str *iname,
      90                 :            :                                 struct fscrypt_str *oname)
      91                 :            : {
      92                 :            :         struct skcipher_request *req = NULL;
      93                 :          0 :         DECLARE_CRYPTO_WAIT(wait);
      94                 :            :         struct scatterlist src_sg, dst_sg;
      95                 :          0 :         struct fscrypt_info *ci = inode->i_crypt_info;
      96                 :          0 :         struct crypto_skcipher *tfm = ci->ci_ctfm;
      97                 :            :         union fscrypt_iv iv;
      98                 :            :         int res;
      99                 :            : 
     100                 :            :         /* Allocate request */
     101                 :          0 :         req = skcipher_request_alloc(tfm, GFP_NOFS);
     102                 :          0 :         if (!req)
     103                 :            :                 return -ENOMEM;
     104                 :            :         skcipher_request_set_callback(req,
     105                 :            :                 CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
     106                 :            :                 crypto_req_done, &wait);
     107                 :            : 
     108                 :            :         /* Initialize IV */
     109                 :          0 :         fscrypt_generate_iv(&iv, 0, ci);
     110                 :            : 
     111                 :            :         /* Create decryption request */
     112                 :          0 :         sg_init_one(&src_sg, iname->name, iname->len);
     113                 :          0 :         sg_init_one(&dst_sg, oname->name, oname->len);
     114                 :          0 :         skcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, &iv);
     115                 :          0 :         res = crypto_wait_req(crypto_skcipher_decrypt(req), &wait);
     116                 :            :         skcipher_request_free(req);
     117                 :          0 :         if (res < 0) {
     118                 :          0 :                 fscrypt_err(inode, "Filename decryption failed: %d", res);
     119                 :          0 :                 return res;
     120                 :            :         }
     121                 :            : 
     122                 :          0 :         oname->len = strnlen(oname->name, iname->len);
     123                 :          0 :         return 0;
     124                 :            : }
     125                 :            : 
     126                 :            : static const char lookup_table[65] =
     127                 :            :         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
     128                 :            : 
     129                 :            : #define BASE64_CHARS(nbytes)    DIV_ROUND_UP((nbytes) * 4, 3)
     130                 :            : 
     131                 :            : /**
     132                 :            :  * base64_encode() -
     133                 :            :  *
     134                 :            :  * Encodes the input string using characters from the set [A-Za-z0-9+,].
     135                 :            :  * The encoded string is roughly 4/3 times the size of the input string.
     136                 :            :  *
     137                 :            :  * Return: length of the encoded string
     138                 :            :  */
     139                 :          0 : static int base64_encode(const u8 *src, int len, char *dst)
     140                 :            : {
     141                 :            :         int i, bits = 0, ac = 0;
     142                 :            :         char *cp = dst;
     143                 :            : 
     144                 :          0 :         for (i = 0; i < len; i++) {
     145                 :          0 :                 ac += src[i] << bits;
     146                 :          0 :                 bits += 8;
     147                 :            :                 do {
     148                 :          0 :                         *cp++ = lookup_table[ac & 0x3f];
     149                 :          0 :                         ac >>= 6;
     150                 :          0 :                         bits -= 6;
     151                 :          0 :                 } while (bits >= 6);
     152                 :            :         }
     153                 :          0 :         if (bits)
     154                 :          0 :                 *cp++ = lookup_table[ac & 0x3f];
     155                 :          0 :         return cp - dst;
     156                 :            : }
     157                 :            : 
     158                 :          0 : static int base64_decode(const char *src, int len, u8 *dst)
     159                 :            : {
     160                 :            :         int i, bits = 0, ac = 0;
     161                 :            :         const char *p;
     162                 :            :         u8 *cp = dst;
     163                 :            : 
     164                 :          0 :         for (i = 0; i < len; i++) {
     165                 :          0 :                 p = strchr(lookup_table, src[i]);
     166                 :          0 :                 if (p == NULL || src[i] == 0)
     167                 :            :                         return -2;
     168                 :          0 :                 ac += (p - lookup_table) << bits;
     169                 :          0 :                 bits += 6;
     170                 :          0 :                 if (bits >= 8) {
     171                 :          0 :                         *cp++ = ac & 0xff;
     172                 :          0 :                         ac >>= 8;
     173                 :          0 :                         bits -= 8;
     174                 :            :                 }
     175                 :            :         }
     176                 :          0 :         if (ac)
     177                 :            :                 return -1;
     178                 :          0 :         return cp - dst;
     179                 :            : }
     180                 :            : 
     181                 :          0 : bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len,
     182                 :            :                                   u32 max_len, u32 *encrypted_len_ret)
     183                 :            : {
     184                 :          0 :         const struct fscrypt_info *ci = inode->i_crypt_info;
     185                 :          0 :         int padding = 4 << (fscrypt_policy_flags(&ci->ci_policy) &
     186                 :            :                             FSCRYPT_POLICY_FLAGS_PAD_MASK);
     187                 :            :         u32 encrypted_len;
     188                 :            : 
     189                 :          0 :         if (orig_len > max_len)
     190                 :            :                 return false;
     191                 :          0 :         encrypted_len = max(orig_len, (u32)FS_CRYPTO_BLOCK_SIZE);
     192                 :          0 :         encrypted_len = round_up(encrypted_len, padding);
     193                 :          0 :         *encrypted_len_ret = min(encrypted_len, max_len);
     194                 :          0 :         return true;
     195                 :            : }
     196                 :            : 
     197                 :            : /**
     198                 :            :  * fscrypt_fname_alloc_buffer - allocate a buffer for presented filenames
     199                 :            :  *
     200                 :            :  * Allocate a buffer that is large enough to hold any decrypted or encoded
     201                 :            :  * filename (null-terminated), for the given maximum encrypted filename length.
     202                 :            :  *
     203                 :            :  * Return: 0 on success, -errno on failure
     204                 :            :  */
     205                 :          0 : int fscrypt_fname_alloc_buffer(const struct inode *inode,
     206                 :            :                                u32 max_encrypted_len,
     207                 :            :                                struct fscrypt_str *crypto_str)
     208                 :            : {
     209                 :            :         const u32 max_encoded_len =
     210                 :            :                 max_t(u32, BASE64_CHARS(FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE),
     211                 :            :                       1 + BASE64_CHARS(sizeof(struct fscrypt_digested_name)));
     212                 :            :         u32 max_presented_len;
     213                 :            : 
     214                 :          0 :         max_presented_len = max(max_encoded_len, max_encrypted_len);
     215                 :            : 
     216                 :          0 :         crypto_str->name = kmalloc(max_presented_len + 1, GFP_NOFS);
     217                 :          0 :         if (!crypto_str->name)
     218                 :            :                 return -ENOMEM;
     219                 :          0 :         crypto_str->len = max_presented_len;
     220                 :          0 :         return 0;
     221                 :            : }
     222                 :            : EXPORT_SYMBOL(fscrypt_fname_alloc_buffer);
     223                 :            : 
     224                 :            : /**
     225                 :            :  * fscrypt_fname_free_buffer - free the buffer for presented filenames
     226                 :            :  *
     227                 :            :  * Free the buffer allocated by fscrypt_fname_alloc_buffer().
     228                 :            :  */
     229                 :          3 : void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str)
     230                 :            : {
     231                 :          3 :         if (!crypto_str)
     232                 :          3 :                 return;
     233                 :          3 :         kfree(crypto_str->name);
     234                 :          3 :         crypto_str->name = NULL;
     235                 :            : }
     236                 :            : EXPORT_SYMBOL(fscrypt_fname_free_buffer);
     237                 :            : 
     238                 :            : /**
     239                 :            :  * fscrypt_fname_disk_to_usr() - converts a filename from disk space to user
     240                 :            :  * space
     241                 :            :  *
     242                 :            :  * The caller must have allocated sufficient memory for the @oname string.
     243                 :            :  *
     244                 :            :  * If the key is available, we'll decrypt the disk name; otherwise, we'll encode
     245                 :            :  * it for presentation.  Short names are directly base64-encoded, while long
     246                 :            :  * names are encoded in fscrypt_digested_name format.
     247                 :            :  *
     248                 :            :  * Return: 0 on success, -errno on failure
     249                 :            :  */
     250                 :          0 : int fscrypt_fname_disk_to_usr(struct inode *inode,
     251                 :            :                         u32 hash, u32 minor_hash,
     252                 :            :                         const struct fscrypt_str *iname,
     253                 :            :                         struct fscrypt_str *oname)
     254                 :            : {
     255                 :          0 :         const struct qstr qname = FSTR_TO_QSTR(iname);
     256                 :            :         struct fscrypt_digested_name digested_name;
     257                 :            : 
     258                 :          0 :         if (fscrypt_is_dot_dotdot(&qname)) {
     259                 :          0 :                 oname->name[0] = '.';
     260                 :          0 :                 oname->name[iname->len - 1] = '.';
     261                 :          0 :                 oname->len = iname->len;
     262                 :          0 :                 return 0;
     263                 :            :         }
     264                 :            : 
     265                 :          0 :         if (iname->len < FS_CRYPTO_BLOCK_SIZE)
     266                 :            :                 return -EUCLEAN;
     267                 :            : 
     268                 :          0 :         if (fscrypt_has_encryption_key(inode))
     269                 :          0 :                 return fname_decrypt(inode, iname, oname);
     270                 :            : 
     271                 :          0 :         if (iname->len <= FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE) {
     272                 :          0 :                 oname->len = base64_encode(iname->name, iname->len,
     273                 :          0 :                                            oname->name);
     274                 :          0 :                 return 0;
     275                 :            :         }
     276                 :          0 :         if (hash) {
     277                 :          0 :                 digested_name.hash = hash;
     278                 :          0 :                 digested_name.minor_hash = minor_hash;
     279                 :            :         } else {
     280                 :          0 :                 digested_name.hash = 0;
     281                 :          0 :                 digested_name.minor_hash = 0;
     282                 :            :         }
     283                 :          0 :         memcpy(digested_name.digest,
     284                 :          0 :                FSCRYPT_FNAME_DIGEST(iname->name, iname->len),
     285                 :            :                FSCRYPT_FNAME_DIGEST_SIZE);
     286                 :          0 :         oname->name[0] = '_';
     287                 :          0 :         oname->len = 1 + base64_encode((const u8 *)&digested_name,
     288                 :          0 :                                        sizeof(digested_name), oname->name + 1);
     289                 :          0 :         return 0;
     290                 :            : }
     291                 :            : EXPORT_SYMBOL(fscrypt_fname_disk_to_usr);
     292                 :            : 
     293                 :            : /**
     294                 :            :  * fscrypt_setup_filename() - prepare to search a possibly encrypted directory
     295                 :            :  * @dir: the directory that will be searched
     296                 :            :  * @iname: the user-provided filename being searched for
     297                 :            :  * @lookup: 1 if we're allowed to proceed without the key because it's
     298                 :            :  *      ->lookup() or we're finding the dir_entry for deletion; 0 if we cannot
     299                 :            :  *      proceed without the key because we're going to create the dir_entry.
     300                 :            :  * @fname: the filename information to be filled in
     301                 :            :  *
     302                 :            :  * Given a user-provided filename @iname, this function sets @fname->disk_name
     303                 :            :  * to the name that would be stored in the on-disk directory entry, if possible.
     304                 :            :  * If the directory is unencrypted this is simply @iname.  Else, if we have the
     305                 :            :  * directory's encryption key, then @iname is the plaintext, so we encrypt it to
     306                 :            :  * get the disk_name.
     307                 :            :  *
     308                 :            :  * Else, for keyless @lookup operations, @iname is the presented ciphertext, so
     309                 :            :  * we decode it to get either the ciphertext disk_name (for short names) or the
     310                 :            :  * fscrypt_digested_name (for long names).  Non-@lookup operations will be
     311                 :            :  * impossible in this case, so we fail them with ENOKEY.
     312                 :            :  *
     313                 :            :  * If successful, fscrypt_free_filename() must be called later to clean up.
     314                 :            :  *
     315                 :            :  * Return: 0 on success, -errno on failure
     316                 :            :  */
     317                 :          3 : int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
     318                 :            :                               int lookup, struct fscrypt_name *fname)
     319                 :            : {
     320                 :            :         int ret;
     321                 :            :         int digested;
     322                 :            : 
     323                 :          3 :         memset(fname, 0, sizeof(struct fscrypt_name));
     324                 :          3 :         fname->usr_fname = iname;
     325                 :            : 
     326                 :          3 :         if (!IS_ENCRYPTED(dir) || fscrypt_is_dot_dotdot(iname)) {
     327                 :          3 :                 fname->disk_name.name = (unsigned char *)iname->name;
     328                 :          3 :                 fname->disk_name.len = iname->len;
     329                 :          3 :                 return 0;
     330                 :            :         }
     331                 :          0 :         ret = fscrypt_get_encryption_info(dir);
     332                 :          0 :         if (ret)
     333                 :            :                 return ret;
     334                 :            : 
     335                 :          0 :         if (fscrypt_has_encryption_key(dir)) {
     336                 :          0 :                 if (!fscrypt_fname_encrypted_size(dir, iname->len,
     337                 :          0 :                                                   dir->i_sb->s_cop->max_namelen,
     338                 :            :                                                   &fname->crypto_buf.len))
     339                 :            :                         return -ENAMETOOLONG;
     340                 :          0 :                 fname->crypto_buf.name = kmalloc(fname->crypto_buf.len,
     341                 :            :                                                  GFP_NOFS);
     342                 :          0 :                 if (!fname->crypto_buf.name)
     343                 :            :                         return -ENOMEM;
     344                 :            : 
     345                 :          0 :                 ret = fname_encrypt(dir, iname, fname->crypto_buf.name,
     346                 :            :                                     fname->crypto_buf.len);
     347                 :          0 :                 if (ret)
     348                 :            :                         goto errout;
     349                 :          0 :                 fname->disk_name.name = fname->crypto_buf.name;
     350                 :          0 :                 fname->disk_name.len = fname->crypto_buf.len;
     351                 :          0 :                 return 0;
     352                 :            :         }
     353                 :          0 :         if (!lookup)
     354                 :            :                 return -ENOKEY;
     355                 :          0 :         fname->is_ciphertext_name = true;
     356                 :            : 
     357                 :            :         /*
     358                 :            :          * We don't have the key and we are doing a lookup; decode the
     359                 :            :          * user-supplied name
     360                 :            :          */
     361                 :          0 :         if (iname->name[0] == '_') {
     362                 :          0 :                 if (iname->len !=
     363                 :            :                     1 + BASE64_CHARS(sizeof(struct fscrypt_digested_name)))
     364                 :            :                         return -ENOENT;
     365                 :            :                 digested = 1;
     366                 :            :         } else {
     367                 :          0 :                 if (iname->len >
     368                 :            :                     BASE64_CHARS(FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE))
     369                 :            :                         return -ENOENT;
     370                 :            :                 digested = 0;
     371                 :            :         }
     372                 :            : 
     373                 :          0 :         fname->crypto_buf.name =
     374                 :            :                 kmalloc(max_t(size_t, FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE,
     375                 :            :                               sizeof(struct fscrypt_digested_name)),
     376                 :            :                         GFP_KERNEL);
     377                 :          0 :         if (fname->crypto_buf.name == NULL)
     378                 :            :                 return -ENOMEM;
     379                 :            : 
     380                 :          0 :         ret = base64_decode(iname->name + digested, iname->len - digested,
     381                 :            :                             fname->crypto_buf.name);
     382                 :          0 :         if (ret < 0) {
     383                 :            :                 ret = -ENOENT;
     384                 :            :                 goto errout;
     385                 :            :         }
     386                 :          0 :         fname->crypto_buf.len = ret;
     387                 :          0 :         if (digested) {
     388                 :          0 :                 const struct fscrypt_digested_name *n =
     389                 :            :                         (const void *)fname->crypto_buf.name;
     390                 :          0 :                 fname->hash = n->hash;
     391                 :          0 :                 fname->minor_hash = n->minor_hash;
     392                 :            :         } else {
     393                 :          0 :                 fname->disk_name.name = fname->crypto_buf.name;
     394                 :          0 :                 fname->disk_name.len = fname->crypto_buf.len;
     395                 :            :         }
     396                 :            :         return 0;
     397                 :            : 
     398                 :            : errout:
     399                 :          0 :         kfree(fname->crypto_buf.name);
     400                 :          0 :         return ret;
     401                 :            : }
     402                 :            : EXPORT_SYMBOL(fscrypt_setup_filename);
    

Generated by: LCOV version 1.14