summaryrefslogtreecommitdiff
path: root/drivers/crypto/ux500/hash/hash_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/crypto/ux500/hash/hash_core.c')
-rw-r--r--[-rwxr-xr-x]drivers/crypto/ux500/hash/hash_core.c1615
1 files changed, 547 insertions, 1068 deletions
diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c
index fd5f8a870bf..a2e4ebd8ac1 100755..100644
--- a/drivers/crypto/ux500/hash/hash_core.c
+++ b/drivers/crypto/ux500/hash/hash_core.c
@@ -1,14 +1,13 @@
/*
* Cryptographic API.
- *
* Support for Nomadik hardware crypto engine.
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
+
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Shujuan Chen <shujuan.chen@stericsson.com> for ST-Ericsson
+ * Author: Joakim Bech <joakim.xx.bech@stericsson.com> for ST-Ericsson
+ * Author: Berne Hebark <berne.herbark@stericsson.com> for ST-Ericsson.
+ * Author: Niklas Hernaeus <niklas.hernaeus@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL) version 2
*/
#include <linux/clk.h>
@@ -20,86 +19,54 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
-
#include <linux/crypto.h>
+#include <linux/regulator/consumer.h>
+#include <linux/bitops.h>
+
#include <crypto/internal/hash.h>
#include <crypto/sha.h>
-#include <mach/debug.h>
#include <mach/hardware.h>
#include "hash_alg.h"
#define DRIVER_NAME "DRIVER HASH"
-/* enables/disables debug msgs */
+/* Enable/Disables debug msgs */
#define DRIVER_DEBUG 1
#define DRIVER_DEBUG_PFX DRIVER_NAME
-#define DRIVER_DBG KERN_ERR
+#define DRIVER_DBG KERN_DEBUG
#define MAX_HASH_DIGEST_BYTE_SIZE 32
-#define HASH_BLOCK_BYTE_SIZE 64
-#define HASH_ACC_SYNC_CONTROL
-#ifdef HASH_ACC_SYNC_CONTROL
static struct mutex hash_hw_acc_mutex;
-#endif
-int debug;
-static int mode;
-static int contextsaving;
-static struct hash_system_context g_sys_ctx;
+static int debug;
+static struct hash_system_context sys_ctx_g;
+static struct hash_driver_data *internal_drv_data;
/**
* struct hash_driver_data - IO Base and clock.
- * @base: The IO base for the block
- * @clk: FIXME, add comment
+ * @base: The IO base for the block.
+ * @clk: The clock.
+ * @regulator: The current regulator.
+ * @power_state: TRUE = power state on, FALSE = power state off.
+ * @power_state_mutex: Mutex for power_state.
+ * @restore_dev_ctx: TRUE = saved ctx, FALSE = no saved ctx.
*/
struct hash_driver_data {
void __iomem *base;
+ struct device *dev;
struct clk *clk;
-};
-
-/**
- * struct hash_ctx - The context used for hash calculations.
- * @key: The key used in the operation
- * @keylen: The length of the key
- * @updated: Indicates if hardware is initialized for new operations
- * @state: The state of the current calculations
- * @config: The current configuration
- */
-struct hash_ctx {
- u8 key[HASH_BLOCK_BYTE_SIZE];
- u32 keylen;
- u8 updated;
- struct hash_state state;
- struct hash_config config;
-};
-
-/**
- * struct hash_tfm_ctx - Transform context
- * @key: The key stored in the transform context
- * @keylen: The length of the key in the transform context
- */
-struct hash_tfm_ctx {
- u8 key[HASH_BLOCK_BYTE_SIZE];
- u32 keylen;
+ struct regulator *regulator;
+ bool power_state;
+ struct mutex power_state_mutex;
+ bool restore_dev_state;
};
/* Declaration of functions */
static void hash_messagepad(int hid, const u32 *message, u8 index_bytes);
/**
- * hexdump - Dumps buffers in hex.
- * @buf: The buffer to dump
- * @len: The length of the buffer
- */
-static void hexdump(unsigned char *buf, unsigned int len)
-{
- print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
- 16, 1, buf, len, false);
-}
-
-/**
* clear_reg_str - Clear the registry hash_str.
* @hid: Hardware device ID
*
@@ -107,83 +74,86 @@ static void hexdump(unsigned char *buf, unsigned int len)
*/
static inline void clear_reg_str(int hid)
{
- /* We will only clear the valid registers and not the reserved */
- g_sys_ctx.registry[hid]->str &= ~HASH_STR_DCAL_MASK;
- g_sys_ctx.registry[hid]->str &= ~HASH_STR_NBLW_MASK;
+ /*
+ * We will only clear NBLW since writing 0 to DCAL is done by the
+ * hardware
+ */
+ sys_ctx_g.registry[hid]->str &= ~HASH_STR_NBLW_MASK;
}
-/**
- * write_nblw - Writes the number of valid bytes to nblw.
- * @hid: Hardware device ID
- * @bytes: The number of valid bytes in last word of a message
- *
- * Note that this function only writes, i.e. it does not clear the registry
- * before it writes the new data.
- */
-static inline void write_nblw(int hid, int bytes)
+static int hash_disable_power(
+ struct device *dev,
+ struct hash_driver_data *device_data,
+ bool save_device_state)
{
- g_sys_ctx.registry[hid]->str |=
- ((bytes * 8) & HASH_STR_NBLW_MASK);
-}
+ int ret = 0;
-/**
- * write_dcal - Write/set the dcal bit.
- * @hid: Hardware device ID
- */
-static inline void write_dcal(int hid)
-{
- g_sys_ctx.registry[hid]->str |= (1 << HASH_STR_DCAL_POS);
-}
+ dev_dbg(dev, "[%s]", __func__);
-/**
- * pad_message - Function that pads a message.
- * @hid: Hardware device ID
- *
- * FIXME: This function should be replaced.
- */
-static inline void pad_message(int hid)
-{
- hash_messagepad(hid, g_sys_ctx.state[hid].buffer,
- g_sys_ctx.state[hid].index);
+ mutex_lock(&device_data->power_state_mutex);
+ if (!device_data->power_state)
+ goto out;
+
+ if (save_device_state) {
+ hash_save_state(HASH_DEVICE_ID_1,
+ &sys_ctx_g.state[HASH_DEVICE_ID_1]);
+ device_data->restore_dev_state = true;
+ }
+
+ clk_disable(device_data->clk);
+ ret = regulator_disable(device_data->regulator);
+ if (ret)
+ dev_err(dev, "[%s]: "
+ "regulator_disable() failed!",
+ __func__);
+
+ device_data->power_state = false;
+
+out:
+ mutex_unlock(&device_data->power_state_mutex);
+
+ return ret;
}
-/**
- * write_key - Writes the key to the hardware registries.
- * @hid: Hardware device ID
- * @key: The key used in the operation
- * @keylen: The length of the key
- *
- * Note that in this function we DO NOT write to the NBLW registry even though
- * the hardware reference manual says so. There must be incorrect information in
- * the manual or there must be a bug in the state machine in the hardware.
- */
-static void write_key(int hid, const u8 *key, u32 keylen)
+static int hash_enable_power(
+ struct device *dev,
+ struct hash_driver_data *device_data,
+ bool restore_device_state)
{
- u32 word = 0;
- clear_reg_str(hid);
+ int ret = 0;
+
+ dev_dbg(dev, "[%s]", __func__);
- while (keylen >= 4) {
- word = ((u32) (key[3] & 255) << 24) |
- ((u32) (key[2] & 255) << 16) |
- ((u32) (key[1] & 255) << 8) |
- ((u32) (key[0] & 255));
+ mutex_lock(&device_data->power_state_mutex);
+ if (!device_data->power_state) {
+ ret = regulator_enable(device_data->regulator);
+ if (ret) {
+ dev_err(dev, "[%s]: regulator_enable() failed!",
+ __func__);
+ goto out;
+ }
- HASH_SET_DIN(word);
- keylen -= 4;
- key += 4;
+ ret = clk_enable(device_data->clk);
+ if (ret) {
+ dev_err(dev, "[%s]: clk_enable() failed!",
+ __func__);
+ regulator_disable(device_data->regulator);
+ goto out;
+ }
+ device_data->power_state = true;
}
- /* This takes care of the remaining bytes on the last word */
- if (keylen) {
- word = 0;
- while (keylen) {
- word |= (key[keylen - 1] << (8 * (keylen - 1)));
- keylen--;
+ if (device_data->restore_dev_state) {
+ if (restore_device_state) {
+ device_data->restore_dev_state = false;
+ hash_resume_state(HASH_DEVICE_ID_1,
+ &sys_ctx_g.state[HASH_DEVICE_ID_1]);
}
- HASH_SET_DIN(word);
}
+out:
+ mutex_unlock(&device_data->power_state_mutex);
- write_dcal(hid);
+ return ret;
}
/**
@@ -196,32 +166,20 @@ static void write_key(int hid, const u8 *key, u32 keylen)
static int init_hash_hw(struct shash_desc *desc)
{
int ret = 0;
- int hash_error = HASH_OK;
+ int hash_rv;
struct hash_ctx *ctx = shash_desc_ctx(desc);
- stm_dbg(debug, "[init_hash_hw] (ctx=0x%x)!", (u32)ctx);
+ pr_debug("[init_hash_hw] (ctx=0x%x)!", (u32)ctx);
- hash_error = hash_setconfiguration(HASH_DEVICE_ID_1, &ctx->config);
- if (hash_error != HASH_OK) {
- stm_error("hash_setconfiguration() failed!");
- ret = -1;
- goto out;
+ hash_rv = hash_setconfiguration(HASH_DEVICE_ID_1, &ctx->config);
+ if (hash_rv != HASH_OK) {
+ pr_err("hash_setconfiguration() failed!");
+ ret = -EPERM;
+ return ret;
}
- hash_error = hash_begin(HASH_DEVICE_ID_1);
- if (hash_error != HASH_OK) {
- stm_error("hash_begin() failed!");
- ret = -1;
- goto out;
- }
-
- if (ctx->config.oper_mode == HASH_OPER_MODE_HMAC) {
- stm_dbg(debug, "[init_hash_hw] update key=0x%0x, len=%d",
- (u32) ctx->key, ctx->keylen);
- write_key(HASH_DEVICE_ID_1, ctx->key, ctx->keylen);
- }
+ hash_begin(ctx);
-out:
return ret;
}
@@ -229,22 +187,13 @@ out:
* hash_init - Common hash init function for SHA1/SHA2 (SHA256).
* @desc: The hash descriptor for the job
*
- * Initialize structures and copy the key from the transform context to the
- * descriptor context if the mode is HMAC.
+ * Initialize structures.
*/
static int hash_init(struct shash_desc *desc)
{
struct hash_ctx *ctx = shash_desc_ctx(desc);
- struct hash_tfm_ctx *tfm_ctx = crypto_tfm_ctx(&desc->tfm->base);
-
- stm_dbg(debug, "[hash_init]: (ctx=0x%x)!", (u32)ctx);
- if (ctx->config.oper_mode == HASH_OPER_MODE_HMAC) {
- if (tfm_ctx->key) {
- memcpy(ctx->key, tfm_ctx->key, tfm_ctx->keylen);
- ctx->keylen = tfm_ctx->keylen;
- }
- }
+ pr_debug("[hash_init]: (ctx=0x%x)!", (u32)ctx);
memset(&ctx->state, 0, sizeof(struct hash_state));
ctx->updated = 0;
@@ -262,60 +211,23 @@ static int hash_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
int ret = 0;
- int hash_error = HASH_OK;
- struct hash_ctx *ctx = shash_desc_ctx(desc);
+ int hash_rv = HASH_OK;
- stm_dbg(debug, "[hash_update]: (ctx=0x%x, data=0x%x, len=%d)!",
- (u32)ctx, (u32)data, len);
+ pr_debug("[hash_update]: (data=0x%x, len=%d)!",
+ (u32)data, len);
-#ifdef HASH_ACC_SYNC_CONTROL
mutex_lock(&hash_hw_acc_mutex);
-#endif
-
- if (!ctx->updated) {
- ret = init_hash_hw(desc);
- if (ret) {
- stm_error("init_hash_hw() failed!");
- goto out;
- }
- }
-
- if (contextsaving) {
- if (ctx->updated) {
- hash_error =
- hash_resume_state(HASH_DEVICE_ID_1, &ctx->state);
- if (hash_error != HASH_OK) {
- stm_error("hash_resume_state() failed!");
- ret = -1;
- goto out;
- }
- }
- }
/* NOTE: The length of the message is in the form of number of bits */
- hash_error = hash_hw_update(HASH_DEVICE_ID_1, data, len * 8);
- if (hash_error != HASH_OK) {
- stm_error("hash_hw_update() failed!");
- ret = -1;
+ hash_rv = hash_hw_update(desc, HASH_DEVICE_ID_1, data, len * 8);
+ if (hash_rv != HASH_OK) {
+ pr_err("hash_hw_update() failed!");
+ ret = -EPERM;
goto out;
}
- if (contextsaving) {
- hash_error =
- hash_save_state(HASH_DEVICE_ID_1, &ctx->state);
- if (hash_error != HASH_OK) {
- stm_error("hash_save_state() failed!");
- ret = -1;
- goto out;
- }
-
- }
- ctx->updated = 1;
-
out:
-#ifdef HASH_ACC_SYNC_CONTROL
mutex_unlock(&hash_hw_acc_mutex);
-#endif
return ret;
}
@@ -327,100 +239,61 @@ out:
static int hash_final(struct shash_desc *desc, u8 *out)
{
int ret = 0;
- int hash_error = HASH_OK;
+ int hash_rv = HASH_OK;
struct hash_ctx *ctx = shash_desc_ctx(desc);
+ struct hash_driver_data *device_data = internal_drv_data;
int digestsize = crypto_shash_digestsize(desc->tfm);
u8 digest[HASH_MSG_DIGEST_SIZE];
- stm_dbg(debug, "[hash_final]: (ctx=0x%x)!", (u32) ctx);
+ pr_debug("[hash_final]: (ctx=0x%x)!", (u32) ctx);
-#ifdef HASH_ACC_SYNC_CONTROL
mutex_lock(&hash_hw_acc_mutex);
-#endif
- if (contextsaving) {
- hash_error = hash_resume_state(HASH_DEVICE_ID_1, &ctx->state);
+ /* Enable device power (and clock) */
+ ret = hash_enable_power(device_data->dev, device_data, false);
+ if (ret) {
+ dev_err(device_data->dev, "[%s]: "
+ "hash_enable_power() failed!", __func__);
+ goto out;
+ }
- if (hash_error != HASH_OK) {
- stm_error("hash_resume_state() failed!");
- ret = -1;
- goto out;
+ if (!ctx->updated) {
+ ret = init_hash_hw(desc);
+ if (ret) {
+ pr_err("init_hash_hw() failed!");
+ goto out_power;
}
- }
+ } else {
+ hash_rv = hash_resume_state(HASH_DEVICE_ID_1, &ctx->state);
- pad_message(HASH_DEVICE_ID_1);
+ if (hash_rv != HASH_OK) {
+ pr_err("hash_resume_state() failed!");
+ ret = -EPERM;
+ goto out_power;
+ }
+ }
- if (ctx->config.oper_mode == HASH_OPER_MODE_HMAC)
- write_key(HASH_DEVICE_ID_1, ctx->key, ctx->keylen);
+ hash_messagepad(HASH_DEVICE_ID_1, ctx->state.buffer,
+ ctx->state.index);
- hash_error = hash_get_digest(HASH_DEVICE_ID_1, digest);
+ hash_get_digest(HASH_DEVICE_ID_1, digest, ctx->config.algorithm);
memcpy(out, digest, digestsize);
+out_power:
+ /* Disable power (and clock) */
+ if (hash_disable_power(device_data->dev, device_data, false))
+ dev_err(device_data->dev, "[%s]: "
+ "hash_disable_power() failed!", __func__);
+
out:
-#ifdef HASH_ACC_SYNC_CONTROL
mutex_unlock(&hash_hw_acc_mutex);
-#endif
return ret;
}
/**
- * hash_setkey - The setkey function for providing the key during HMAC
- * calculations.
- * @tfm: Pointer to the transform
- * @key: The key used in the operation
- * @keylen: The length of the key
- * @alg: The algorithm to use in the operation
- */
-static int hash_setkey(struct crypto_shash *tfm, const u8 *key,
- unsigned int keylen, int alg)
-{
- int ret = 0;
- int hash_error = HASH_OK;
-
- struct hash_tfm_ctx *ctx_tfm = crypto_shash_ctx(tfm);
-
- stm_dbg(debug, "[hash_setkey]: (ctx_tfm=0x%x, key=0x%x, keylen=%d)!",
- (u32) ctx_tfm, (u32) key, keylen);
-
- /* Truncate the key to block size */
- if (keylen > HASH_BLOCK_BYTE_SIZE) {
- struct hash_config config;
- u8 digest[MAX_HASH_DIGEST_BYTE_SIZE];
- unsigned int digestsize = crypto_shash_digestsize(tfm);
-
- config.algorithm = alg;
- config.data_format = HASH_DATA_8_BITS;
- config.oper_mode = HASH_OPER_MODE_HASH;
-
-#ifdef HASH_ACC_SYNC_CONTROL
- mutex_lock(&hash_hw_acc_mutex);
-#endif
- hash_error = hash_compute(HASH_DEVICE_ID_1, key, keylen * 8,
- &config, digest);
-#ifdef HASH_ACC_SYNC_CONTROL
- mutex_unlock(&hash_hw_acc_mutex);
-#endif
- if (hash_error != HASH_OK) {
- stm_error("Error: hash_compute() failed!");
- ret = -1;
- goto out;
- }
-
- memcpy(ctx_tfm->key, digest, digestsize);
- ctx_tfm->keylen = digestsize;
- } else {
- memcpy(ctx_tfm->key, key, keylen);
- ctx_tfm->keylen = keylen;
- }
-
-out:
- return ret;
-}
-
-/**
* sha1_init - SHA1 init function.
* @desc: The hash descriptor for the job
*/
@@ -428,7 +301,7 @@ static int sha1_init(struct shash_desc *desc)
{
struct hash_ctx *ctx = shash_desc_ctx(desc);
- stm_dbg(debug, "[sha1_init]: (ctx=0x%x)!", (u32) ctx);
+ pr_debug("[sha1_init]: (ctx=0x%x)!", (u32) ctx);
ctx->config.data_format = HASH_DATA_8_BITS;
ctx->config.algorithm = HASH_ALGO_SHA1;
@@ -445,7 +318,7 @@ static int sha256_init(struct shash_desc *desc)
{
struct hash_ctx *ctx = shash_desc_ctx(desc);
- stm_dbg(debug, "[sha256_init]: (ctx=0x%x)!", (u32) ctx);
+ pr_debug("[sha256_init]: (ctx=0x%x)!", (u32) ctx);
ctx->config.data_format = HASH_DATA_8_BITS;
ctx->config.algorithm = HASH_ALGO_SHA2;
@@ -454,70 +327,24 @@ static int sha256_init(struct shash_desc *desc)
return hash_init(desc);
}
-/**
- * hmac_sha1_init - SHA1 HMAC init function.
- * @desc: The hash descriptor for the job
- */
-static int hmac_sha1_init(struct shash_desc *desc)
+static int hash_export(struct shash_desc *desc, void *out)
{
struct hash_ctx *ctx = shash_desc_ctx(desc);
- stm_dbg(debug, "[hmac_sha1_init]: (ctx=0x%x)!", (u32) ctx);
-
- ctx->config.data_format = HASH_DATA_8_BITS;
- ctx->config.algorithm = HASH_ALGO_SHA1;
- ctx->config.oper_mode = HASH_OPER_MODE_HMAC;
- ctx->config.hmac_key = HASH_SHORT_KEY;
-
- return hash_init(desc);
+ pr_debug("[hash_export]: (ctx=0x%X) (out=0x%X)",
+ (u32) ctx, (u32) out);
+ memcpy(out, ctx, sizeof(*ctx));
+ return 0;
}
-/**
- * hmac_sha256_init - SHA2 (SHA256) HMAC init function.
- * @desc: The hash descriptor for the job
- */
-static int hmac_sha256_init(struct shash_desc *desc)
+static int hash_import(struct shash_desc *desc, const void *in)
{
struct hash_ctx *ctx = shash_desc_ctx(desc);
- stm_dbg(debug, "[hmac_sha256_init]: (ctx=0x%x)!", (u32) ctx);
-
- ctx->config.data_format = HASH_DATA_8_BITS;
- ctx->config.algorithm = HASH_ALGO_SHA2;
- ctx->config.oper_mode = HASH_OPER_MODE_HMAC;
- ctx->config.hmac_key = HASH_SHORT_KEY;
-
- return hash_init(desc);
-}
-
-/**
- * hmac_sha1_setkey - SHA1 HMAC setkey function.
- * @tfm: Pointer to the transform
- * @key: The key used in the operation
- * @keylen: The length of the key
- */
-static int hmac_sha1_setkey(struct crypto_shash *tfm, const u8 *key,
- unsigned int keylen)
-{
- stm_dbg(debug, "[hmac_sha1_setkey]: (tfm=0x%x, key=0x%x, keylen=%d)!",
- (u32) tfm, (u32) key, keylen);
-
- return hash_setkey(tfm, key, keylen, HASH_ALGO_SHA1);
-}
-
-/**
- * hmac_sha256_setkey - SHA2 (SHA256) HMAC setkey function.
- * @tfm: Pointer to the transform
- * @key: The key used in the operation
- * @keylen: The length of the key
- */
-static int hmac_sha256_setkey(struct crypto_shash *tfm, const u8 *key,
- unsigned int keylen)
-{
- stm_dbg(debug, "[hmac_sha256_setkey]: (tfm=0x%x, key=0x%x, keylen=%d)!",
- (u32) tfm, (u32) key, keylen);
-
- return hash_setkey(tfm, key, keylen, HASH_ALGO_SHA2);
+ pr_debug("[hash_import]: (ctx=0x%x) (in =0x%X)",
+ (u32) ctx, (u32) in);
+ memcpy(ctx, in, sizeof(*ctx));
+ return 0;
}
static struct shash_alg sha1_alg = {
@@ -525,16 +352,17 @@ static struct shash_alg sha1_alg = {
.init = sha1_init,
.update = hash_update,
.final = hash_final,
+ .export = hash_export,
+ .import = hash_import,
.descsize = sizeof(struct hash_ctx),
+ .statesize = sizeof(struct hash_ctx),
.base = {
- .cra_name = "sha1",
- .cra_driver_name = "sha1-u8500",
- .cra_flags = CRYPTO_ALG_TYPE_DIGEST |
- CRYPTO_ALG_TYPE_SHASH,
- .cra_blocksize = SHA1_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct hash_tfm_ctx),
- .cra_module = THIS_MODULE,
- }
+ .cra_name = "sha1",
+ .cra_driver_name = "sha1-u8500",
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .cra_blocksize = SHA1_BLOCK_SIZE,
+ .cra_module = THIS_MODULE,
+ }
};
static struct shash_alg sha256_alg = {
@@ -542,52 +370,17 @@ static struct shash_alg sha256_alg = {
.init = sha256_init,
.update = hash_update,
.final = hash_final,
+ .export = hash_export,
+ .import = hash_import,
.descsize = sizeof(struct hash_ctx),
+ .statesize = sizeof(struct hash_ctx),
.base = {
- .cra_name = "sha256",
- .cra_driver_name = "sha256-u8500",
- .cra_flags = CRYPTO_ALG_TYPE_DIGEST |
- CRYPTO_ALG_TYPE_SHASH,
- .cra_blocksize = SHA256_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct hash_tfm_ctx),
- .cra_module = THIS_MODULE,
- }
-};
-
-static struct shash_alg hmac_sha1_alg = {
- .digestsize = SHA1_DIGEST_SIZE,
- .init = hmac_sha1_init,
- .update = hash_update,
- .final = hash_final,
- .setkey = hmac_sha1_setkey,
- .descsize = sizeof(struct hash_ctx),
- .base = {
- .cra_name = "hmac(sha1)",
- .cra_driver_name = "hmac(sha1-u8500)",
- .cra_flags = CRYPTO_ALG_TYPE_DIGEST |
- CRYPTO_ALG_TYPE_SHASH,
- .cra_blocksize = SHA1_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct hash_tfm_ctx),
- .cra_module = THIS_MODULE,
- }
-};
-
-static struct shash_alg hmac_sha256_alg = {
- .digestsize = SHA256_DIGEST_SIZE,
- .init = hmac_sha256_init,
- .update = hash_update,
- .final = hash_final,
- .setkey = hmac_sha256_setkey,
- .descsize = sizeof(struct hash_ctx),
- .base = {
- .cra_name = "hmac(sha256)",
- .cra_driver_name = "hmac(sha256-u8500)",
- .cra_flags = CRYPTO_ALG_TYPE_DIGEST |
- CRYPTO_ALG_TYPE_SHASH,
- .cra_blocksize = SHA256_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct hash_tfm_ctx),
- .cra_module = THIS_MODULE,
- }
+ .cra_name = "sha256",
+ .cra_driver_name = "sha256-u8500",
+ .cra_flags = CRYPTO_ALG_TYPE_SHASH,
+ .cra_blocksize = SHA256_BLOCK_SIZE,
+ .cra_module = THIS_MODULE,
+ }
};
/**
@@ -597,155 +390,129 @@ static struct shash_alg hmac_sha256_alg = {
static int u8500_hash_probe(struct platform_device *pdev)
{
int ret = 0;
- int hash_error = HASH_OK;
+ int hash_rv = HASH_OK;
struct resource *res = NULL;
struct hash_driver_data *hash_drv_data;
- stm_dbg(debug, "[u8500_hash_probe]: (pdev=0x%x)", (u32) pdev);
+ pr_debug("[u8500_hash_probe]: (pdev=0x%x)", (u32) pdev);
- stm_dbg(debug, "[u8500_hash_probe]: Calling kzalloc()!");
+ pr_debug("[u8500_hash_probe]: Calling kzalloc()!");
hash_drv_data = kzalloc(sizeof(struct hash_driver_data), GFP_KERNEL);
if (!hash_drv_data) {
- stm_dbg(debug, "kzalloc() failed!");
+ pr_debug("kzalloc() failed!");
ret = -ENOMEM;
goto out;
}
- stm_dbg(debug, "[u8500_hash_probe]: Calling platform_get_resource()!");
+ hash_drv_data->dev = &pdev->dev;
+
+ pr_debug("[u8500_hash_probe]: Calling platform_get_resource()!");
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
- stm_dbg(debug, "platform_get_resource() failed");
+ pr_debug("platform_get_resource() failed");
ret = -ENODEV;
goto out_kfree;
}
- stm_dbg(debug, "[u8500_hash_probe]: Calling request_mem_region()!");
- res = request_mem_region(res->start, res->end - res->start + 1,
- pdev->name);
+ pr_debug("[u8500_hash_probe]: Calling request_mem_region()!");
+ res = request_mem_region(res->start, resource_size(res), pdev->name);
if (res == NULL) {
- stm_dbg(debug, "request_mem_region() failed");
+ pr_debug("request_mem_region() failed");
ret = -EBUSY;
goto out_kfree;
}
- stm_dbg(debug, "[u8500_hash_probe]: Calling ioremap()!");
- hash_drv_data->base = ioremap(res->start, res->end - res->start + 1);
+ pr_debug("[u8500_hash_probe]: Calling ioremap()!");
+ hash_drv_data->base = ioremap(res->start, resource_size(res));
if (!hash_drv_data->base) {
- stm_error
- ("[u8500_hash] ioremap of hash1 register memory failed!");
+ pr_err("[u8500_hash] "
+ "ioremap of hash1 register memory failed!");
ret = -ENOMEM;
goto out_free_mem;
}
+ mutex_init(&hash_drv_data->power_state_mutex);
+
+ /* Enable power for HASH hardware block */
+ hash_drv_data->regulator = regulator_get(&pdev->dev, "v-ape");
+ if (IS_ERR(hash_drv_data->regulator)) {
+ dev_err(&pdev->dev, "[u8500_hash] "
+ "could not get hash regulator\n");
+ ret = PTR_ERR(hash_drv_data->regulator);
+ hash_drv_data->regulator = NULL;
+ goto out_unmap;
+ }
- stm_dbg(debug, "[u8500_hash_probe]: Calling clk_get()!");
+ pr_debug("[u8500_hash_probe]: Calling clk_get()!");
/* Enable the clk for HASH1 hardware block */
hash_drv_data->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(hash_drv_data->clk)) {
- stm_error("clk_get() failed!");
+ pr_err("clk_get() failed!");
ret = PTR_ERR(hash_drv_data->clk);
- goto out_unmap;
+ goto out_regulator;
}
- stm_dbg(debug, "[u8500_hash_probe]: Calling clk_enable()!");
- ret = clk_enable(hash_drv_data->clk);
+ /* Enable device power (and clock) */
+ ret = hash_enable_power(&pdev->dev, hash_drv_data, false);
if (ret) {
- stm_error("clk_enable() failed!");
- goto out_unmap;
+ dev_err(&pdev->dev, "[%s]: hash_enable_power() failed!",
+ __func__);
+ goto out_clk;
}
- stm_dbg(debug,
- "[u8500_hash_probe]: Calling hash_init_base_address()->"
- "(base=0x%x,DEVICE_ID=%d)!",
- (u32) hash_drv_data->base, HASH_DEVICE_ID_1);
+ pr_debug("[u8500_hash_probe]: Calling hash_init_base_address()->"
+ "(base=0x%x,DEVICE_ID=%d)!",
+ (u32) hash_drv_data->base, HASH_DEVICE_ID_1);
/* Setting base address */
- hash_error =
+ hash_rv =
hash_init_base_address(HASH_DEVICE_ID_1,
(t_logical_address) hash_drv_data->base);
- if (hash_error != HASH_OK) {
- stm_error("hash_init_base_address() failed!");
- ret = -1; /*TODO: what error code should be used here!? */
- goto out_clk;
+ if (hash_rv != HASH_OK) {
+ pr_err("hash_init_base_address() failed!");
+ ret = -EPERM;
+ goto out_power;
}
-#ifdef HASH_ACC_SYNC_CONTROL
- stm_dbg(debug, "[u8500_hash_probe]: Calling mutex_init()!");
+ pr_debug("[u8500_hash_probe]: Calling mutex_init()!");
mutex_init(&hash_hw_acc_mutex);
-#endif
- if (mode == 0) {
- stm_dbg(debug,
- "[u8500_hash_probe]: To register all algorithms!");
-
- ret = crypto_register_shash(&sha1_alg);
- if (ret) {
- stm_error("Could not register sha1_alg!");
- goto out_clk;
- }
- stm_dbg(debug, "[u8500_hash_probe]: sha1_alg registered!");
-
- ret = crypto_register_shash(&sha256_alg);
- if (ret) {
- stm_error("Could not register sha256_alg!");
- goto out_unreg1;
- }
- stm_dbg(debug, "[u8500_hash_probe]: sha256_alg registered!");
+ pr_debug("[u8500_hash_probe]: To register only sha1 and sha256"
+ " algorithms!");
+ internal_drv_data = hash_drv_data;
- ret = crypto_register_shash(&hmac_sha1_alg);
- if (ret) {
- stm_error("Could not register hmac_sha1_alg!");
- goto out_unreg2;
- }
- stm_dbg(debug, "[u8500_hash_probe]: hmac_sha1_alg registered!");
-
- ret = crypto_register_shash(&hmac_sha256_alg);
- if (ret) {
- stm_error("Could not register hmac_sha256_alg!");
- goto out_unreg3;
- }
- stm_dbg(debug,
- "[u8500_hash_probe]: hmac_sha256_alg registered!");
+ ret = crypto_register_shash(&sha1_alg);
+ if (ret) {
+ pr_err("Could not register sha1_alg!");
+ goto out_power;
}
+ pr_debug("[u8500_hash_probe]: sha1_alg registered!");
- if (mode == 10) {
- stm_dbg(debug,
- "[u8500_hash_probe]: To register only sha1 and sha256"
- " algorithms!");
-
- ret = crypto_register_shash(&sha1_alg);
- if (ret) {
- stm_error("Could not register sha1_alg!");
- goto out_clk;
- }
-
- ret = crypto_register_shash(&sha256_alg);
- if (ret) {
- stm_error("Could not register sha256_alg!");
- goto out_unreg1_tmp;
- }
+ ret = crypto_register_shash(&sha256_alg);
+ if (ret) {
+ pr_err("Could not register sha256_alg!");
+ goto out_unreg1_tmp;
}
- stm_dbg(debug, "[u8500_hash_probe]: Calling platform_set_drvdata()!");
+ pr_debug("[u8500_hash_probe]: Calling platform_set_drvdata()!");
platform_set_drvdata(pdev, hash_drv_data);
- return 0;
- if (mode == 0) {
-out_unreg1:
- crypto_unregister_shash(&sha1_alg);
-out_unreg2:
- crypto_unregister_shash(&sha256_alg);
-out_unreg3:
- crypto_unregister_shash(&hmac_sha1_alg);
- }
+ if (hash_disable_power(&pdev->dev, hash_drv_data, false))
+ dev_err(&pdev->dev, "[%s]: hash_disable_power()"
+ " failed!", __func__);
+
+ return 0;
- if (mode == 10) {
out_unreg1_tmp:
- crypto_unregister_shash(&sha1_alg);
- }
+ crypto_unregister_shash(&sha1_alg);
+
+out_power:
+ hash_disable_power(&pdev->dev, hash_drv_data, false);
out_clk:
- clk_disable(hash_drv_data->clk);
clk_put(hash_drv_data->clk);
+out_regulator:
+ regulator_put(hash_drv_data->regulator);
+
out_unmap:
iounmap(hash_drv_data->base);
@@ -767,60 +534,133 @@ static int u8500_hash_remove(struct platform_device *pdev)
struct resource *res;
struct hash_driver_data *hash_drv_data;
- stm_dbg(debug, "[u8500_hash_remove]: (pdev=0x%x)", (u32) pdev);
+ pr_debug("[u8500_hash_remove]: (pdev=0x%x)", (u32) pdev);
- stm_dbg(debug, "[u8500_hash_remove]: Calling platform_get_drvdata()!");
+ pr_debug("[u8500_hash_remove]: Calling platform_get_drvdata()!");
hash_drv_data = platform_get_drvdata(pdev);
- if (mode == 0) {
- stm_dbg(debug,
- "[u8500_hash_remove]: To unregister all algorithms!");
- crypto_unregister_shash(&sha1_alg);
- crypto_unregister_shash(&sha256_alg);
- crypto_unregister_shash(&hmac_sha1_alg);
- crypto_unregister_shash(&hmac_sha256_alg);
- }
+ pr_debug("[u8500_hash_remove]: To unregister only sha1 and "
+ "sha256 algorithms!");
+ crypto_unregister_shash(&sha1_alg);
+ crypto_unregister_shash(&sha256_alg);
- if (mode == 10) {
- stm_dbg(debug,
- "[u8500_hash_remove]: To unregister only sha1 and "
- "sha256 algorithms!");
- crypto_unregister_shash(&sha1_alg);
- crypto_unregister_shash(&sha256_alg);
- }
-#ifdef HASH_ACC_SYNC_CONTROL
- stm_dbg(debug, "[u8500_hash_remove]: Calling mutex_destroy()!");
+ pr_debug("[u8500_hash_remove]: Calling mutex_destroy()!");
mutex_destroy(&hash_hw_acc_mutex);
-#endif
- stm_dbg(debug, "[u8500_hash_remove]: Calling clk_disable()!");
+ pr_debug("[u8500_hash_remove]: Calling clk_disable()!");
clk_disable(hash_drv_data->clk);
- stm_dbg(debug, "[u8500_hash_remove]: Calling clk_put()!");
+ pr_debug("[u8500_hash_remove]: Calling clk_put()!");
clk_put(hash_drv_data->clk);
- stm_dbg(debug, "[u8500_hash_remove]: Calling iounmap(): base = 0x%x",
- (u32) hash_drv_data->base);
+ pr_debug("[u8500_hash_remove]: Calling regulator_disable()!");
+ regulator_disable(hash_drv_data->regulator);
+
+ pr_debug("[u8500_hash_remove]: Calling iounmap(): base = 0x%x",
+ (u32) hash_drv_data->base);
iounmap(hash_drv_data->base);
- stm_dbg(debug, "[u8500_hash_remove]: Calling platform_get_resource()!");
+ pr_debug("[u8500_hash_remove]: Calling platform_get_resource()!");
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- stm_dbg(debug,
- "[u8500_hash_remove]: Calling release_mem_region()"
- "->res->start=0x%x, res->end = 0x%x!",
+ pr_debug("[u8500_hash_remove]: Calling release_mem_region()"
+ "->res->start=0x%x, res->end = 0x%x!",
res->start, res->end);
release_mem_region(res->start, res->end - res->start + 1);
- stm_dbg(debug, "[u8500_hash_remove]: Calling kfree()!");
+ pr_debug("[u8500_hash_remove]: Calling kfree()!");
kfree(hash_drv_data);
return 0;
}
+static void u8500_hash_shutdown(struct platform_device *pdev)
+{
+ struct resource *res = NULL;
+ struct hash_driver_data *hash_drv_data;
+
+ dev_dbg(&pdev->dev, "[%s]", __func__);
+
+ hash_drv_data = platform_get_drvdata(pdev);
+ if (!hash_drv_data) {
+ dev_err(&pdev->dev, "[%s]: "
+ "platform_get_drvdata() failed!", __func__);
+ return;
+ }
+
+ crypto_unregister_shash(&sha1_alg);
+ crypto_unregister_shash(&sha256_alg);
+
+ mutex_destroy(&hash_hw_acc_mutex);
+
+ iounmap(hash_drv_data->base);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res)
+ release_mem_region(res->start, resource_size(res));
+
+ if (hash_disable_power(&pdev->dev, hash_drv_data, false))
+ dev_err(&pdev->dev, "[%s]: "
+ "hash_disable_power() failed", __func__);
+
+ clk_put(hash_drv_data->clk);
+ regulator_put(hash_drv_data->regulator);
+}
+
+static int u8500_hash_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ int ret;
+ struct hash_driver_data *hash_drv_data;
+
+ dev_dbg(&pdev->dev, "[%s]", __func__);
+
+ /* Handle state? */
+ hash_drv_data = platform_get_drvdata(pdev);
+ if (!hash_drv_data) {
+ dev_err(&pdev->dev, "[%s]: "
+ "platform_get_drvdata() failed!", __func__);
+ return -ENOMEM;
+ }
+
+ ret = hash_disable_power(&pdev->dev, hash_drv_data, true);
+ if (ret)
+ dev_err(&pdev->dev, "[%s]: "
+ "hash_disable_power()", __func__);
+
+ return ret;
+}
+
+static int u8500_hash_resume(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct hash_driver_data *hash_drv_data;
+
+ dev_dbg(&pdev->dev, "[%s]", __func__);
+
+ hash_drv_data = platform_get_drvdata(pdev);
+ if (!hash_drv_data) {
+ dev_err(&pdev->dev, "[%s]: "
+ "platform_get_drvdata() failed!", __func__);
+ return -ENOMEM;
+ }
+
+ if (hash_drv_data->restore_dev_state) {
+ ret = hash_enable_power(&pdev->dev, hash_drv_data, true);
+ if (ret)
+ dev_err(&pdev->dev, "[%s]: "
+ "hash_enable_power() failed!", __func__);
+ }
+
+ return ret;
+}
+
+
static struct platform_driver hash_driver = {
.probe = u8500_hash_probe,
.remove = u8500_hash_remove,
+ .shutdown = u8500_hash_shutdown,
+ .suspend = u8500_hash_suspend,
+ .resume = u8500_hash_resume,
.driver = {
.owner = THIS_MODULE,
.name = "hash1",
@@ -832,7 +672,7 @@ static struct platform_driver hash_driver = {
*/
static int __init u8500_hash_mod_init(void)
{
- stm_dbg(debug, "u8500_hash_mod_init() is called!");
+ pr_debug("u8500_hash_mod_init() is called!");
return platform_driver_register(&hash_driver);
}
@@ -842,7 +682,7 @@ static int __init u8500_hash_mod_init(void)
*/
static void __exit u8500_hash_mod_fini(void)
{
- stm_dbg(debug, "u8500_hash_mod_fini() is called!");
+ pr_debug("u8500_hash_mod_fini() is called!");
platform_driver_unregister(&hash_driver);
return;
@@ -860,14 +700,10 @@ static void hash_processblock(int hid, const u32 *message)
{
u32 count;
- HCL_CLEAR_BITS(g_sys_ctx.registry[hid]->str,
- HASH_STR_DCAL_MASK);
- HCL_CLEAR_BITS(g_sys_ctx.registry[hid]->str,
- HASH_STR_NBLW_MASK);
+ clear_bit(HASH_STR_NBLW_MASK, (void *)sys_ctx_g.registry[hid]->str);
/* Partially unrolled loop */
- for (count = 0; count < (HASH_BLOCK_SIZE / sizeof(u32));
- count += 4) {
+ for (count = 0; count < (HASH_BLOCK_SIZE / sizeof(u32)); count += 4) {
HASH_SET_DIN(message[0]);
HASH_SET_DIN(message[1]);
HASH_SET_DIN(message[2]);
@@ -889,8 +725,8 @@ static void hash_processblock(int hid, const u32 *message)
*/
static void hash_messagepad(int hid, const u32 *message, u8 index_bytes)
{
- stm_dbg(debug, "[u8500_hash_alg] hash_messagepad"
- "(bytes in final msg=%d))", index_bytes);
+ pr_debug("[u8500_hash_alg] hash_messagepad"
+ "(bytes in final msg=%d))", index_bytes);
clear_reg_str(hid);
@@ -904,34 +740,39 @@ static void hash_messagepad(int hid, const u32 *message, u8 index_bytes)
if (index_bytes)
HASH_SET_DIN(message[0]);
+ while (sys_ctx_g.registry[hid]->str & HASH_STR_DCAL_MASK)
+ cpu_relax();
+
/* num_of_bytes == 0 => NBLW <- 0 (32 bits valid in DATAIN) */
HASH_SET_NBLW(index_bytes * 8);
- stm_dbg(debug, "[u8500_hash_alg] hash_messagepad -> DIN=0x%08x NBLW=%d",
- g_sys_ctx.registry[hid]->din,
- g_sys_ctx.registry[hid]->str);
+ pr_debug("[u8500_hash_alg] hash_messagepad -> DIN=0x%08x NBLW=%d",
+ sys_ctx_g.registry[hid]->din,
+ sys_ctx_g.registry[hid]->str);
HASH_SET_DCAL;
- stm_dbg(debug, "[u8500_hash_alg] hash_messagepad d -> "
- "DIN=0x%08x NBLW=%d",
- g_sys_ctx.registry[hid]->din,
- g_sys_ctx.registry[hid]->str);
+ pr_debug("[u8500_hash_alg] hash_messagepad after dcal -> "
+ "DIN=0x%08x NBLW=%d",
+ sys_ctx_g.registry[hid]->din,
+ sys_ctx_g.registry[hid]->str);
+ while (sys_ctx_g.registry[hid]->str & HASH_STR_DCAL_MASK)
+ cpu_relax();
}
/**
* hash_incrementlength - Increments the length of the current message.
- * @hid: Hardware device ID
+ * @ctx: Hash context
* @incr: Length of message processed already
*
* Overflow cannot occur, because conditions for overflow are checked in
* hash_hw_update.
*/
-static void hash_incrementlength(int hid, u32 incr)
+static void hash_incrementlength(struct hash_ctx *ctx, u32 incr)
{
- g_sys_ctx.state[hid].length.low_word += incr;
+ ctx->state.length.low_word += incr;
/* Check for wrap-around */
- if (g_sys_ctx.state[hid].length.low_word < incr)
- g_sys_ctx.state[hid].length.high_word++;
+ if (ctx->state.length.low_word < incr)
+ ctx->state.length.high_word++;
}
/**
@@ -963,60 +804,49 @@ static void hash_incrementlength(int hid, u32 incr)
*/
int hash_setconfiguration(int hid, struct hash_config *p_config)
{
- int hash_error = HASH_OK;
+ int hash_rv = HASH_OK;
- stm_dbg(debug, "[u8500_hash_alg] hash_setconfiguration())");
+ pr_debug("[u8500_hash_alg] hash_setconfiguration())");
- if (!((HASH_DEVICE_ID_0 == hid)
- || (HASH_DEVICE_ID_1 == hid))) {
- hash_error = HASH_INVALID_PARAMETER;
- stm_error("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
- return hash_error;
- }
+ if (p_config->algorithm != HASH_ALGO_SHA1 &&
+ p_config->algorithm != HASH_ALGO_SHA2)
+ return HASH_INVALID_PARAMETER;
HASH_SET_DATA_FORMAT(p_config->data_format);
- HCL_SET_BITS(g_sys_ctx.registry[hid]->cr,
- HASH_CR_EMPTYMSG_MASK);
+ HCL_SET_BITS(sys_ctx_g.registry[hid]->cr, HASH_CR_EMPTYMSG_MASK);
- /* This bit selects between SHA-1 or SHA-2 algorithm */
- if (HASH_ALGO_SHA2 == p_config->algorithm) {
- HCL_CLEAR_BITS(g_sys_ctx.registry[hid]->cr,
- HASH_CR_ALGO_MASK);
- } else { /* SHA1 algorithm */
+ switch (p_config->algorithm) {
+ case HASH_ALGO_SHA1:
+ HCL_SET_BITS(sys_ctx_g.registry[hid]->cr, HASH_CR_ALGO_MASK);
+ break;
- HCL_SET_BITS(g_sys_ctx.registry[hid]->cr,
- HASH_CR_ALGO_MASK);
+ case HASH_ALGO_SHA2:
+ HCL_CLEAR_BITS(sys_ctx_g.registry[hid]->cr, HASH_CR_ALGO_MASK);
+ break;
+
+ default:
+ pr_debug("[u8500_hash_alg] Incorrect algorithm.");
+ return HASH_INVALID_PARAMETER;
}
/* This bit selects between HASH or HMAC mode for the selected
algorithm */
if (HASH_OPER_MODE_HASH == p_config->oper_mode) {
- HCL_CLEAR_BITS(g_sys_ctx.registry
+ HCL_CLEAR_BITS(sys_ctx_g.registry
[hid]->cr, HASH_CR_MODE_MASK);
- } else { /* HMAC mode */
-
- HCL_SET_BITS(g_sys_ctx.registry[hid]->cr,
- HASH_CR_MODE_MASK);
-
- /* This bit selects between short key (<= 64 bytes) or long key
- (>64 bytes) in HMAC mode */
- if (HASH_SHORT_KEY == p_config->hmac_key) {
- HCL_CLEAR_BITS(g_sys_ctx.registry[hid]->cr,
- HASH_CR_LKEY_MASK);
- } else {
- HCL_SET_BITS(g_sys_ctx.registry[hid]->cr,
- HASH_CR_LKEY_MASK);
- }
+ } else { /* HMAC mode or wrong hash mode */
+ hash_rv = HASH_INVALID_PARAMETER;
+ pr_err("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
}
- return hash_error;
+ return hash_rv;
}
/**
* hash_begin - This routine resets some globals and initializes the hash
* hardware.
- * @hid: Hardware device ID
+ * @ctx: Hash context
*
* Reentrancy: Non Re-entrant
*
@@ -1033,35 +863,20 @@ int hash_setconfiguration(int hid, struct hash_config *p_config)
* So the user has to initialize the device for new
* configuration to take in to effect.
*/
-int hash_begin(int hid)
+void hash_begin(struct hash_ctx *ctx)
{
- int hash_error = HASH_OK;
-
/* HW and SW initializations */
/* Note: there is no need to initialize buffer and digest members */
- stm_dbg(debug, "[u8500_hash_alg] hash_begin())");
-
- if (!((HASH_DEVICE_ID_0 == hid)
- || (HASH_DEVICE_ID_1 == hid))) {
- hash_error = HASH_INVALID_PARAMETER;
- stm_error("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
- return hash_error;
- }
+ pr_debug("[u8500_hash_alg] hash_begin())");
- g_sys_ctx.state[hid].index = 0;
- g_sys_ctx.state[hid].bit_index = 0;
- g_sys_ctx.state[hid].length.high_word = 0;
- g_sys_ctx.state[hid].length.low_word = 0;
+ while (sys_ctx_g.registry[HASH_DEVICE_ID_1]->str & HASH_STR_DCAL_MASK)
+ cpu_relax();
HASH_INITIALIZE;
- HCL_CLEAR_BITS(g_sys_ctx.registry[hid]->str,
- HASH_STR_DCAL_MASK);
- HCL_CLEAR_BITS(g_sys_ctx.registry[hid]->str,
+ HCL_CLEAR_BITS(sys_ctx_g.registry[HASH_DEVICE_ID_1]->str,
HASH_STR_NBLW_MASK);
-
- return hash_error;
}
/**
@@ -1074,57 +889,62 @@ int hash_begin(int hid)
*
* Reentrancy: Non Re-entrant
*/
-int hash_hw_update(int hid, const u8 *p_data_buffer, u32 msg_length)
+int hash_hw_update(struct shash_desc *desc,
+ int hid,
+ const u8 *p_data_buffer,
+ u32 msg_length)
{
- int hash_error = HASH_OK;
+ int hash_rv = HASH_OK;
u8 index;
u8 *p_buffer;
u32 count;
+ struct hash_ctx *ctx = shash_desc_ctx(desc);
+ struct hash_driver_data *device_data = internal_drv_data;
- stm_dbg(debug, "[u8500_hash_alg] hash_hw_update(msg_length=%d / %d), "
- "in=%d, bin=%d))",
+ pr_debug("[u8500_hash_alg] hash_hw_update(msg_length=%d / %d), "
+ "in=%d, bin=%d))",
msg_length,
msg_length / 8,
- g_sys_ctx.state[hid].index,
- g_sys_ctx.state[hid].bit_index);
-
- if (!((HASH_DEVICE_ID_0 == hid)
- || (HASH_DEVICE_ID_1 == hid))) {
- hash_error = HASH_INVALID_PARAMETER;
- stm_error("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
- return hash_error;
- }
+ ctx->state.index,
+ ctx->state.bit_index);
- index = g_sys_ctx.state[hid].index;
+ index = ctx->state.index;
- p_buffer = (u8 *)g_sys_ctx.state[hid].buffer;
+ p_buffer = (u8 *)ctx->state.buffer;
/* Number of bytes in the message */
msg_length /= 8;
/* Check parameters */
if (NULL == p_data_buffer) {
- hash_error = HASH_INVALID_PARAMETER;
- stm_error("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
- return hash_error;
+ hash_rv = HASH_INVALID_PARAMETER;
+ pr_err("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
+ return hash_rv;
}
- /* Check if g_sys_ctx.state.length + msg_length
+ /* Check if ctx->state.length + msg_length
overflows */
if (msg_length >
- (g_sys_ctx.state[hid].length.low_word + msg_length)
+ (ctx->state.length.low_word + msg_length)
&& HASH_HIGH_WORD_MAX_VAL ==
- (g_sys_ctx.state[hid].length.high_word)) {
- hash_error = HASH_MSG_LENGTH_OVERFLOW;
- stm_error("[u8500_hash_alg] HASH_MSG_LENGTH_OVERFLOW!");
- return hash_error;
+ (ctx->state.length.high_word)) {
+ hash_rv = HASH_MSG_LENGTH_OVERFLOW;
+ pr_err("[u8500_hash_alg] HASH_MSG_LENGTH_OVERFLOW!");
+ return hash_rv;
+ }
+
+ /* Enable device power (and clock) */
+ hash_rv = hash_enable_power(device_data->dev, device_data, false);
+ if (hash_rv) {
+ dev_err(device_data->dev, "[%s]: "
+ "hash_enable_power() failed!", __func__);
+ goto out;
}
/* Main loop */
while (0 != msg_length) {
if ((index + msg_length) < HASH_BLOCK_SIZE) {
for (count = 0; count < msg_length; count++) {
- /*TODO: memcpy? */
p_buffer[index + count] =
*(p_data_buffer + count);
}
@@ -1132,7 +952,26 @@ int hash_hw_update(int hid, const u8 *p_data_buffer, u32 msg_length)
index += msg_length;
msg_length = 0;
} else {
- /* if 'p_data_buffer' is four byte aligned and local
+ if (!ctx->updated) {
+ hash_rv = init_hash_hw(desc);
+ if (hash_rv != HASH_OK) {
+ pr_err("init_hash_hw() failed!");
+ goto out;
+ }
+ ctx->updated = 1;
+ } else {
+ hash_rv =
+ hash_resume_state(HASH_DEVICE_ID_1,
+ &ctx->state);
+ if (hash_rv != HASH_OK) {
+ pr_err("hash_resume_state()"
+ " failed!");
+ goto out_power;
+ }
+ }
+
+ /*
+ * If 'p_data_buffer' is four byte aligned and local
* buffer does not have any data, we can write data
* directly from 'p_data_buffer' to HW peripheral,
* otherwise we first copy data to a local buffer
@@ -1152,60 +991,34 @@ int hash_hw_update(int hid, const u8 *p_data_buffer, u32 msg_length)
hash_processblock(hid, (const u32 *)p_buffer);
}
- hash_incrementlength(hid, HASH_BLOCK_SIZE);
+ hash_incrementlength(ctx, HASH_BLOCK_SIZE);
p_data_buffer += (HASH_BLOCK_SIZE - index);
msg_length -= (HASH_BLOCK_SIZE - index);
index = 0;
+
+ hash_rv =
+ hash_save_state(HASH_DEVICE_ID_1, &ctx->state);
+ if (hash_rv != HASH_OK) {
+ pr_err("hash_save_state() failed!");
+ goto out_power;
+ }
}
}
- g_sys_ctx.state[hid].index = index;
+ ctx->state.index = index;
- stm_dbg(debug, "[u8500_hash_alg] hash_hw_update END(msg_length=%d in "
- "bits, in=%d, bin=%d))",
+ pr_debug("[u8500_hash_alg] hash_hw_update END(msg_length=%d in "
+ "bits, in=%d, bin=%d))",
msg_length,
- g_sys_ctx.state[hid].index,
- g_sys_ctx.state[hid].bit_index);
-
- return hash_error;
-}
-
-/**
- * hash_end_key - Function that ends a message, i.e. pad and triggers the last
- * calculation.
- * @hid: Hardware device ID
- *
- * This function also clear the registries that have been involved in
- * computation.
- */
-int hash_end_key(int hid)
-{
- int hash_error = HASH_OK;
- u8 count = 0;
-
- stm_dbg(debug, "[u8500_hash_alg] hash_end_key(index=%d))",
- g_sys_ctx.state[hid].index);
-
- hash_messagepad(hid, g_sys_ctx.state[hid].buffer,
- g_sys_ctx.state[hid].index);
-
- /* Wait till the DCAL bit get cleared, So that we get the final
- * message digest not intermediate value.
- */
- while (g_sys_ctx.registry[hid]->str & HASH_STR_DCAL_MASK)
- ;
-
- /* Reset the HASH state */
- g_sys_ctx.state[hid].index = 0;
- g_sys_ctx.state[hid].bit_index = 0;
-
- for (count = 0; count < HASH_BLOCK_SIZE / sizeof(u32); count++)
- g_sys_ctx.state[hid].buffer[count] = 0;
-
- g_sys_ctx.state[hid].length.high_word = 0;
- g_sys_ctx.state[hid].length.low_word = 0;
-
- return hash_error;
+ ctx->state.index,
+ ctx->state.bit_index);
+out_power:
+ /* Disable power (and clock) */
+ if (hash_disable_power(device_data->dev, device_data, false))
+ dev_err(device_data->dev, "[%s]: "
+ "hash_disable_power() failed!", __func__);
+out:
+ return hash_rv;
}
/**
@@ -1218,66 +1031,53 @@ int hash_end_key(int hid)
int hash_resume_state(int hid, const struct hash_state *device_state)
{
u32 temp_cr;
- int hash_error = HASH_OK;
+ int hash_rv = HASH_OK;
s32 count;
+ int hash_mode = HASH_OPER_MODE_HASH;
- stm_dbg(debug, "[u8500_hash_alg] hash_resume_state(state(0x%x)))",
- (u32) device_state);
+ pr_debug("[u8500_hash_alg] hash_resume_state(state(0x%x)))",
+ (u32) device_state);
if (NULL == device_state) {
- hash_error = HASH_INVALID_PARAMETER;
- stm_error("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
- return hash_error;
- }
-
- if (!((HASH_DEVICE_ID_0 == hid)
- || (HASH_DEVICE_ID_1 == hid))) {
- hash_error = HASH_INVALID_PARAMETER;
- stm_error("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
- return hash_error;
+ hash_rv = HASH_INVALID_PARAMETER;
+ pr_err("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
+ return hash_rv;
}
/* Check correctness of index and length members */
if (device_state->index > HASH_BLOCK_SIZE
|| (device_state->length.low_word % HASH_BLOCK_SIZE) != 0) {
- hash_error = HASH_INVALID_PARAMETER;
- stm_error("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
- return hash_error;
- }
-
- for (count = 0; count < (s32) (HASH_BLOCK_SIZE / sizeof(u32));
- count++) {
- g_sys_ctx.state[hid].buffer[count] =
- device_state->buffer[count];
+ hash_rv = HASH_INVALID_PARAMETER;
+ pr_err("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
+ return hash_rv;
}
- g_sys_ctx.state[hid].index = device_state->index;
- g_sys_ctx.state[hid].bit_index = device_state->bit_index;
- g_sys_ctx.state[hid].length = device_state->length;
-
HASH_INITIALIZE;
temp_cr = device_state->temp_cr;
- g_sys_ctx.registry[hid]->cr =
+ sys_ctx_g.registry[hid]->cr =
temp_cr & HASH_CR_RESUME_MASK;
+ if (sys_ctx_g.registry[hid]->cr & HASH_CR_MODE_MASK)
+ hash_mode = HASH_OPER_MODE_HMAC;
+ else
+ hash_mode = HASH_OPER_MODE_HASH;
+
for (count = 0; count < HASH_CSR_COUNT; count++) {
- if ((count >= 36) &&
- !(g_sys_ctx.registry[hid]->cr &
- HASH_CR_MODE_MASK)) {
+ if ((count >= 36) && (hash_mode == HASH_OPER_MODE_HASH))
break;
- }
- g_sys_ctx.registry[hid]->csrx[count] =
+
+ sys_ctx_g.registry[hid]->csrx[count] =
device_state->csr[count];
}
- g_sys_ctx.registry[hid]->csfull = device_state->csfull;
- g_sys_ctx.registry[hid]->csdatain = device_state->csdatain;
+ sys_ctx_g.registry[hid]->csfull = device_state->csfull;
+ sys_ctx_g.registry[hid]->csdatain = device_state->csdatain;
- g_sys_ctx.registry[hid]->str = device_state->str_reg;
- g_sys_ctx.registry[hid]->cr = temp_cr;
+ sys_ctx_g.registry[hid]->str = device_state->str_reg;
+ sys_ctx_g.registry[hid]->cr = temp_cr;
- return hash_error;
+ return hash_rv;
}
/**
@@ -1291,289 +1091,50 @@ int hash_save_state(int hid, struct hash_state *device_state)
{
u32 temp_cr;
u32 count;
- int hash_error = HASH_OK;
+ int hash_rv = HASH_OK;
+ int hash_mode = HASH_OPER_MODE_HASH;
- stm_dbg(debug, "[u8500_hash_alg] hash_save_state( state(0x%x)))",
- (u32) device_state);
+ pr_debug("[u8500_hash_alg] hash_save_state( state(0x%x)))",
+ (u32) device_state);
if (NULL == device_state) {
- hash_error = HASH_INVALID_PARAMETER;
- stm_error("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
- return hash_error;
- }
-
- if (!((HASH_DEVICE_ID_0 == hid)
- || (HASH_DEVICE_ID_1 == hid))) {
- hash_error = HASH_INVALID_PARAMETER;
- stm_error("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
- return hash_error;
- }
-
- for (count = 0; count < HASH_BLOCK_SIZE / sizeof(u32); count++) {
- device_state->buffer[count] =
- g_sys_ctx.state[hid].buffer[count];
+ hash_rv = HASH_INVALID_PARAMETER;
+ pr_err("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
+ return hash_rv;
}
- device_state->index = g_sys_ctx.state[hid].index;
- device_state->bit_index = g_sys_ctx.state[hid].bit_index;
- device_state->length = g_sys_ctx.state[hid].length;
-
/* Write dummy value to force digest intermediate calculation. This
* actually makes sure that there isn't any ongoing calculation in the
* hardware.
*/
- while (g_sys_ctx.registry[hid]->str & HASH_STR_DCAL_MASK)
- ;
+ while (sys_ctx_g.registry[hid]->str & HASH_STR_DCAL_MASK)
+ cpu_relax();
- temp_cr = g_sys_ctx.registry[hid]->cr;
+ temp_cr = sys_ctx_g.registry[hid]->cr;
- device_state->str_reg = g_sys_ctx.registry[hid]->str;
+ device_state->str_reg = sys_ctx_g.registry[hid]->str;
- device_state->din_reg = g_sys_ctx.registry[hid]->din;
+ device_state->din_reg = sys_ctx_g.registry[hid]->din;
+
+ if (sys_ctx_g.registry[hid]->cr & HASH_CR_MODE_MASK)
+ hash_mode = HASH_OPER_MODE_HMAC;
+ else
+ hash_mode = HASH_OPER_MODE_HASH;
for (count = 0; count < HASH_CSR_COUNT; count++) {
- if ((count >= 36)
- && !(g_sys_ctx.registry[hid]->cr &
- HASH_CR_MODE_MASK)) {
+ if ((count >= 36) && (hash_mode == HASH_OPER_MODE_HASH))
break;
- }
device_state->csr[count] =
- g_sys_ctx.registry[hid]->csrx[count];
+ sys_ctx_g.registry[hid]->csrx[count];
}
- device_state->csfull = g_sys_ctx.registry[hid]->csfull;
- device_state->csdatain = g_sys_ctx.registry[hid]->csdatain;
+ device_state->csfull = sys_ctx_g.registry[hid]->csfull;
+ device_state->csdatain = sys_ctx_g.registry[hid]->csdatain;
- /* end if */
device_state->temp_cr = temp_cr;
- return hash_error;
-}
-
-/**
- * hash_end - Ends current HASH computation, passing back the hash to the user.
- * @hid: Hardware device ID
- * @digest: User allocated byte array for the calculated digest
- *
- * Reentrancy: Non Re-entrant
- */
-int hash_end(int hid, u8 digest[HASH_MSG_DIGEST_SIZE])
-{
- int hash_error = HASH_OK;
- u32 count;
- /* Standard SHA-1 digest for null string for HASH mode */
- u8 zero_message_hash_sha1[HASH_MSG_DIGEST_SIZE] = {
- 0xDA, 0x39, 0xA3, 0xEE,
- 0x5E, 0x6B, 0x4B, 0x0D,
- 0x32, 0x55, 0xBF, 0xEF,
- 0x95, 0x60, 0x18, 0x90,
- 0xAF, 0xD8, 0x07, 0x09,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
- /* Standard SHA-2 digest for null string for HASH mode */
- u8 zero_message_hash_sha2[HASH_MSG_DIGEST_SIZE] = {
- 0xD4, 0x1D, 0x8C, 0xD9,
- 0x8F, 0x00, 0xB2, 0x04,
- 0xE9, 0x80, 0x09, 0x98,
- 0xEC, 0xF8, 0x42, 0x7E,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
- /* Standard SHA-1 digest for null string for HMAC mode,with no key */
- u8 zero_message_hmac_sha1[HASH_MSG_DIGEST_SIZE] = {
- 0xFB, 0xDB, 0x1D, 0x1B,
- 0x18, 0xAA, 0x6C, 0x08,
- 0x32, 0x4B, 0x7D, 0x64,
- 0xB7, 0x1F, 0xB7, 0x63,
- 0x70, 0x69, 0x0E, 0x1D,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
- /* Standard SHA2 digest for null string for HMAC mode,with no key */
- u8 zero_message_hmac_sha2[HASH_MSG_DIGEST_SIZE] = {
- 0x74, 0xE6, 0xF7, 0x29,
- 0x8A, 0x9C, 0x2D, 0x16,
- 0x89, 0x35, 0xF5, 0x8C,
- 0x00, 0x1B, 0xAD, 0x88,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
-
- stm_dbg(debug, "[u8500_hash_alg] hash_end(digest array (0x%x)))",
- (u32) digest);
-
- if (NULL == digest) {
- hash_error = HASH_INVALID_PARAMETER;
- stm_error("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
- return hash_error;
- }
-
- if (!((HASH_DEVICE_ID_0 == hid)
- || (HASH_DEVICE_ID_1 == hid))) {
- hash_error = HASH_INVALID_PARAMETER;
- stm_error("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
- return hash_error;
- }
-
- if (0 == g_sys_ctx.state[hid].index &&
- 0 == g_sys_ctx.state[hid].length.high_word &&
- 0 == g_sys_ctx.state[hid].length.low_word) {
- if (g_sys_ctx.registry[hid]->cr & HASH_CR_MODE_MASK) {
- if (g_sys_ctx.registry[hid]->cr & HASH_CR_ALGO_MASK) {
- /* hash of an empty message was requested */
- for (count = 0; count < HASH_MSG_DIGEST_SIZE;
- count++) {
- digest[count] =
- zero_message_hmac_sha1[count];
- }
- } else { /* SHA-2 algo */
-
- /* hash of an empty message was requested */
- for (count = 0; count < HASH_MSG_DIGEST_SIZE;
- count++) {
- digest[count] =
- zero_message_hmac_sha2[count];
- }
- }
- } else { /* HASH mode */
-
- if (g_sys_ctx.registry[hid]->cr & HASH_CR_ALGO_MASK) {
- /* hash of an empty message was requested */
- for (count = 0; count < HASH_MSG_DIGEST_SIZE;
- count++) {
- digest[count] =
- zero_message_hash_sha1[count];
- }
- } else { /* SHA-2 algo */
-
- /* hash of an empty message was requested */
- for (count = 0; count < HASH_MSG_DIGEST_SIZE;
- count++) {
- digest[count] =
- zero_message_hash_sha2[count];
- }
- }
- }
-
- HASH_SET_DCAL;
- } else {
- hash_messagepad(hid,
- g_sys_ctx.state[hid].buffer,
- g_sys_ctx.state[hid].index);
-
- /* Wait till the DCAL bit get cleared, So that we get the final
- * message digest not intermediate value. */
- while (g_sys_ctx.registry[hid]->str & HASH_STR_DCAL_MASK)
- ;
-
- hash_error = hash_get_digest(hid, digest);
-
- /* Reset the HASH state */
- g_sys_ctx.state[hid].index = 0;
- g_sys_ctx.state[hid].bit_index = 0;
- for (count = 0; count < HASH_BLOCK_SIZE / sizeof(u32);
- count++) {
- g_sys_ctx.state[hid].buffer[count]
- = 0;
- }
-
- g_sys_ctx.state[hid].length.high_word = 0;
- g_sys_ctx.state[hid].length.low_word = 0;
- }
-
- if (debug)
- hexdump(digest, HASH_MSG_DIGEST_SIZE);
-
- return hash_error;
-}
-
-/**
- * hash_initialize_globals - Initialize global variables to their default reset
- * value.
- * @hid: Hardware device ID
- *
- * Reentrancy: Non Re-entrant, global structure g_sys_ctx elements are being
- * modified
- */
-static void hash_initialize_globals(int hid)
-{
- u8 loop_count;
-
- /* Resetting the values of global variables except the registry */
- g_sys_ctx.state[hid].temp_cr = HASH_RESET_INDEX_VAL;
- g_sys_ctx.state[hid].str_reg = HASH_RESET_INDEX_VAL;
- g_sys_ctx.state[hid].din_reg = HASH_RESET_INDEX_VAL;
-
- for (loop_count = 0; loop_count < HASH_CSR_COUNT; loop_count++) {
- g_sys_ctx.state[hid].csr[loop_count] =
- HASH_RESET_CSRX_REG_VALUE;
- }
-
- g_sys_ctx.state[hid].csfull = HASH_RESET_CSFULL_REG_VALUE;
- g_sys_ctx.state[hid].csdatain = HASH_RESET_CSDATAIN_REG_VALUE;
-
- for (loop_count = 0; loop_count < (HASH_BLOCK_SIZE / sizeof(u32));
- loop_count++) {
- g_sys_ctx.state[hid].buffer[loop_count] =
- HASH_RESET_BUFFER_VAL;
- }
-
- g_sys_ctx.state[hid].length.high_word = HASH_RESET_LEN_HIGH_VAL;
- g_sys_ctx.state[hid].length.low_word = HASH_RESET_LEN_LOW_VAL;
- g_sys_ctx.state[hid].index = HASH_RESET_INDEX_VAL;
- g_sys_ctx.state[hid].bit_index = HASH_RESET_BIT_INDEX_VAL;
-}
-
-/**
- * hash_reset - This routine will reset the global variable to default reset
- * value and HASH registers to their power on reset values.
- * @hid: Hardware device ID
- *
- * Reentrancy: Non Re-entrant, global structure g_sys_ctx elements are being
- * modified.
- */
-int hash_reset(int hid)
-{
- int hash_error = HASH_OK;
- u8 loop_count;
-
- if (!((HASH_DEVICE_ID_0 == hid)
- || (HASH_DEVICE_ID_1 == hid))) {
- hash_error = HASH_INVALID_PARAMETER;
-
- return hash_error;
- }
-
- /* Resetting the values of global variables except the registry */
- hash_initialize_globals(hid);
-
- /* Resetting HASH control register to power-on-reset values */
- g_sys_ctx.registry[hid]->str = HASH_RESET_START_REG_VALUE;
-
- for (loop_count = 0; loop_count < HASH_CSR_COUNT; loop_count++) {
- g_sys_ctx.registry[hid]->csrx[loop_count] =
- HASH_RESET_CSRX_REG_VALUE;
- }
-
- g_sys_ctx.registry[hid]->csfull = HASH_RESET_CSFULL_REG_VALUE;
- g_sys_ctx.registry[hid]->csdatain =
- HASH_RESET_CSDATAIN_REG_VALUE;
-
- /* Resetting the HASH Control reg. This also reset the PRIVn and SECn
- * bits and hence the device registers will not be accessed anymore and
- * should be done in the last HASH register access statement.
- */
- g_sys_ctx.registry[hid]->cr = HASH_RESET_CONTROL_REG_VALUE;
-
- return hash_error;
+ return hash_rv;
}
/**
@@ -1587,59 +1148,37 @@ int hash_reset(int hid)
*/
int hash_init_base_address(int hid, t_logical_address base_address)
{
- int hash_error = HASH_OK;
-
- stm_dbg(debug, "[u8500_hash_alg] hash_init_base_address())");
+ int hash_rv = HASH_OK;
- if (!((HASH_DEVICE_ID_0 == hid)
- || (HASH_DEVICE_ID_1 == hid))) {
- hash_error = HASH_INVALID_PARAMETER;
-
- return hash_error;
- }
+ pr_debug("[u8500_hash_alg] hash_init_base_address())");
if (0 != base_address) {
- /*--------------------------------------*
- * Initializing the registers structure *
- *--------------------------------------*/
- g_sys_ctx.registry[hid] = (struct hash_register *) base_address;
-
- /*--------------------------*
- * Checking Peripheral Ids *
- *--------------------------*/
- if ((HASH_P_ID0 ==
- g_sys_ctx.registry[hid]->periphid0)
- && (HASH_P_ID1 ==
- g_sys_ctx.registry[hid]->periphid1)
- && (HASH_P_ID2 ==
- g_sys_ctx.registry[hid]->periphid2)
- && (HASH_P_ID3 ==
- g_sys_ctx.registry[hid]->periphid3)
- && (HASH_CELL_ID0 ==
- g_sys_ctx.registry[hid]->cellid0)
- && (HASH_CELL_ID1 ==
- g_sys_ctx.registry[hid]->cellid1)
- && (HASH_CELL_ID2 ==
- g_sys_ctx.registry[hid]->cellid2)
- && (HASH_CELL_ID3 ==
- g_sys_ctx.registry[hid]->cellid3)
+ /* Initializing the registers structure */
+ sys_ctx_g.registry[hid] =
+ (struct hash_register *) base_address;
+
+ /* Checking Peripheral Ids */
+ if ((HASH_P_ID0 == sys_ctx_g.registry[hid]->periphid0)
+ && (HASH_P_ID1 == sys_ctx_g.registry[hid]->periphid1)
+ && (HASH_P_ID2 == sys_ctx_g.registry[hid]->periphid2)
+ && (HASH_P_ID3 == sys_ctx_g.registry[hid]->periphid3)
+ && (HASH_CELL_ID0 == sys_ctx_g.registry[hid]->cellid0)
+ && (HASH_CELL_ID1 == sys_ctx_g.registry[hid]->cellid1)
+ && (HASH_CELL_ID2 == sys_ctx_g.registry[hid]->cellid2)
+ && (HASH_CELL_ID3 == sys_ctx_g.registry[hid]->cellid3)
) {
-
- /* Resetting the values of global variables except the
- registry */
- hash_initialize_globals(hid);
- hash_error = HASH_OK;
- return hash_error;
+ hash_rv = HASH_OK;
+ return hash_rv;
} else {
- hash_error = HASH_UNSUPPORTED_HW;
- stm_error("[u8500_hash_alg] HASH_UNSUPPORTED_HW!");
- return hash_error;
+ hash_rv = HASH_UNSUPPORTED_HW;
+ pr_err("[u8500_hash_alg] HASH_UNSUPPORTED_HW!");
+ return hash_rv;
}
} /* end if */
else {
- hash_error = HASH_INVALID_PARAMETER;
- stm_error("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
- return hash_error;
+ hash_rv = HASH_INVALID_PARAMETER;
+ pr_err("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
+ return hash_rv;
}
}
@@ -1647,110 +1186,50 @@ int hash_init_base_address(int hid, t_logical_address base_address)
* hash_get_digest - Gets the digest.
* @hid: Hardware device ID
* @digest: User allocated byte array for the calculated digest
+ * @algorithm: The algorithm in use.
*
* Reentrancy: Non Re-entrant, global variable registry (hash control register)
* is being modified.
*
- * Note that, if this is called before the final message has been handle it will
- * return the intermediate message digest.
+ * Note that, if this is called before the final message has been handle it
+ * will return the intermediate message digest.
*/
-int hash_get_digest(int hid, u8 *digest)
+void hash_get_digest(int hid, u8 *digest, int algorithm)
{
u32 temp_hx_val, count;
- int hash_error = HASH_OK;
-
- stm_dbg(debug,
- "[u8500_hash_alg] hash_get_digest(digest array:(0x%x))",
- (u32) digest);
+ int loop_ctr;
- if (!((HASH_DEVICE_ID_0 == hid)
- || (HASH_DEVICE_ID_1 == hid))) {
- hash_error = HASH_INVALID_PARAMETER;
- stm_error("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
- return hash_error;
+ if (algorithm != HASH_ALGO_SHA1 && algorithm != HASH_ALGO_SHA2) {
+ pr_err("[hash_get_digest] Incorrect algorithm %d", algorithm);
+ return;
}
+ if (algorithm == HASH_ALGO_SHA1)
+ loop_ctr = HASH_SHA1_DIGEST_SIZE / sizeof(u32);
+ else
+ loop_ctr = HASH_SHA2_DIGEST_SIZE / sizeof(u32);
+
+ pr_debug("[u8500_hash_alg] hash_get_digest(digest array:(0x%x))",
+ (u32) digest);
+
/* Copy result into digest array */
- for (count = 0; count < (HASH_MSG_DIGEST_SIZE / sizeof(u32));
- count++) {
+ for (count = 0; count < loop_ctr; count++) {
temp_hx_val = HASH_GET_HX(count);
digest[count * 4] = (u8) ((temp_hx_val >> 24) & 0xFF);
digest[count * 4 + 1] = (u8) ((temp_hx_val >> 16) & 0xFF);
digest[count * 4 + 2] = (u8) ((temp_hx_val >> 8) & 0xFF);
digest[count * 4 + 3] = (u8) ((temp_hx_val >> 0) & 0xFF);
}
-
- return hash_error;
}
-/**
- * hash_compute - Performs a complete HASH calculation on the message passed.
- * @hid: Hardware device ID
- * @p_data_buffer: Pointer to the message to be hashed
- * @msg_length: The length of the message
- * @p_hash_config: Structure with configuration data for the hash hardware
- * @digest: User allocated byte array for the calculated digest
- *
- * Reentrancy: Non Re-entrant
- */
-int hash_compute(int hid,
- const u8 *p_data_buffer,
- u32 msg_length,
- struct hash_config *p_hash_config,
- u8 digest[HASH_MSG_DIGEST_SIZE]) {
- int hash_error = HASH_OK;
-
- stm_dbg(debug, "[u8500_hash_alg] hash_compute())");
-
- if (!((HASH_DEVICE_ID_0 == hid)
- || (HASH_DEVICE_ID_1 == hid))) {
- hash_error = HASH_INVALID_PARAMETER;
- stm_error("[u8500_hash_alg] HASH_INVALID_PARAMETER!");
- return hash_error;
- }
-
-
- /* WARNING: return code must be checked if
- * behaviour of hash_begin changes.
- */
- hash_error = hash_setconfiguration(hid, p_hash_config);
- if (HASH_OK != hash_error) {
- stm_error("[u8500_hash_alg] hash_setconfiguration() failed!");
- return hash_error;
- }
-
- hash_error = hash_begin(hid);
- if (HASH_OK != hash_error) {
- stm_error("[u8500_hash_alg] hash_begin() failed!");
- return hash_error;
- }
-
- hash_error = hash_hw_update(hid, p_data_buffer, msg_length);
- if (HASH_OK != hash_error) {
- stm_error("[u8500_hash_alg] hash_hw_update() failed!");
- return hash_error;
- }
-
- hash_error = hash_end(hid, digest);
- if (HASH_OK != hash_error) {
- stm_error("[u8500_hash_alg] hash_end() failed!");
- return hash_error;
- }
-
- return hash_error;
-}
module_init(u8500_hash_mod_init);
module_exit(u8500_hash_mod_fini);
-module_param(mode, int, 0);
module_param(debug, int, 0);
-module_param(contextsaving, int, 0);
MODULE_DESCRIPTION("Driver for ST-Ericsson U8500 HASH engine.");
MODULE_LICENSE("GPL");
MODULE_ALIAS("sha1-u8500");
MODULE_ALIAS("sha256-u8500");
-MODULE_ALIAS("hmac(sha1-u8500)");
-MODULE_ALIAS("hmac(sha256-u8500)");