|
@@ -157,6 +157,7 @@ struct talitos_private {
|
|
|
#define TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT 0x00000001
|
|
|
#define TALITOS_FTR_HW_AUTH_CHECK 0x00000002
|
|
|
#define TALITOS_FTR_SHA224_HWINIT 0x00000004
|
|
|
+#define TALITOS_FTR_HMAC_OK 0x00000008
|
|
|
|
|
|
static void to_talitos_ptr(struct talitos_ptr *talitos_ptr, dma_addr_t dma_addr)
|
|
|
{
|
|
@@ -1874,6 +1875,97 @@ static int ahash_digest(struct ahash_request *areq)
|
|
|
return ahash_process_req(areq, areq->nbytes);
|
|
|
}
|
|
|
|
|
|
+struct keyhash_result {
|
|
|
+ struct completion completion;
|
|
|
+ int err;
|
|
|
+};
|
|
|
+
|
|
|
+static void keyhash_complete(struct crypto_async_request *req, int err)
|
|
|
+{
|
|
|
+ struct keyhash_result *res = req->data;
|
|
|
+
|
|
|
+ if (err == -EINPROGRESS)
|
|
|
+ return;
|
|
|
+
|
|
|
+ res->err = err;
|
|
|
+ complete(&res->completion);
|
|
|
+}
|
|
|
+
|
|
|
+static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
|
|
|
+ u8 *hash)
|
|
|
+{
|
|
|
+ struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
|
|
|
+
|
|
|
+ struct scatterlist sg[1];
|
|
|
+ struct ahash_request *req;
|
|
|
+ struct keyhash_result hresult;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ init_completion(&hresult.completion);
|
|
|
+
|
|
|
+ req = ahash_request_alloc(tfm, GFP_KERNEL);
|
|
|
+ if (!req)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ /* Keep tfm keylen == 0 during hash of the long key */
|
|
|
+ ctx->keylen = 0;
|
|
|
+ ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
|
|
|
+ keyhash_complete, &hresult);
|
|
|
+
|
|
|
+ sg_init_one(&sg[0], key, keylen);
|
|
|
+
|
|
|
+ ahash_request_set_crypt(req, sg, hash, keylen);
|
|
|
+ ret = crypto_ahash_digest(req);
|
|
|
+ switch (ret) {
|
|
|
+ case 0:
|
|
|
+ break;
|
|
|
+ case -EINPROGRESS:
|
|
|
+ case -EBUSY:
|
|
|
+ ret = wait_for_completion_interruptible(
|
|
|
+ &hresult.completion);
|
|
|
+ if (!ret)
|
|
|
+ ret = hresult.err;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ ahash_request_free(req);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
|
|
|
+ unsigned int keylen)
|
|
|
+{
|
|
|
+ struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
|
|
|
+ unsigned int blocksize =
|
|
|
+ crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
|
|
|
+ unsigned int digestsize = crypto_ahash_digestsize(tfm);
|
|
|
+ unsigned int keysize = keylen;
|
|
|
+ u8 hash[SHA512_DIGEST_SIZE];
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (keylen <= blocksize)
|
|
|
+ memcpy(ctx->key, key, keysize);
|
|
|
+ else {
|
|
|
+ /* Must get the hash of the long key */
|
|
|
+ ret = keyhash(tfm, key, keylen, hash);
|
|
|
+
|
|
|
+ if (ret) {
|
|
|
+ crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ keysize = digestsize;
|
|
|
+ memcpy(ctx->key, hash, digestsize);
|
|
|
+ }
|
|
|
+
|
|
|
+ ctx->keylen = keysize;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
struct talitos_alg_template {
|
|
|
u32 type;
|
|
|
union {
|
|
@@ -2217,6 +2309,138 @@ static struct talitos_alg_template driver_algs[] = {
|
|
|
DESC_HDR_SEL0_MDEUB |
|
|
|
DESC_HDR_MODE0_MDEUB_SHA512,
|
|
|
},
|
|
|
+ { .type = CRYPTO_ALG_TYPE_AHASH,
|
|
|
+ .alg.hash = {
|
|
|
+ .init = ahash_init,
|
|
|
+ .update = ahash_update,
|
|
|
+ .final = ahash_final,
|
|
|
+ .finup = ahash_finup,
|
|
|
+ .digest = ahash_digest,
|
|
|
+ .setkey = ahash_setkey,
|
|
|
+ .halg.digestsize = MD5_DIGEST_SIZE,
|
|
|
+ .halg.base = {
|
|
|
+ .cra_name = "hmac(md5)",
|
|
|
+ .cra_driver_name = "hmac-md5-talitos",
|
|
|
+ .cra_blocksize = MD5_BLOCK_SIZE,
|
|
|
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
|
|
|
+ CRYPTO_ALG_ASYNC,
|
|
|
+ .cra_type = &crypto_ahash_type
|
|
|
+ }
|
|
|
+ },
|
|
|
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
|
|
|
+ DESC_HDR_SEL0_MDEUA |
|
|
|
+ DESC_HDR_MODE0_MDEU_MD5,
|
|
|
+ },
|
|
|
+ { .type = CRYPTO_ALG_TYPE_AHASH,
|
|
|
+ .alg.hash = {
|
|
|
+ .init = ahash_init,
|
|
|
+ .update = ahash_update,
|
|
|
+ .final = ahash_final,
|
|
|
+ .finup = ahash_finup,
|
|
|
+ .digest = ahash_digest,
|
|
|
+ .setkey = ahash_setkey,
|
|
|
+ .halg.digestsize = SHA1_DIGEST_SIZE,
|
|
|
+ .halg.base = {
|
|
|
+ .cra_name = "hmac(sha1)",
|
|
|
+ .cra_driver_name = "hmac-sha1-talitos",
|
|
|
+ .cra_blocksize = SHA1_BLOCK_SIZE,
|
|
|
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
|
|
|
+ CRYPTO_ALG_ASYNC,
|
|
|
+ .cra_type = &crypto_ahash_type
|
|
|
+ }
|
|
|
+ },
|
|
|
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
|
|
|
+ DESC_HDR_SEL0_MDEUA |
|
|
|
+ DESC_HDR_MODE0_MDEU_SHA1,
|
|
|
+ },
|
|
|
+ { .type = CRYPTO_ALG_TYPE_AHASH,
|
|
|
+ .alg.hash = {
|
|
|
+ .init = ahash_init,
|
|
|
+ .update = ahash_update,
|
|
|
+ .final = ahash_final,
|
|
|
+ .finup = ahash_finup,
|
|
|
+ .digest = ahash_digest,
|
|
|
+ .setkey = ahash_setkey,
|
|
|
+ .halg.digestsize = SHA224_DIGEST_SIZE,
|
|
|
+ .halg.base = {
|
|
|
+ .cra_name = "hmac(sha224)",
|
|
|
+ .cra_driver_name = "hmac-sha224-talitos",
|
|
|
+ .cra_blocksize = SHA224_BLOCK_SIZE,
|
|
|
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
|
|
|
+ CRYPTO_ALG_ASYNC,
|
|
|
+ .cra_type = &crypto_ahash_type
|
|
|
+ }
|
|
|
+ },
|
|
|
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
|
|
|
+ DESC_HDR_SEL0_MDEUA |
|
|
|
+ DESC_HDR_MODE0_MDEU_SHA224,
|
|
|
+ },
|
|
|
+ { .type = CRYPTO_ALG_TYPE_AHASH,
|
|
|
+ .alg.hash = {
|
|
|
+ .init = ahash_init,
|
|
|
+ .update = ahash_update,
|
|
|
+ .final = ahash_final,
|
|
|
+ .finup = ahash_finup,
|
|
|
+ .digest = ahash_digest,
|
|
|
+ .setkey = ahash_setkey,
|
|
|
+ .halg.digestsize = SHA256_DIGEST_SIZE,
|
|
|
+ .halg.base = {
|
|
|
+ .cra_name = "hmac(sha256)",
|
|
|
+ .cra_driver_name = "hmac-sha256-talitos",
|
|
|
+ .cra_blocksize = SHA256_BLOCK_SIZE,
|
|
|
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
|
|
|
+ CRYPTO_ALG_ASYNC,
|
|
|
+ .cra_type = &crypto_ahash_type
|
|
|
+ }
|
|
|
+ },
|
|
|
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
|
|
|
+ DESC_HDR_SEL0_MDEUA |
|
|
|
+ DESC_HDR_MODE0_MDEU_SHA256,
|
|
|
+ },
|
|
|
+ { .type = CRYPTO_ALG_TYPE_AHASH,
|
|
|
+ .alg.hash = {
|
|
|
+ .init = ahash_init,
|
|
|
+ .update = ahash_update,
|
|
|
+ .final = ahash_final,
|
|
|
+ .finup = ahash_finup,
|
|
|
+ .digest = ahash_digest,
|
|
|
+ .setkey = ahash_setkey,
|
|
|
+ .halg.digestsize = SHA384_DIGEST_SIZE,
|
|
|
+ .halg.base = {
|
|
|
+ .cra_name = "hmac(sha384)",
|
|
|
+ .cra_driver_name = "hmac-sha384-talitos",
|
|
|
+ .cra_blocksize = SHA384_BLOCK_SIZE,
|
|
|
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
|
|
|
+ CRYPTO_ALG_ASYNC,
|
|
|
+ .cra_type = &crypto_ahash_type
|
|
|
+ }
|
|
|
+ },
|
|
|
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
|
|
|
+ DESC_HDR_SEL0_MDEUB |
|
|
|
+ DESC_HDR_MODE0_MDEUB_SHA384,
|
|
|
+ },
|
|
|
+ { .type = CRYPTO_ALG_TYPE_AHASH,
|
|
|
+ .alg.hash = {
|
|
|
+ .init = ahash_init,
|
|
|
+ .update = ahash_update,
|
|
|
+ .final = ahash_final,
|
|
|
+ .finup = ahash_finup,
|
|
|
+ .digest = ahash_digest,
|
|
|
+ .setkey = ahash_setkey,
|
|
|
+ .halg.digestsize = SHA512_DIGEST_SIZE,
|
|
|
+ .halg.base = {
|
|
|
+ .cra_name = "hmac(sha512)",
|
|
|
+ .cra_driver_name = "hmac-sha512-talitos",
|
|
|
+ .cra_blocksize = SHA512_BLOCK_SIZE,
|
|
|
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
|
|
|
+ CRYPTO_ALG_ASYNC,
|
|
|
+ .cra_type = &crypto_ahash_type
|
|
|
+ }
|
|
|
+ },
|
|
|
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
|
|
|
+ DESC_HDR_SEL0_MDEUB |
|
|
|
+ DESC_HDR_MODE0_MDEUB_SHA512,
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
struct talitos_crypto_alg {
|
|
@@ -2373,8 +2597,12 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
|
|
|
case CRYPTO_ALG_TYPE_AHASH:
|
|
|
alg = &t_alg->algt.alg.hash.halg.base;
|
|
|
alg->cra_init = talitos_cra_init_ahash;
|
|
|
+ if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
|
|
|
+ !strncmp(alg->cra_name, "hmac", 4))
|
|
|
+ return ERR_PTR(-ENOTSUPP);
|
|
|
if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
|
|
|
- !strcmp(alg->cra_name, "sha224")) {
|
|
|
+ (!strcmp(alg->cra_name, "sha224") ||
|
|
|
+ !strcmp(alg->cra_name, "hmac(sha224)"))) {
|
|
|
t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
|
|
|
t_alg->algt.desc_hdr_template =
|
|
|
DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
|
|
@@ -2471,7 +2699,8 @@ static int talitos_probe(struct platform_device *ofdev)
|
|
|
|
|
|
if (of_device_is_compatible(np, "fsl,sec2.1"))
|
|
|
priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
|
|
|
- TALITOS_FTR_SHA224_HWINIT;
|
|
|
+ TALITOS_FTR_SHA224_HWINIT |
|
|
|
+ TALITOS_FTR_HMAC_OK;
|
|
|
|
|
|
priv->chan = kzalloc(sizeof(struct talitos_channel) *
|
|
|
priv->num_channels, GFP_KERNEL);
|
|
@@ -2530,6 +2759,10 @@ static int talitos_probe(struct platform_device *ofdev)
|
|
|
t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
|
|
|
if (IS_ERR(t_alg)) {
|
|
|
err = PTR_ERR(t_alg);
|
|
|
+ if (err == -ENOTSUPP) {
|
|
|
+ kfree(t_alg);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
goto err_out;
|
|
|
}
|
|
|
|