diff options
Diffstat (limited to 'fs/ecryptfs/crypto.c')
-rw-r--r-- | fs/ecryptfs/crypto.c | 208 |
1 files changed, 174 insertions, 34 deletions
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 6ac630625b70..4f7d89591970 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c | |||
@@ -204,6 +204,8 @@ void | |||
204 | ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) | 204 | ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) |
205 | { | 205 | { |
206 | memset((void *)crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); | 206 | memset((void *)crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); |
207 | INIT_LIST_HEAD(&crypt_stat->keysig_list); | ||
208 | mutex_init(&crypt_stat->keysig_list_mutex); | ||
207 | mutex_init(&crypt_stat->cs_mutex); | 209 | mutex_init(&crypt_stat->cs_mutex); |
208 | mutex_init(&crypt_stat->cs_tfm_mutex); | 210 | mutex_init(&crypt_stat->cs_tfm_mutex); |
209 | mutex_init(&crypt_stat->cs_hash_tfm_mutex); | 211 | mutex_init(&crypt_stat->cs_hash_tfm_mutex); |
@@ -218,20 +220,41 @@ ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) | |||
218 | */ | 220 | */ |
219 | void ecryptfs_destruct_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) | 221 | void ecryptfs_destruct_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) |
220 | { | 222 | { |
223 | struct ecryptfs_key_sig *key_sig, *key_sig_tmp; | ||
224 | |||
221 | if (crypt_stat->tfm) | 225 | if (crypt_stat->tfm) |
222 | crypto_free_blkcipher(crypt_stat->tfm); | 226 | crypto_free_blkcipher(crypt_stat->tfm); |
223 | if (crypt_stat->hash_tfm) | 227 | if (crypt_stat->hash_tfm) |
224 | crypto_free_hash(crypt_stat->hash_tfm); | 228 | crypto_free_hash(crypt_stat->hash_tfm); |
229 | mutex_lock(&crypt_stat->keysig_list_mutex); | ||
230 | list_for_each_entry_safe(key_sig, key_sig_tmp, | ||
231 | &crypt_stat->keysig_list, crypt_stat_list) { | ||
232 | list_del(&key_sig->crypt_stat_list); | ||
233 | kmem_cache_free(ecryptfs_key_sig_cache, key_sig); | ||
234 | } | ||
235 | mutex_unlock(&crypt_stat->keysig_list_mutex); | ||
225 | memset(crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); | 236 | memset(crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); |
226 | } | 237 | } |
227 | 238 | ||
228 | void ecryptfs_destruct_mount_crypt_stat( | 239 | void ecryptfs_destruct_mount_crypt_stat( |
229 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat) | 240 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat) |
230 | { | 241 | { |
231 | if (mount_crypt_stat->global_auth_tok_key) | 242 | struct ecryptfs_global_auth_tok *auth_tok, *auth_tok_tmp; |
232 | key_put(mount_crypt_stat->global_auth_tok_key); | 243 | |
233 | if (mount_crypt_stat->global_key_tfm) | 244 | if (!(mount_crypt_stat->flags & ECRYPTFS_MOUNT_CRYPT_STAT_INITIALIZED)) |
234 | crypto_free_blkcipher(mount_crypt_stat->global_key_tfm); | 245 | return; |
246 | mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); | ||
247 | list_for_each_entry_safe(auth_tok, auth_tok_tmp, | ||
248 | &mount_crypt_stat->global_auth_tok_list, | ||
249 | mount_crypt_stat_list) { | ||
250 | list_del(&auth_tok->mount_crypt_stat_list); | ||
251 | mount_crypt_stat->num_global_auth_toks--; | ||
252 | if (auth_tok->global_auth_tok_key | ||
253 | && !(auth_tok->flags & ECRYPTFS_AUTH_TOK_INVALID)) | ||
254 | key_put(auth_tok->global_auth_tok_key); | ||
255 | kmem_cache_free(ecryptfs_global_auth_tok_cache, auth_tok); | ||
256 | } | ||
257 | mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); | ||
235 | memset(mount_crypt_stat, 0, sizeof(struct ecryptfs_mount_crypt_stat)); | 258 | memset(mount_crypt_stat, 0, sizeof(struct ecryptfs_mount_crypt_stat)); |
236 | } | 259 | } |
237 | 260 | ||
@@ -931,6 +954,30 @@ static void ecryptfs_copy_mount_wide_flags_to_inode_flags( | |||
931 | crypt_stat->flags |= ECRYPTFS_VIEW_AS_ENCRYPTED; | 954 | crypt_stat->flags |= ECRYPTFS_VIEW_AS_ENCRYPTED; |
932 | } | 955 | } |
933 | 956 | ||
957 | static int ecryptfs_copy_mount_wide_sigs_to_inode_sigs( | ||
958 | struct ecryptfs_crypt_stat *crypt_stat, | ||
959 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat) | ||
960 | { | ||
961 | struct ecryptfs_global_auth_tok *global_auth_tok; | ||
962 | int rc = 0; | ||
963 | |||
964 | mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); | ||
965 | list_for_each_entry(global_auth_tok, | ||
966 | &mount_crypt_stat->global_auth_tok_list, | ||
967 | mount_crypt_stat_list) { | ||
968 | rc = ecryptfs_add_keysig(crypt_stat, global_auth_tok->sig); | ||
969 | if (rc) { | ||
970 | printk(KERN_ERR "Error adding keysig; rc = [%d]\n", rc); | ||
971 | mutex_unlock( | ||
972 | &mount_crypt_stat->global_auth_tok_list_mutex); | ||
973 | goto out; | ||
974 | } | ||
975 | } | ||
976 | mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); | ||
977 | out: | ||
978 | return rc; | ||
979 | } | ||
980 | |||
934 | /** | 981 | /** |
935 | * ecryptfs_set_default_crypt_stat_vals | 982 | * ecryptfs_set_default_crypt_stat_vals |
936 | * @crypt_stat | 983 | * @crypt_stat |
@@ -973,46 +1020,44 @@ static void ecryptfs_set_default_crypt_stat_vals( | |||
973 | /* Associate an authentication token(s) with the file */ | 1020 | /* Associate an authentication token(s) with the file */ |
974 | int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry) | 1021 | int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry) |
975 | { | 1022 | { |
976 | int rc = 0; | ||
977 | struct ecryptfs_crypt_stat *crypt_stat = | 1023 | struct ecryptfs_crypt_stat *crypt_stat = |
978 | &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; | 1024 | &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; |
979 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat = | 1025 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat = |
980 | &ecryptfs_superblock_to_private( | 1026 | &ecryptfs_superblock_to_private( |
981 | ecryptfs_dentry->d_sb)->mount_crypt_stat; | 1027 | ecryptfs_dentry->d_sb)->mount_crypt_stat; |
982 | int cipher_name_len; | 1028 | int cipher_name_len; |
1029 | int rc = 0; | ||
983 | 1030 | ||
984 | ecryptfs_set_default_crypt_stat_vals(crypt_stat, mount_crypt_stat); | 1031 | ecryptfs_set_default_crypt_stat_vals(crypt_stat, mount_crypt_stat); |
985 | /* See if there are mount crypt options */ | 1032 | mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); |
986 | if (mount_crypt_stat->global_auth_tok) { | 1033 | BUG_ON(mount_crypt_stat->num_global_auth_toks == 0); |
987 | ecryptfs_printk(KERN_DEBUG, "Initializing context for new " | 1034 | mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); |
988 | "file using mount_crypt_stat\n"); | 1035 | crypt_stat->flags |= ECRYPTFS_ENCRYPTED; |
989 | crypt_stat->flags |= ECRYPTFS_ENCRYPTED; | 1036 | crypt_stat->flags |= ECRYPTFS_KEY_VALID; |
990 | crypt_stat->flags |= ECRYPTFS_KEY_VALID; | 1037 | ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat, |
991 | ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat, | 1038 | mount_crypt_stat); |
992 | mount_crypt_stat); | 1039 | rc = ecryptfs_copy_mount_wide_sigs_to_inode_sigs(crypt_stat, |
993 | memcpy(crypt_stat->keysigs[crypt_stat->num_keysigs++], | 1040 | mount_crypt_stat); |
994 | mount_crypt_stat->global_auth_tok_sig, | 1041 | if (rc) { |
995 | ECRYPTFS_SIG_SIZE_HEX); | 1042 | printk(KERN_ERR "Error attempting to copy mount-wide key sigs " |
996 | cipher_name_len = | 1043 | "to the inode key sigs; rc = [%d]\n", rc); |
997 | strlen(mount_crypt_stat->global_default_cipher_name); | 1044 | goto out; |
998 | memcpy(crypt_stat->cipher, | 1045 | } |
999 | mount_crypt_stat->global_default_cipher_name, | 1046 | cipher_name_len = |
1000 | cipher_name_len); | 1047 | strlen(mount_crypt_stat->global_default_cipher_name); |
1001 | crypt_stat->cipher[cipher_name_len] = '\0'; | 1048 | memcpy(crypt_stat->cipher, |
1002 | crypt_stat->key_size = | 1049 | mount_crypt_stat->global_default_cipher_name, |
1003 | mount_crypt_stat->global_default_cipher_key_size; | 1050 | cipher_name_len); |
1004 | ecryptfs_generate_new_key(crypt_stat); | 1051 | crypt_stat->cipher[cipher_name_len] = '\0'; |
1005 | } else | 1052 | crypt_stat->key_size = |
1006 | /* We should not encounter this scenario since we | 1053 | mount_crypt_stat->global_default_cipher_key_size; |
1007 | * should detect lack of global_auth_tok at mount time | 1054 | ecryptfs_generate_new_key(crypt_stat); |
1008 | * TODO: Applies to 0.1 release only; remove in future | ||
1009 | * release */ | ||
1010 | BUG(); | ||
1011 | rc = ecryptfs_init_crypt_ctx(crypt_stat); | 1055 | rc = ecryptfs_init_crypt_ctx(crypt_stat); |
1012 | if (rc) | 1056 | if (rc) |
1013 | ecryptfs_printk(KERN_ERR, "Error initializing cryptographic " | 1057 | ecryptfs_printk(KERN_ERR, "Error initializing cryptographic " |
1014 | "context for cipher [%s]: rc = [%d]\n", | 1058 | "context for cipher [%s]: rc = [%d]\n", |
1015 | crypt_stat->cipher, rc); | 1059 | crypt_stat->cipher, rc); |
1060 | out: | ||
1016 | return rc; | 1061 | return rc; |
1017 | } | 1062 | } |
1018 | 1063 | ||
@@ -1776,7 +1821,7 @@ out: | |||
1776 | } | 1821 | } |
1777 | 1822 | ||
1778 | /** | 1823 | /** |
1779 | * ecryptfs_process_cipher - Perform cipher initialization. | 1824 | * ecryptfs_process_key_cipher - Perform key cipher initialization. |
1780 | * @key_tfm: Crypto context for key material, set by this function | 1825 | * @key_tfm: Crypto context for key material, set by this function |
1781 | * @cipher_name: Name of the cipher | 1826 | * @cipher_name: Name of the cipher |
1782 | * @key_size: Size of the key in bytes | 1827 | * @key_size: Size of the key in bytes |
@@ -1786,8 +1831,8 @@ out: | |||
1786 | * event, regardless of whether this function succeeds for fails. | 1831 | * event, regardless of whether this function succeeds for fails. |
1787 | */ | 1832 | */ |
1788 | int | 1833 | int |
1789 | ecryptfs_process_cipher(struct crypto_blkcipher **key_tfm, char *cipher_name, | 1834 | ecryptfs_process_key_cipher(struct crypto_blkcipher **key_tfm, |
1790 | size_t *key_size) | 1835 | char *cipher_name, size_t *key_size) |
1791 | { | 1836 | { |
1792 | char dummy_key[ECRYPTFS_MAX_KEY_BYTES]; | 1837 | char dummy_key[ECRYPTFS_MAX_KEY_BYTES]; |
1793 | char *full_alg_name; | 1838 | char *full_alg_name; |
@@ -1829,3 +1874,98 @@ ecryptfs_process_cipher(struct crypto_blkcipher **key_tfm, char *cipher_name, | |||
1829 | out: | 1874 | out: |
1830 | return rc; | 1875 | return rc; |
1831 | } | 1876 | } |
1877 | |||
1878 | struct kmem_cache *ecryptfs_key_tfm_cache; | ||
1879 | struct list_head key_tfm_list; | ||
1880 | struct mutex key_tfm_list_mutex; | ||
1881 | |||
1882 | int ecryptfs_init_crypto(void) | ||
1883 | { | ||
1884 | mutex_init(&key_tfm_list_mutex); | ||
1885 | INIT_LIST_HEAD(&key_tfm_list); | ||
1886 | return 0; | ||
1887 | } | ||
1888 | |||
1889 | int ecryptfs_destruct_crypto(void) | ||
1890 | { | ||
1891 | struct ecryptfs_key_tfm *key_tfm, *key_tfm_tmp; | ||
1892 | |||
1893 | mutex_lock(&key_tfm_list_mutex); | ||
1894 | list_for_each_entry_safe(key_tfm, key_tfm_tmp, &key_tfm_list, | ||
1895 | key_tfm_list) { | ||
1896 | list_del(&key_tfm->key_tfm_list); | ||
1897 | if (key_tfm->key_tfm) | ||
1898 | crypto_free_blkcipher(key_tfm->key_tfm); | ||
1899 | kmem_cache_free(ecryptfs_key_tfm_cache, key_tfm); | ||
1900 | } | ||
1901 | mutex_unlock(&key_tfm_list_mutex); | ||
1902 | return 0; | ||
1903 | } | ||
1904 | |||
1905 | int | ||
1906 | ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm **key_tfm, char *cipher_name, | ||
1907 | size_t key_size) | ||
1908 | { | ||
1909 | struct ecryptfs_key_tfm *tmp_tfm; | ||
1910 | int rc = 0; | ||
1911 | |||
1912 | tmp_tfm = kmem_cache_alloc(ecryptfs_key_tfm_cache, GFP_KERNEL); | ||
1913 | if (key_tfm != NULL) | ||
1914 | (*key_tfm) = tmp_tfm; | ||
1915 | if (!tmp_tfm) { | ||
1916 | rc = -ENOMEM; | ||
1917 | printk(KERN_ERR "Error attempting to allocate from " | ||
1918 | "ecryptfs_key_tfm_cache\n"); | ||
1919 | goto out; | ||
1920 | } | ||
1921 | mutex_init(&tmp_tfm->key_tfm_mutex); | ||
1922 | strncpy(tmp_tfm->cipher_name, cipher_name, | ||
1923 | ECRYPTFS_MAX_CIPHER_NAME_SIZE); | ||
1924 | tmp_tfm->key_size = key_size; | ||
1925 | if ((rc = ecryptfs_process_key_cipher(&tmp_tfm->key_tfm, | ||
1926 | tmp_tfm->cipher_name, | ||
1927 | &tmp_tfm->key_size))) { | ||
1928 | printk(KERN_ERR "Error attempting to initialize key TFM " | ||
1929 | "cipher with name = [%s]; rc = [%d]\n", | ||
1930 | tmp_tfm->cipher_name, rc); | ||
1931 | kmem_cache_free(ecryptfs_key_tfm_cache, tmp_tfm); | ||
1932 | if (key_tfm != NULL) | ||
1933 | (*key_tfm) = NULL; | ||
1934 | goto out; | ||
1935 | } | ||
1936 | mutex_lock(&key_tfm_list_mutex); | ||
1937 | list_add(&tmp_tfm->key_tfm_list, &key_tfm_list); | ||
1938 | mutex_unlock(&key_tfm_list_mutex); | ||
1939 | out: | ||
1940 | return rc; | ||
1941 | } | ||
1942 | |||
1943 | int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm, | ||
1944 | struct mutex **tfm_mutex, | ||
1945 | char *cipher_name) | ||
1946 | { | ||
1947 | struct ecryptfs_key_tfm *key_tfm; | ||
1948 | int rc = 0; | ||
1949 | |||
1950 | (*tfm) = NULL; | ||
1951 | (*tfm_mutex) = NULL; | ||
1952 | mutex_lock(&key_tfm_list_mutex); | ||
1953 | list_for_each_entry(key_tfm, &key_tfm_list, key_tfm_list) { | ||
1954 | if (strcmp(key_tfm->cipher_name, cipher_name) == 0) { | ||
1955 | (*tfm) = key_tfm->key_tfm; | ||
1956 | (*tfm_mutex) = &key_tfm->key_tfm_mutex; | ||
1957 | mutex_unlock(&key_tfm_list_mutex); | ||
1958 | goto out; | ||
1959 | } | ||
1960 | } | ||
1961 | mutex_unlock(&key_tfm_list_mutex); | ||
1962 | if ((rc = ecryptfs_add_new_key_tfm(&key_tfm, cipher_name, 0))) { | ||
1963 | printk(KERN_ERR "Error adding new key_tfm to list; rc = [%d]\n", | ||
1964 | rc); | ||
1965 | goto out; | ||
1966 | } | ||
1967 | (*tfm) = key_tfm->key_tfm; | ||
1968 | (*tfm_mutex) = &key_tfm->key_tfm_mutex; | ||
1969 | out: | ||
1970 | return rc; | ||
1971 | } | ||