aboutsummaryrefslogtreecommitdiffstats
path: root/security/smc/tf_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/smc/tf_device.c')
-rw-r--r--security/smc/tf_device.c233
1 files changed, 175 insertions, 58 deletions
diff --git a/security/smc/tf_device.c b/security/smc/tf_device.c
index 7c2c623..fcd09e3 100644
--- a/security/smc/tf_device.c
+++ b/security/smc/tf_device.c
@@ -27,9 +27,7 @@
#include <linux/syscore_ops.h>
#include <linux/vmalloc.h>
#include <linux/signal.h>
-#ifdef CONFIG_ANDROID
#include <linux/device.h>
-#endif
#include "tf_protocol.h"
#include "tf_defs.h"
@@ -40,6 +38,9 @@
#include <plat/cpu.h>
#include "tf_zebra.h"
#endif
+#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
+#include "tf_crypto.h"
+#endif
#include "s_version.h"
@@ -129,10 +130,29 @@ MODULE_PARM_DESC(soft_interrupt,
"The softint interrupt line used by the Secure world");
#endif
-#ifdef CONFIG_ANDROID
-static struct class *tf_class;
+#ifdef CONFIG_TF_DRIVER_DEBUG_SUPPORT
+unsigned tf_debug_level = UINT_MAX;
+module_param_named(debug, tf_debug_level, uint, 0644);
+#endif
+
+#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
+char *tf_integrity_hmac_sha256_expected_value;
+module_param_named(hmac_sha256, tf_integrity_hmac_sha256_expected_value,
+ charp, 0444);
+
+#ifdef CONFIG_TF_DRIVER_FAULT_INJECTION
+unsigned tf_fault_injection_mask;
+module_param_named(fault, tf_fault_injection_mask, uint, 0644);
+#endif
+
+int tf_self_test_blkcipher_align;
+module_param_named(post_align, tf_self_test_blkcipher_align, int, 0644);
+int tf_self_test_blkcipher_use_vmalloc;
+module_param_named(post_vmalloc, tf_self_test_blkcipher_use_vmalloc, int, 0644);
#endif
+static struct class *tf_class;
+
/*----------------------------------------------------------------------------
* Global Variables
*----------------------------------------------------------------------------*/
@@ -163,42 +183,114 @@ struct tf_device *tf_get_device(void)
}
/*
- * displays the driver stats
+ * sysfs entries
*/
-static ssize_t kobject_show(struct kobject *kobj,
- struct attribute *attribute, char *buf)
-{
- struct tf_device_stats *dev_stats = &g_tf_dev.stats;
- u32 pages_allocated;
- u32 pages_locked;
- u32 memories_allocated;
+struct tf_sysfs_entry {
+ struct attribute attr;
+ ssize_t (*show)(struct tf_device *, char *);
+ ssize_t (*store)(struct tf_device *, const char *, size_t);
+};
- memories_allocated =
- atomic_read(&(dev_stats->stat_memories_allocated));
- pages_allocated =
- atomic_read(&(dev_stats->stat_pages_allocated));
- pages_locked = atomic_read(&(dev_stats->stat_pages_locked));
+/*
+ * sysfs entry showing allocation stats
+ */
+static ssize_t info_show(struct tf_device *dev, char *buf)
+{
+ struct tf_device_stats *dev_stats = &dev->stats;
- /*
- * AFY: could we add the number of context switches (call to the SMI
- * instruction)
- */
return snprintf(buf, PAGE_SIZE,
"stat.memories.allocated: %d\n"
"stat.pages.allocated: %d\n"
"stat.pages.locked: %d\n",
- memories_allocated,
- pages_allocated,
- pages_locked);
+ atomic_read(&dev_stats->stat_memories_allocated),
+ atomic_read(&dev_stats->stat_pages_allocated),
+ atomic_read(&dev_stats->stat_pages_locked));
+}
+static struct tf_sysfs_entry tf_info_entry = __ATTR_RO(info);
+
+#ifdef CONFIG_TF_ZEBRA
+/*
+ * sysfs entry showing whether secure world is up and running
+ */
+static ssize_t tf_started_show(struct tf_device *dev, char *buf)
+{
+ int tf_started = test_bit(TF_COMM_FLAG_PA_AVAILABLE,
+ &dev->sm.flags);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", tf_started ? "yes" : "no");
+}
+static struct tf_sysfs_entry tf_started_entry =
+ __ATTR_RO(tf_started);
+
+static ssize_t workspace_addr_show(struct tf_device *dev, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "0x%08x\n", dev->workspace_addr);
+}
+static struct tf_sysfs_entry tf_workspace_addr_entry =
+ __ATTR_RO(workspace_addr);
+
+static ssize_t workspace_size_show(struct tf_device *dev, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "0x%08x\n", dev->workspace_size);
+}
+static struct tf_sysfs_entry tf_workspace_size_entry =
+ __ATTR_RO(workspace_size);
+#endif
+
+static ssize_t tf_attr_show(struct kobject *kobj, struct attribute *attr,
+ char *page)
+{
+ struct tf_sysfs_entry *entry = container_of(attr, struct tf_sysfs_entry,
+ attr);
+ struct tf_device *dev = container_of(kobj, struct tf_device, kobj);
+
+ if (!entry->show)
+ return -EIO;
+
+ return entry->show(dev, page);
+}
+
+static ssize_t tf_attr_store(struct kobject *kobj, struct attribute *attr,
+ const char *page, size_t length)
+{
+ struct tf_sysfs_entry *entry = container_of(attr, struct tf_sysfs_entry,
+ attr);
+ struct tf_device *dev = container_of(kobj, struct tf_device, kobj);
+
+ if (!entry->store)
+ return -EIO;
+
+ return entry->store(dev, page, length);
}
-static const struct sysfs_ops kobj_sysfs_operations = {
- .show = kobject_show,
+static void tf_kobj_release(struct kobject *kobj) {}
+
+static struct attribute *tf_default_attrs[] = {
+ &tf_info_entry.attr,
+#ifdef CONFIG_TF_ZEBRA
+ &tf_started_entry.attr,
+ &tf_workspace_addr_entry.attr,
+ &tf_workspace_size_entry.attr,
+#endif
+ NULL,
+};
+static const struct sysfs_ops tf_sysfs_ops = {
+ .show = tf_attr_show,
+ .store = tf_attr_store,
+};
+static struct kobj_type tf_ktype = {
+ .release = tf_kobj_release,
+ .sysfs_ops = &tf_sysfs_ops,
+ .default_attrs = tf_default_attrs
};
/*----------------------------------------------------------------------------*/
+#if defined(MODULE) && defined(CONFIG_TF_ZEBRA)
+static char *smc_mem;
+module_param(smc_mem, charp, S_IRUGO);
+#endif
static const struct syscore_ops g_tf_syscore_ops = {
.shutdown = tf_device_shutdown,
.suspend = tf_device_suspend,
@@ -212,7 +304,6 @@ static int __init tf_device_register(void)
{
int error;
struct tf_device *dev = &g_tf_dev;
- struct tf_device_stats *dev_stats = &dev->stats;
dprintk(KERN_INFO "tf_device_register()\n");
@@ -227,21 +318,33 @@ static int __init tf_device_register(void)
INIT_LIST_HEAD(&dev->connection_list);
spin_lock_init(&dev->connection_list_lock);
- /* register the sysfs object driver stats */
- dev_stats->kobj_type.sysfs_ops = &kobj_sysfs_operations;
+#if defined(MODULE) && defined(CONFIG_TF_ZEBRA)
+ error = (*tf_comm_early_init)();
+ if (error)
+ goto module_early_init_failed;
+
+ error = tf_device_mshield_init(smc_mem);
+ if (error)
+ goto mshield_init_failed;
+
+#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
+ error = tf_crypto_hmac_module_init();
+ if (error)
+ goto hmac_init_failed;
- dev_stats->kobj_stat_attribute.name = "info";
- dev_stats->kobj_stat_attribute.mode = S_IRUGO;
- dev_stats->kobj_attribute_list[0] =
- &dev_stats->kobj_stat_attribute;
+ error = tf_self_test_register_device();
+ if (error)
+ goto self_test_register_device_failed;
+#endif
+#endif
- dev_stats->kobj_type.default_attrs =
- dev_stats->kobj_attribute_list,
- error = kobject_init_and_add(&(dev_stats->kobj),
- &(dev_stats->kobj_type), NULL, "%s",
+ /* register the sysfs object driver stats */
+ error = kobject_init_and_add(&dev->kobj, &tf_ktype, NULL, "%s",
TF_DEVICE_BASE_NAME);
if (error) {
- kobject_put(&dev_stats->kobj);
+ printk(KERN_ERR "tf_device_register(): "
+ "kobject_init_and_add failed (error %d)!\n", error);
+ kobject_put(&dev->kobj);
goto kobject_init_and_add_failed;
}
@@ -285,12 +388,22 @@ static int __init tf_device_register(void)
goto init_failed;
}
-#ifdef CONFIG_ANDROID
+#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
+ error = tf_self_test_post_init(&(dev_stats->kobj));
+ /* N.B. error > 0 indicates a POST failure, which will not
+ prevent the module from loading. */
+ if (error < 0) {
+ dprintk(KERN_ERR "tf_device_register(): "
+ "tf_self_test_post_vectors failed (error %d)!\n",
+ error);
+ goto post_failed;
+ }
+#endif
+
tf_class = class_create(THIS_MODULE, TF_DEVICE_BASE_NAME);
device_create(tf_class, NULL,
dev->dev_number,
NULL, TF_DEVICE_BASE_NAME);
-#endif
#ifdef CONFIG_TF_ZEBRA
/*
@@ -298,11 +411,10 @@ static int __init tf_device_register(void)
*/
error = tf_ctrl_device_register();
if (error)
- goto init_failed;
+ goto ctrl_failed;
#endif
-#ifdef CONFIG_BENCH_SECURE_CYCLE
- run_bogo_mips();
+#ifdef CONFIG_TF_DRIVER_DEBUG_SUPPORT
address_cache_property((unsigned long) &tf_device_register);
#endif
/*
@@ -315,6 +427,13 @@ static int __init tf_device_register(void)
/*
* Error: undo all operations in the reverse order
*/
+#ifdef CONFIG_TF_ZEBRA
+ctrl_failed:
+#endif
+#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
+ tf_self_test_post_exit();
+post_failed:
+#endif
init_failed:
cdev_del(&dev->cdev);
cdev_add_failed:
@@ -322,8 +441,19 @@ cdev_add_failed:
register_chrdev_region_failed:
unregister_syscore_ops((struct syscore_ops *)&g_tf_syscore_ops);
kobject_init_and_add_failed:
- kobject_del(&g_tf_dev.stats.kobj);
-
+ kobject_del(&g_tf_dev.kobj);
+
+#if defined(MODULE) && defined(CONFIG_TF_ZEBRA)
+#ifdef CONFIG_TF_DRIVER_CRYPTO_FIPS
+ tf_self_test_unregister_device();
+self_test_register_device_failed:
+ tf_crypto_hmac_module_exit();
+hmac_init_failed:
+#endif
+ tf_device_mshield_exit();
+mshield_init_failed:
+module_early_init_failed:
+#endif
dprintk(KERN_INFO "tf_device_register(): Failure (error %d)\n",
error);
return error;
@@ -349,19 +479,6 @@ static int tf_device_open(struct inode *inode, struct file *file)
goto error;
}
-#ifndef CONFIG_ANDROID
- /*
- * Check file flags. We only autthorize the O_RDWR access
- */
- if (file->f_flags != O_RDWR) {
- dprintk(KERN_ERR "tf_device_open(%p): "
- "Invalid access mode %u\n",
- file, file->f_flags);
- error = -EACCES;
- goto error;
- }
-#endif
-
/*
* Open a new connection.
*/