drivers: crypto: ace_sha: add implementation of hardware based lib rand

This patch adds implementation of rand library based on hardware random
number generator of security subsystem in Exynos SOC.

This library includes:
- srand()  - used for seed hardware block
- rand()   - returns random number
- rand_r() - the same as above with given seed

which depends on CONFIG_EXYNOS_ACE_SHA and CONFIG_LIB_HW_RAND.

Signed-off-by: Przemyslaw Marczak <p.marczak@samsung.com>
cc: Akshay Saraswat <akshay.s@samsung.com>
cc: ARUN MANKUZHI <arun.m@samsung.com>
cc: Minkyu Kang <mk7.kang@samsung.com>
Cc: Michael Walle <michael@walle.cc>
Cc: Tom Rini <trini@ti.com>
Cc: Masahiro Yamada <yamada.m@jp.panasonic.com>
master
Przemyslaw Marczak 11 years ago committed by Tom Rini
parent 680d8f03ea
commit 0bd937248a
  1. 73
      drivers/crypto/ace_sha.c
  2. 8
      drivers/crypto/ace_sha.h

@ -5,10 +5,12 @@
* SPDX-License-Identifier: GPL-2.0+ * SPDX-License-Identifier: GPL-2.0+
*/ */
#include <common.h> #include <common.h>
#include "ace_sha.h"
#ifdef CONFIG_SHA_HW_ACCEL
#include <sha256.h> #include <sha256.h>
#include <sha1.h> #include <sha1.h>
#include <asm/errno.h> #include <asm/errno.h>
#include "ace_sha.h"
/* SHA1 value for the message of zero length */ /* SHA1 value for the message of zero length */
static const unsigned char sha1_digest_emptymsg[SHA1_SUM_LEN] = { static const unsigned char sha1_digest_emptymsg[SHA1_SUM_LEN] = {
@ -111,3 +113,72 @@ void hw_sha1(const unsigned char *pbuf, unsigned int buf_len,
if (ace_sha_hash_digest(pbuf, buf_len, pout, ACE_SHA_TYPE_SHA1)) if (ace_sha_hash_digest(pbuf, buf_len, pout, ACE_SHA_TYPE_SHA1))
debug("ACE was not setup properly or it is faulty\n"); debug("ACE was not setup properly or it is faulty\n");
} }
#endif /* CONFIG_SHA_HW_ACCEL */
#ifdef CONFIG_LIB_HW_RAND
static unsigned int seed_done;
void srand(unsigned int seed)
{
struct exynos_ace_sfr *reg =
(struct exynos_ace_sfr *)samsung_get_base_ace_sfr();
int i, status;
/* Seed data */
for (i = 0; i < ACE_HASH_PRNG_REG_NUM; i++)
writel(seed << i, &reg->hash_seed[i]);
/* Wait for seed setup done */
while (1) {
status = readl(&reg->hash_status);
if ((status & ACE_HASH_SEEDSETTING_MASK) ||
(status & ACE_HASH_PRNGERROR_MASK))
break;
}
seed_done = 1;
}
unsigned int rand(void)
{
struct exynos_ace_sfr *reg =
(struct exynos_ace_sfr *)samsung_get_base_ace_sfr();
int i, status;
unsigned int seed = (unsigned int)&status;
unsigned int ret = 0;
if (!seed_done)
srand(seed);
/* Start PRNG */
writel(ACE_HASH_ENGSEL_PRNG | ACE_HASH_STARTBIT_ON, &reg->hash_control);
/* Wait for PRNG done */
while (1) {
status = readl(&reg->hash_status);
if (status & ACE_HASH_PRNGDONE_MASK)
break;
if (status & ACE_HASH_PRNGERROR_MASK) {
seed_done = 0;
return 0;
}
}
/* Clear Done IRQ */
writel(ACE_HASH_PRNGDONE_MASK, &reg->hash_status);
/* Read a PRNG result */
for (i = 0; i < ACE_HASH_PRNG_REG_NUM; i++)
ret += readl(&reg->hash_prng[i]);
seed_done = 0;
return ret;
}
unsigned int rand_r(unsigned int *seedp)
{
srand(*seedp);
return rand();
}
#endif /* CONFIG_LIB_HW_RAND */

@ -72,9 +72,10 @@ struct exynos_ace_sfr {
unsigned char res12[0x30]; unsigned char res12[0x30];
unsigned int hash_result[8]; unsigned int hash_result[8];
unsigned char res13[0x20]; unsigned char res13[0x20];
unsigned int hash_seed[8]; unsigned int hash_seed[5];
unsigned int hash_prng[8]; unsigned char res14[12];
unsigned char res14[0x180]; unsigned int hash_prng[5];
unsigned char res15[0x18c];
unsigned int pka_sfr[5]; /* base + 0x700 */ unsigned int pka_sfr[5]; /* base + 0x700 */
}; };
@ -291,6 +292,7 @@ struct exynos_ace_sfr {
#define ACE_HASH_PRNGERROR_MASK (1 << 7) #define ACE_HASH_PRNGERROR_MASK (1 << 7)
#define ACE_HASH_PRNGERROR_OFF (0 << 7) #define ACE_HASH_PRNGERROR_OFF (0 << 7)
#define ACE_HASH_PRNGERROR_ON (1 << 7) #define ACE_HASH_PRNGERROR_ON (1 << 7)
#define ACE_HASH_PRNG_REG_NUM 5
#define ACE_SHA_TYPE_SHA1 1 #define ACE_SHA_TYPE_SHA1 1
#define ACE_SHA_TYPE_SHA256 2 #define ACE_SHA_TYPE_SHA256 2

Loading…
Cancel
Save