+
+struct kmem_cache *ecryptfs_key_tfm_cache;
+struct list_head key_tfm_list;
+struct mutex key_tfm_list_mutex;
+
+int ecryptfs_init_crypto(void)
+{
+ mutex_init(&key_tfm_list_mutex);
+ INIT_LIST_HEAD(&key_tfm_list);
+ return 0;
+}
+
+int ecryptfs_destroy_crypto(void)
+{
+ struct ecryptfs_key_tfm *key_tfm, *key_tfm_tmp;
+
+ mutex_lock(&key_tfm_list_mutex);
+ list_for_each_entry_safe(key_tfm, key_tfm_tmp, &key_tfm_list,
+ key_tfm_list) {
+ list_del(&key_tfm->key_tfm_list);
+ if (key_tfm->key_tfm)
+ crypto_free_blkcipher(key_tfm->key_tfm);
+ kmem_cache_free(ecryptfs_key_tfm_cache, key_tfm);
+ }
+ mutex_unlock(&key_tfm_list_mutex);
+ return 0;
+}
+
+int
+ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm **key_tfm, char *cipher_name,
+ size_t key_size)
+{
+ struct ecryptfs_key_tfm *tmp_tfm;
+ int rc = 0;
+
+ tmp_tfm = kmem_cache_alloc(ecryptfs_key_tfm_cache, GFP_KERNEL);
+ if (key_tfm != NULL)
+ (*key_tfm) = tmp_tfm;
+ if (!tmp_tfm) {
+ rc = -ENOMEM;
+ printk(KERN_ERR "Error attempting to allocate from "
+ "ecryptfs_key_tfm_cache\n");
+ goto out;
+ }
+ mutex_init(&tmp_tfm->key_tfm_mutex);
+ strncpy(tmp_tfm->cipher_name, cipher_name,
+ ECRYPTFS_MAX_CIPHER_NAME_SIZE);
+ tmp_tfm->key_size = key_size;
+ rc = ecryptfs_process_key_cipher(&tmp_tfm->key_tfm,
+ tmp_tfm->cipher_name,
+ &tmp_tfm->key_size);
+ if (rc) {
+ printk(KERN_ERR "Error attempting to initialize key TFM "
+ "cipher with name = [%s]; rc = [%d]\n",
+ tmp_tfm->cipher_name, rc);
+ kmem_cache_free(ecryptfs_key_tfm_cache, tmp_tfm);
+ if (key_tfm != NULL)
+ (*key_tfm) = NULL;
+ goto out;
+ }
+ mutex_lock(&key_tfm_list_mutex);
+ list_add(&tmp_tfm->key_tfm_list, &key_tfm_list);
+ mutex_unlock(&key_tfm_list_mutex);
+out:
+ return rc;
+}
+
+int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm,
+ struct mutex **tfm_mutex,
+ char *cipher_name)
+{
+ struct ecryptfs_key_tfm *key_tfm;
+ int rc = 0;
+
+ (*tfm) = NULL;
+ (*tfm_mutex) = NULL;
+ mutex_lock(&key_tfm_list_mutex);
+ list_for_each_entry(key_tfm, &key_tfm_list, key_tfm_list) {
+ if (strcmp(key_tfm->cipher_name, cipher_name) == 0) {
+ (*tfm) = key_tfm->key_tfm;
+ (*tfm_mutex) = &key_tfm->key_tfm_mutex;
+ mutex_unlock(&key_tfm_list_mutex);
+ goto out;
+ }
+ }
+ mutex_unlock(&key_tfm_list_mutex);
+ rc = ecryptfs_add_new_key_tfm(&key_tfm, cipher_name, 0);
+ if (rc) {
+ printk(KERN_ERR "Error adding new key_tfm to list; rc = [%d]\n",
+ rc);
+ goto out;
+ }
+ (*tfm) = key_tfm->key_tfm;
+ (*tfm_mutex) = &key_tfm->key_tfm_mutex;
+out:
+ return rc;
+}