diff options
Diffstat (limited to 'fs/ecryptfs')
-rw-r--r-- | fs/ecryptfs/crypto.c | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index c9839df37c7d..18c78abba683 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c | |||
@@ -1721,6 +1721,98 @@ out: | |||
1721 | } | 1721 | } |
1722 | 1722 | ||
1723 | /** | 1723 | /** |
1724 | * ecryptfs_encrypt_filename - encrypt filename | ||
1725 | * | ||
1726 | * CBC-encrypts the filename. We do not want to encrypt the same | ||
1727 | * filename with the same key and IV, which may happen with hard | ||
1728 | * links, so we prepend random bits to each filename. | ||
1729 | * | ||
1730 | * Returns zero on success; non-zero otherwise | ||
1731 | */ | ||
1732 | static int | ||
1733 | ecryptfs_encrypt_filename(struct ecryptfs_filename *filename, | ||
1734 | struct ecryptfs_crypt_stat *crypt_stat, | ||
1735 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat) | ||
1736 | { | ||
1737 | int rc = 0; | ||
1738 | |||
1739 | filename->encrypted_filename = NULL; | ||
1740 | filename->encrypted_filename_size = 0; | ||
1741 | if ((crypt_stat && (crypt_stat->flags & ECRYPTFS_ENCFN_USE_MOUNT_FNEK)) | ||
1742 | || (mount_crypt_stat && (mount_crypt_stat->flags | ||
1743 | & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK))) { | ||
1744 | size_t packet_size; | ||
1745 | size_t remaining_bytes; | ||
1746 | |||
1747 | rc = ecryptfs_write_tag_70_packet( | ||
1748 | NULL, NULL, | ||
1749 | &filename->encrypted_filename_size, | ||
1750 | mount_crypt_stat, NULL, | ||
1751 | filename->filename_size); | ||
1752 | if (rc) { | ||
1753 | printk(KERN_ERR "%s: Error attempting to get packet " | ||
1754 | "size for tag 72; rc = [%d]\n", __func__, | ||
1755 | rc); | ||
1756 | filename->encrypted_filename_size = 0; | ||
1757 | goto out; | ||
1758 | } | ||
1759 | filename->encrypted_filename = | ||
1760 | kmalloc(filename->encrypted_filename_size, GFP_KERNEL); | ||
1761 | if (!filename->encrypted_filename) { | ||
1762 | printk(KERN_ERR "%s: Out of memory whilst attempting " | ||
1763 | "to kmalloc [%Zd] bytes\n", __func__, | ||
1764 | filename->encrypted_filename_size); | ||
1765 | rc = -ENOMEM; | ||
1766 | goto out; | ||
1767 | } | ||
1768 | remaining_bytes = filename->encrypted_filename_size; | ||
1769 | rc = ecryptfs_write_tag_70_packet(filename->encrypted_filename, | ||
1770 | &remaining_bytes, | ||
1771 | &packet_size, | ||
1772 | mount_crypt_stat, | ||
1773 | filename->filename, | ||
1774 | filename->filename_size); | ||
1775 | if (rc) { | ||
1776 | printk(KERN_ERR "%s: Error attempting to generate " | ||
1777 | "tag 70 packet; rc = [%d]\n", __func__, | ||
1778 | rc); | ||
1779 | kfree(filename->encrypted_filename); | ||
1780 | filename->encrypted_filename = NULL; | ||
1781 | filename->encrypted_filename_size = 0; | ||
1782 | goto out; | ||
1783 | } | ||
1784 | filename->encrypted_filename_size = packet_size; | ||
1785 | } else { | ||
1786 | printk(KERN_ERR "%s: No support for requested filename " | ||
1787 | "encryption method in this release\n", __func__); | ||
1788 | rc = -ENOTSUPP; | ||
1789 | goto out; | ||
1790 | } | ||
1791 | out: | ||
1792 | return rc; | ||
1793 | } | ||
1794 | |||
1795 | static int ecryptfs_copy_filename(char **copied_name, size_t *copied_name_size, | ||
1796 | const char *name, size_t name_size) | ||
1797 | { | ||
1798 | int rc = 0; | ||
1799 | |||
1800 | (*copied_name) = kmalloc((name_size + 2), GFP_KERNEL); | ||
1801 | if (!(*copied_name)) { | ||
1802 | rc = -ENOMEM; | ||
1803 | goto out; | ||
1804 | } | ||
1805 | memcpy((void *)(*copied_name), (void *)name, name_size); | ||
1806 | (*copied_name)[(name_size)] = '\0'; /* Only for convenience | ||
1807 | * in printing out the | ||
1808 | * string in debug | ||
1809 | * messages */ | ||
1810 | (*copied_name_size) = (name_size + 1); | ||
1811 | out: | ||
1812 | return rc; | ||
1813 | } | ||
1814 | |||
1815 | /** | ||
1724 | * ecryptfs_process_key_cipher - Perform key cipher initialization. | 1816 | * ecryptfs_process_key_cipher - Perform key cipher initialization. |
1725 | * @key_tfm: Crypto context for key material, set by this function | 1817 | * @key_tfm: Crypto context for key material, set by this function |
1726 | * @cipher_name: Name of the cipher | 1818 | * @cipher_name: Name of the cipher |
@@ -1911,3 +2003,344 @@ out: | |||
1911 | mutex_unlock(&key_tfm_list_mutex); | 2003 | mutex_unlock(&key_tfm_list_mutex); |
1912 | return rc; | 2004 | return rc; |
1913 | } | 2005 | } |
2006 | |||
2007 | /* 64 characters forming a 6-bit target field */ | ||
2008 | static unsigned char *portable_filename_chars = ("-.0123456789ABCD" | ||
2009 | "EFGHIJKLMNOPQRST" | ||
2010 | "UVWXYZabcdefghij" | ||
2011 | "klmnopqrstuvwxyz"); | ||
2012 | |||
2013 | /* We could either offset on every reverse map or just pad some 0x00's | ||
2014 | * at the front here */ | ||
2015 | static unsigned char filename_rev_map[] = { | ||
2016 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */ | ||
2017 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 15 */ | ||
2018 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 23 */ | ||
2019 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 31 */ | ||
2020 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 39 */ | ||
2021 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, /* 47 */ | ||
2022 | 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, /* 55 */ | ||
2023 | 0x0A, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 63 */ | ||
2024 | 0x00, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, /* 71 */ | ||
2025 | 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, /* 79 */ | ||
2026 | 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, /* 87 */ | ||
2027 | 0x23, 0x24, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, /* 95 */ | ||
2028 | 0x00, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, /* 103 */ | ||
2029 | 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, /* 111 */ | ||
2030 | 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, /* 119 */ | ||
2031 | 0x3D, 0x3E, 0x3F | ||
2032 | }; | ||
2033 | |||
2034 | /** | ||
2035 | * ecryptfs_encode_for_filename | ||
2036 | * @dst: Destination location for encoded filename | ||
2037 | * @dst_size: Size of the encoded filename in bytes | ||
2038 | * @src: Source location for the filename to encode | ||
2039 | * @src_size: Size of the source in bytes | ||
2040 | */ | ||
2041 | void ecryptfs_encode_for_filename(unsigned char *dst, size_t *dst_size, | ||
2042 | unsigned char *src, size_t src_size) | ||
2043 | { | ||
2044 | size_t num_blocks; | ||
2045 | size_t block_num = 0; | ||
2046 | size_t dst_offset = 0; | ||
2047 | unsigned char last_block[3]; | ||
2048 | |||
2049 | if (src_size == 0) { | ||
2050 | (*dst_size) = 0; | ||
2051 | goto out; | ||
2052 | } | ||
2053 | num_blocks = (src_size / 3); | ||
2054 | if ((src_size % 3) == 0) { | ||
2055 | memcpy(last_block, (&src[src_size - 3]), 3); | ||
2056 | } else { | ||
2057 | num_blocks++; | ||
2058 | last_block[2] = 0x00; | ||
2059 | switch (src_size % 3) { | ||
2060 | case 1: | ||
2061 | last_block[0] = src[src_size - 1]; | ||
2062 | last_block[1] = 0x00; | ||
2063 | break; | ||
2064 | case 2: | ||
2065 | last_block[0] = src[src_size - 2]; | ||
2066 | last_block[1] = src[src_size - 1]; | ||
2067 | } | ||
2068 | } | ||
2069 | (*dst_size) = (num_blocks * 4); | ||
2070 | if (!dst) | ||
2071 | goto out; | ||
2072 | while (block_num < num_blocks) { | ||
2073 | unsigned char *src_block; | ||
2074 | unsigned char dst_block[4]; | ||
2075 | |||
2076 | if (block_num == (num_blocks - 1)) | ||
2077 | src_block = last_block; | ||
2078 | else | ||
2079 | src_block = &src[block_num * 3]; | ||
2080 | dst_block[0] = ((src_block[0] >> 2) & 0x3F); | ||
2081 | dst_block[1] = (((src_block[0] << 4) & 0x30) | ||
2082 | | ((src_block[1] >> 4) & 0x0F)); | ||
2083 | dst_block[2] = (((src_block[1] << 2) & 0x3C) | ||
2084 | | ((src_block[2] >> 6) & 0x03)); | ||
2085 | dst_block[3] = (src_block[2] & 0x3F); | ||
2086 | dst[dst_offset++] = portable_filename_chars[dst_block[0]]; | ||
2087 | dst[dst_offset++] = portable_filename_chars[dst_block[1]]; | ||
2088 | dst[dst_offset++] = portable_filename_chars[dst_block[2]]; | ||
2089 | dst[dst_offset++] = portable_filename_chars[dst_block[3]]; | ||
2090 | block_num++; | ||
2091 | } | ||
2092 | out: | ||
2093 | return; | ||
2094 | } | ||
2095 | |||
2096 | int ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size, | ||
2097 | const unsigned char *src, size_t src_size) | ||
2098 | { | ||
2099 | u8 current_bit_offset = 0; | ||
2100 | size_t src_byte_offset = 0; | ||
2101 | size_t dst_byte_offset = 0; | ||
2102 | int rc = 0; | ||
2103 | |||
2104 | if (dst == NULL) { | ||
2105 | /* Not exact; conservatively long */ | ||
2106 | (*dst_size) = (((src_size + 1) * 3) / 4); | ||
2107 | goto out; | ||
2108 | } | ||
2109 | while (src_byte_offset < src_size) { | ||
2110 | unsigned char src_byte = | ||
2111 | filename_rev_map[(int)src[src_byte_offset]]; | ||
2112 | |||
2113 | switch (current_bit_offset) { | ||
2114 | case 0: | ||
2115 | dst[dst_byte_offset] = (src_byte << 2); | ||
2116 | current_bit_offset = 6; | ||
2117 | break; | ||
2118 | case 6: | ||
2119 | dst[dst_byte_offset++] |= (src_byte >> 4); | ||
2120 | dst[dst_byte_offset] = ((src_byte & 0xF) | ||
2121 | << 4); | ||
2122 | current_bit_offset = 4; | ||
2123 | break; | ||
2124 | case 4: | ||
2125 | dst[dst_byte_offset++] |= (src_byte >> 2); | ||
2126 | dst[dst_byte_offset] = (src_byte << 6); | ||
2127 | current_bit_offset = 2; | ||
2128 | break; | ||
2129 | case 2: | ||
2130 | dst[dst_byte_offset++] |= (src_byte); | ||
2131 | dst[dst_byte_offset] = 0; | ||
2132 | current_bit_offset = 0; | ||
2133 | break; | ||
2134 | } | ||
2135 | src_byte_offset++; | ||
2136 | } | ||
2137 | (*dst_size) = dst_byte_offset; | ||
2138 | out: | ||
2139 | return rc; | ||
2140 | } | ||
2141 | |||
2142 | /** | ||
2143 | * ecryptfs_encrypt_and_encode_filename - converts a plaintext file name to cipher text | ||
2144 | * @crypt_stat: The crypt_stat struct associated with the file anem to encode | ||
2145 | * @name: The plaintext name | ||
2146 | * @length: The length of the plaintext | ||
2147 | * @encoded_name: The encypted name | ||
2148 | * | ||
2149 | * Encrypts and encodes a filename into something that constitutes a | ||
2150 | * valid filename for a filesystem, with printable characters. | ||
2151 | * | ||
2152 | * We assume that we have a properly initialized crypto context, | ||
2153 | * pointed to by crypt_stat->tfm. | ||
2154 | * | ||
2155 | * Returns zero on success; non-zero on otherwise | ||
2156 | */ | ||
2157 | int ecryptfs_encrypt_and_encode_filename( | ||
2158 | char **encoded_name, | ||
2159 | size_t *encoded_name_size, | ||
2160 | struct ecryptfs_crypt_stat *crypt_stat, | ||
2161 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat, | ||
2162 | const char *name, size_t name_size) | ||
2163 | { | ||
2164 | size_t encoded_name_no_prefix_size; | ||
2165 | int rc = 0; | ||
2166 | |||
2167 | (*encoded_name) = NULL; | ||
2168 | (*encoded_name_size) = 0; | ||
2169 | if ((crypt_stat && (crypt_stat->flags & ECRYPTFS_ENCRYPT_FILENAMES)) | ||
2170 | || (mount_crypt_stat && (mount_crypt_stat->flags | ||
2171 | & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES))) { | ||
2172 | struct ecryptfs_filename *filename; | ||
2173 | |||
2174 | filename = kzalloc(sizeof(*filename), GFP_KERNEL); | ||
2175 | if (!filename) { | ||
2176 | printk(KERN_ERR "%s: Out of memory whilst attempting " | ||
2177 | "to kzalloc [%d] bytes\n", __func__, | ||
2178 | sizeof(*filename)); | ||
2179 | rc = -ENOMEM; | ||
2180 | goto out; | ||
2181 | } | ||
2182 | filename->filename = (char *)name; | ||
2183 | filename->filename_size = name_size; | ||
2184 | rc = ecryptfs_encrypt_filename(filename, crypt_stat, | ||
2185 | mount_crypt_stat); | ||
2186 | if (rc) { | ||
2187 | printk(KERN_ERR "%s: Error attempting to encrypt " | ||
2188 | "filename; rc = [%d]\n", __func__, rc); | ||
2189 | kfree(filename); | ||
2190 | goto out; | ||
2191 | } | ||
2192 | ecryptfs_encode_for_filename( | ||
2193 | NULL, &encoded_name_no_prefix_size, | ||
2194 | filename->encrypted_filename, | ||
2195 | filename->encrypted_filename_size); | ||
2196 | if ((crypt_stat && (crypt_stat->flags | ||
2197 | & ECRYPTFS_ENCFN_USE_MOUNT_FNEK)) | ||
2198 | || (mount_crypt_stat | ||
2199 | && (mount_crypt_stat->flags | ||
2200 | & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK))) | ||
2201 | (*encoded_name_size) = | ||
2202 | (ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE | ||
2203 | + encoded_name_no_prefix_size); | ||
2204 | else | ||
2205 | (*encoded_name_size) = | ||
2206 | (ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX_SIZE | ||
2207 | + encoded_name_no_prefix_size); | ||
2208 | (*encoded_name) = kmalloc((*encoded_name_size) + 1, GFP_KERNEL); | ||
2209 | if (!(*encoded_name)) { | ||
2210 | printk(KERN_ERR "%s: Out of memory whilst attempting " | ||
2211 | "to kzalloc [%d] bytes\n", __func__, | ||
2212 | (*encoded_name_size)); | ||
2213 | rc = -ENOMEM; | ||
2214 | kfree(filename->encrypted_filename); | ||
2215 | kfree(filename); | ||
2216 | goto out; | ||
2217 | } | ||
2218 | if ((crypt_stat && (crypt_stat->flags | ||
2219 | & ECRYPTFS_ENCFN_USE_MOUNT_FNEK)) | ||
2220 | || (mount_crypt_stat | ||
2221 | && (mount_crypt_stat->flags | ||
2222 | & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK))) { | ||
2223 | memcpy((*encoded_name), | ||
2224 | ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX, | ||
2225 | ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE); | ||
2226 | ecryptfs_encode_for_filename( | ||
2227 | ((*encoded_name) | ||
2228 | + ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE), | ||
2229 | &encoded_name_no_prefix_size, | ||
2230 | filename->encrypted_filename, | ||
2231 | filename->encrypted_filename_size); | ||
2232 | (*encoded_name_size) = | ||
2233 | (ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE | ||
2234 | + encoded_name_no_prefix_size); | ||
2235 | (*encoded_name)[(*encoded_name_size)] = '\0'; | ||
2236 | (*encoded_name_size)++; | ||
2237 | } else { | ||
2238 | rc = -ENOTSUPP; | ||
2239 | } | ||
2240 | if (rc) { | ||
2241 | printk(KERN_ERR "%s: Error attempting to encode " | ||
2242 | "encrypted filename; rc = [%d]\n", __func__, | ||
2243 | rc); | ||
2244 | kfree((*encoded_name)); | ||
2245 | (*encoded_name) = NULL; | ||
2246 | (*encoded_name_size) = 0; | ||
2247 | } | ||
2248 | kfree(filename->encrypted_filename); | ||
2249 | kfree(filename); | ||
2250 | } else { | ||
2251 | rc = ecryptfs_copy_filename(encoded_name, | ||
2252 | encoded_name_size, | ||
2253 | name, name_size); | ||
2254 | } | ||
2255 | out: | ||
2256 | return rc; | ||
2257 | } | ||
2258 | |||
2259 | /** | ||
2260 | * ecryptfs_decode_and_decrypt_filename - converts the encoded cipher text name to decoded plaintext | ||
2261 | * @plaintext_name: The plaintext name | ||
2262 | * @plaintext_name_size: The plaintext name size | ||
2263 | * @ecryptfs_dir_dentry: eCryptfs directory dentry | ||
2264 | * @name: The filename in cipher text | ||
2265 | * @name_size: The cipher text name size | ||
2266 | * | ||
2267 | * Decrypts and decodes the filename. | ||
2268 | * | ||
2269 | * Returns zero on error; non-zero otherwise | ||
2270 | */ | ||
2271 | int ecryptfs_decode_and_decrypt_filename(char **plaintext_name, | ||
2272 | size_t *plaintext_name_size, | ||
2273 | struct dentry *ecryptfs_dir_dentry, | ||
2274 | const char *name, size_t name_size) | ||
2275 | { | ||
2276 | char *decoded_name; | ||
2277 | size_t decoded_name_size; | ||
2278 | size_t packet_size; | ||
2279 | int rc = 0; | ||
2280 | |||
2281 | if ((name_size > ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE) | ||
2282 | && (strncmp(name, ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX, | ||
2283 | ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE) == 0)) { | ||
2284 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat = | ||
2285 | &ecryptfs_superblock_to_private( | ||
2286 | ecryptfs_dir_dentry->d_sb)->mount_crypt_stat; | ||
2287 | const char *orig_name = name; | ||
2288 | size_t orig_name_size = name_size; | ||
2289 | |||
2290 | name += ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE; | ||
2291 | name_size -= ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE; | ||
2292 | rc = ecryptfs_decode_from_filename(NULL, &decoded_name_size, | ||
2293 | name, name_size); | ||
2294 | if (rc) { | ||
2295 | printk(KERN_ERR "%s: Error attempting to decode " | ||
2296 | "filename; rc = [%d]\n", __func__, rc); | ||
2297 | rc = ecryptfs_copy_filename(plaintext_name, | ||
2298 | plaintext_name_size, | ||
2299 | orig_name, orig_name_size); | ||
2300 | goto out; | ||
2301 | } | ||
2302 | decoded_name = kmalloc(decoded_name_size, GFP_KERNEL); | ||
2303 | if (!decoded_name) { | ||
2304 | printk(KERN_ERR "%s: Out of memory whilst attempting " | ||
2305 | "to kmalloc [%Zd] bytes\n", __func__, | ||
2306 | decoded_name_size); | ||
2307 | rc = -ENOMEM; | ||
2308 | goto out; | ||
2309 | } | ||
2310 | rc = ecryptfs_decode_from_filename(decoded_name, | ||
2311 | &decoded_name_size, | ||
2312 | name, name_size); | ||
2313 | if (rc) { | ||
2314 | printk(KERN_ERR "%s: Error attempting to decode " | ||
2315 | "filename; rc = [%d]\n", __func__, rc); | ||
2316 | rc = ecryptfs_copy_filename(plaintext_name, | ||
2317 | plaintext_name_size, | ||
2318 | orig_name, orig_name_size); | ||
2319 | goto out_free; | ||
2320 | } | ||
2321 | rc = ecryptfs_parse_tag_70_packet(plaintext_name, | ||
2322 | plaintext_name_size, | ||
2323 | &packet_size, | ||
2324 | mount_crypt_stat, | ||
2325 | decoded_name, | ||
2326 | decoded_name_size); | ||
2327 | if (rc) { | ||
2328 | printk(KERN_INFO "%s: Could not parse tag 70 packet " | ||
2329 | "from filename; copying through filename " | ||
2330 | "as-is\n", __func__); | ||
2331 | rc = ecryptfs_copy_filename(plaintext_name, | ||
2332 | plaintext_name_size, | ||
2333 | orig_name, orig_name_size); | ||
2334 | goto out_free; | ||
2335 | } | ||
2336 | } else { | ||
2337 | rc = ecryptfs_copy_filename(plaintext_name, | ||
2338 | plaintext_name_size, | ||
2339 | name, name_size); | ||
2340 | goto out; | ||
2341 | } | ||
2342 | out_free: | ||
2343 | kfree(decoded_name); | ||
2344 | out: | ||
2345 | return rc; | ||
2346 | } | ||