summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorLaura Abbott <lauraa@codeaurora.org>2013-08-09 18:17:06 -0700
committerOlav Haugan <ohaugan@codeaurora.org>2016-10-08 10:43:20 -0700
commitfb25c8b683babfc18e583f634fb95a5fac7e12ef (patch)
tree51037161b1a2b97c4649f76c3f246c150109a6ee /arch
parent3ffe336b5e3673039568fabea7785ff066c32fca (diff)
msm: implement ARCH_RANDOM
Currently, the software random number generator is not initialized until relatively late in the boot process. Software that relies on random numbers early will not be reliable. Entropy sources are available early but not early enough for some use cases which means that moving the software random number generation earlier is not an option. As an alternate solution, implement the functions associated with CONFIG_ARCH_RANDOM. These functions currently make a call into trustzone to get reliable random numbers. The functions are disabled once the regular random number generator is sufficiently reliable. Change-Id: If40cfcb96b091fa26a28047c10a902287b26f6c1 Signed-off-by: Laura Abbott <lauraa@codeaurora.org> [ohaugan@codeaurora.org: Dropped Makefile from patch set] Signed-off-by: Olav Haugan <ohaugan@codeaurora.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/include/asm/archrandom.h20
-rw-r--r--arch/arm/mach-msm/early_random.c83
2 files changed, 103 insertions, 0 deletions
diff --git a/arch/arm/include/asm/archrandom.h b/arch/arm/include/asm/archrandom.h
new file mode 100644
index 000000000000..5530d450a098
--- /dev/null
+++ b/arch/arm/include/asm/archrandom.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef ARM_ASM_ARCHRANDOM_H
+#define ARM_ASM_ARCHRANDOM_H
+
+extern int arch_get_random_long(unsigned long *v);
+extern int arch_get_random_int(unsigned int *v);
+
+#endif
diff --git a/arch/arm/mach-msm/early_random.c b/arch/arm/mach-msm/early_random.c
new file mode 100644
index 000000000000..e315b86a4315
--- /dev/null
+++ b/arch/arm/mach-msm/early_random.c
@@ -0,0 +1,83 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+
+#include <mach/scm.h>
+
+#include <asm/io.h>
+#include <asm/cacheflush.h>
+
+#define TZ_SVC_CRYPTO 10
+#define PRNG_CMD_ID 0x01
+
+static int use_arch_random = 1;
+struct tz_prng_data {
+ uint8_t *out_buf;
+ uint32_t out_buf_sz;
+} __packed;
+
+DEFINE_SCM_BUFFER(common_scm_buf)
+DEFINE_MUTEX(arch_random_lock);
+#define RANDOM_BUFFER_SIZE PAGE_SIZE
+char random_buffer[RANDOM_BUFFER_SIZE] __aligned(PAGE_SIZE);
+
+int arch_get_random_common(void *v, size_t size)
+{
+ struct tz_prng_data data;
+ int ret;
+ u32 resp;
+
+ if (!use_arch_random)
+ return 0;
+
+ if (size > sizeof(random_buffer))
+ return 0;
+
+ mutex_lock(&arch_random_lock);
+ data.out_buf = (uint8_t *) virt_to_phys(random_buffer);
+ data.out_buf_sz = size;
+
+ ret = scm_call_noalloc(TZ_SVC_CRYPTO, PRNG_CMD_ID, &data,
+ sizeof(data), &resp, sizeof(resp),
+ common_scm_buf, SCM_BUFFER_SIZE(common_scm_buf));
+ if (!ret) {
+ dmac_inv_range(random_buffer, random_buffer +
+ RANDOM_BUFFER_SIZE);
+ outer_inv_range(
+ (unsigned long) virt_to_phys(random_buffer),
+ (unsigned long) virt_to_phys(random_buffer) +
+ RANDOM_BUFFER_SIZE);
+ memcpy(v, random_buffer, size);
+ }
+ mutex_unlock(&arch_random_lock);
+ return !ret;
+}
+
+int arch_get_random_long(unsigned long *v)
+{
+ return arch_get_random_common(v, sizeof(unsigned long));
+}
+
+int arch_get_random_int(unsigned int *v)
+{
+ return arch_get_random_common(v, sizeof(unsigned int));
+}
+
+int arch_random_init(void)
+{
+ use_arch_random = 0;
+
+ return 0;
+}
+module_init(arch_random_init);