diff options
author | Sandeep Nair | 2013-07-10 18:20:21 -0500 |
---|---|---|
committer | Murali Karicheri | 2014-12-03 10:51:23 -0600 |
commit | 703ecb1f3919fca2af64204767d11c371cb66c31 (patch) | |
tree | 286c4df067ec1dd04f8ecca5df90d749dfb5abda | |
parent | c95655622816ccea66879d5111d38c83c1691adc (diff) | |
download | linux-703ecb1f3919fca2af64204767d11c371cb66c31.tar.gz linux-703ecb1f3919fca2af64204767d11c371cb66c31.tar.xz linux-703ecb1f3919fca2af64204767d11c371cb66c31.zip |
crypto: keystone: Fix security context teardown procedure
After initiating a security context teardown, host should wait until the ownership flag is cleared by CP_ACE. Non-compliance to this procedure could create race condition when the same SCID is reused for a new context.
Signed-off-by: Sandeep Nair <sandeep_n@ti.com>
-rw-r--r-- | drivers/crypto/keystone-sa.c | 34 | ||||
-rw-r--r-- | drivers/crypto/keystone-sa.h | 6 |
2 files changed, 37 insertions, 3 deletions
diff --git a/drivers/crypto/keystone-sa.c b/drivers/crypto/keystone-sa.c index b59cb1f3a49..bba1025ff81 100644 --- a/drivers/crypto/keystone-sa.c +++ b/drivers/crypto/keystone-sa.c | |||
@@ -2015,7 +2015,7 @@ static int sa_init_sc(struct sa_ctx_info *ctx, const u8 *enc_key, | |||
2015 | php_f = php_e = SA_CTX_DMA_SIZE_64; | 2015 | php_f = php_e = SA_CTX_DMA_SIZE_64; |
2016 | 2016 | ||
2017 | /* SCCTL Owner info: 0=host, 1=CP_ACE */ | 2017 | /* SCCTL Owner info: 0=host, 1=CP_ACE */ |
2018 | sc_buf[0] = 0; | 2018 | sc_buf[SA_CTX_SCCTL_OWNER_OFFSET] = 0; |
2019 | /* SCCTL F/E control */ | 2019 | /* SCCTL F/E control */ |
2020 | sc_buf[1] = SA_CTX_SCCTL_MK_DMA_INFO(php_f, eng0_f, eng1_f, php_e); | 2020 | sc_buf[1] = SA_CTX_SCCTL_MK_DMA_INFO(php_f, eng0_f, eng1_f, php_e); |
2021 | memcpy(&sc_buf[2], &sc_id, 2); /*(optional) | 2021 | memcpy(&sc_buf[2], &sc_id, 2); /*(optional) |
@@ -2045,7 +2045,7 @@ static int sa_init_sc(struct sa_ctx_info *ctx, const u8 *enc_key, | |||
2045 | } | 2045 | } |
2046 | 2046 | ||
2047 | /* Set the ownership of context to CP_ACE */ | 2047 | /* Set the ownership of context to CP_ACE */ |
2048 | sc_buf[0] = 0x80; | 2048 | sc_buf[SA_CTX_SCCTL_OWNER_OFFSET] = 0x80; |
2049 | 2049 | ||
2050 | /* swizzle the security context */ | 2050 | /* swizzle the security context */ |
2051 | sa_swiz_128(sc_buf, sc_buf, SA_CTX_MAX_SZ); | 2051 | sa_swiz_128(sc_buf, sc_buf, SA_CTX_MAX_SZ); |
@@ -2077,17 +2077,20 @@ static int sa_init_sc(struct sa_ctx_info *ctx, const u8 *enc_key, | |||
2077 | } | 2077 | } |
2078 | 2078 | ||
2079 | /* Tear down the Security Context */ | 2079 | /* Tear down the Security Context */ |
2080 | #define SA_SC_TEAR_RETRIES 5 | ||
2081 | #define SA_SC_TEAR_DELAY 20 /* msecs */ | ||
2080 | static int sa_tear_sc(struct sa_ctx_info *ctx, | 2082 | static int sa_tear_sc(struct sa_ctx_info *ctx, |
2081 | struct keystone_crypto_data *pdata) | 2083 | struct keystone_crypto_data *pdata) |
2082 | { | 2084 | { |
2085 | int own_off, cnt = SA_SC_TEAR_RETRIES; | ||
2083 | struct dma_async_tx_descriptor *desc; | 2086 | struct dma_async_tx_descriptor *desc; |
2084 | struct sa_dma_req_ctx *dma_ctx; | 2087 | struct sa_dma_req_ctx *dma_ctx; |
2085 | struct sa_swinfo swinfo; | 2088 | struct sa_swinfo swinfo; |
2086 | dma_cookie_t cookie; | 2089 | dma_cookie_t cookie; |
2087 | unsigned long flags; | 2090 | unsigned long flags; |
2088 | u16 queue_id; | 2091 | u16 queue_id; |
2089 | u8 flow_id; | ||
2090 | int ret = 0; | 2092 | int ret = 0; |
2093 | u8 flow_id; | ||
2091 | 2094 | ||
2092 | dma_ctx = kmalloc(sizeof(struct sa_dma_req_ctx), 0); | 2095 | dma_ctx = kmalloc(sizeof(struct sa_dma_req_ctx), 0); |
2093 | if (!dma_ctx) | 2096 | if (!dma_ctx) |
@@ -2152,6 +2155,22 @@ static int sa_tear_sc(struct sa_ctx_info *ctx, | |||
2152 | ret = -ENXIO; | 2155 | ret = -ENXIO; |
2153 | goto err; | 2156 | goto err; |
2154 | } | 2157 | } |
2158 | |||
2159 | /* | ||
2160 | * Check that CP_ACE has released the context | ||
2161 | * by making sure that the owner bit is 0 | ||
2162 | */ | ||
2163 | /* | ||
2164 | * Security context had been swizzled by 128 bits | ||
2165 | * before handing to CP_ACE | ||
2166 | */ | ||
2167 | own_off = ((SA_CTX_SCCTL_OWNER_OFFSET/16) * 16) | ||
2168 | + (15 - (SA_CTX_SCCTL_OWNER_OFFSET % 16)); | ||
2169 | while (__raw_readb(&ctx->sc[own_off])) { | ||
2170 | if (!--cnt) | ||
2171 | return -EAGAIN; | ||
2172 | msleep_interruptible(SA_SC_TEAR_DELAY); | ||
2173 | } | ||
2155 | return 0; | 2174 | return 0; |
2156 | 2175 | ||
2157 | err: | 2176 | err: |
@@ -2184,6 +2203,7 @@ static void sa_free_ctx_info | |||
2184 | if (sa_tear_sc(ctx, data)) { | 2203 | if (sa_tear_sc(ctx, data)) { |
2185 | dev_err(keystone_dev, | 2204 | dev_err(keystone_dev, |
2186 | "Failed to tear down context id(%x)\n", ctx->sc_id); | 2205 | "Failed to tear down context id(%x)\n", ctx->sc_id); |
2206 | return; | ||
2187 | } | 2207 | } |
2188 | 2208 | ||
2189 | bn = ctx->sc_id - data->sc_id_start; | 2209 | bn = ctx->sc_id - data->sc_id_start; |
@@ -2284,6 +2304,9 @@ static int sa_init_tfm(struct crypto_tfm *tfm) | |||
2284 | } | 2304 | } |
2285 | } | 2305 | } |
2286 | 2306 | ||
2307 | dev_dbg(keystone_dev, "%s(0x%p) sc-ids(0x%x(0x%x), 0x%x(0x%x))\n", | ||
2308 | __func__, tfm, ctx->enc.sc_id, ctx->enc.sc_phys, | ||
2309 | ctx->dec.sc_id, ctx->dec.sc_phys); | ||
2287 | return 0; | 2310 | return 0; |
2288 | } | 2311 | } |
2289 | 2312 | ||
@@ -2312,6 +2335,10 @@ static void sa_exit_tfm(struct crypto_tfm *tfm) | |||
2312 | struct sa_tfm_ctx *ctx = crypto_tfm_ctx(tfm); | 2335 | struct sa_tfm_ctx *ctx = crypto_tfm_ctx(tfm); |
2313 | struct keystone_crypto_data *data = dev_get_drvdata(keystone_dev); | 2336 | struct keystone_crypto_data *data = dev_get_drvdata(keystone_dev); |
2314 | 2337 | ||
2338 | dev_dbg(keystone_dev, "%s(0x%p) sc-ids(0x%x(0x%x), 0x%x(0x%x))\n", | ||
2339 | __func__, tfm, ctx->enc.sc_id, ctx->enc.sc_phys, | ||
2340 | ctx->dec.sc_id, ctx->dec.sc_phys); | ||
2341 | |||
2315 | if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) | 2342 | if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) |
2316 | == CRYPTO_ALG_TYPE_AEAD) { | 2343 | == CRYPTO_ALG_TYPE_AEAD) { |
2317 | sa_free_ctx_info(&ctx->enc, data); | 2344 | sa_free_ctx_info(&ctx->enc, data); |
@@ -3084,6 +3111,7 @@ static int keystone_crypto_remove(struct platform_device *pdev) | |||
3084 | 3111 | ||
3085 | /* un-register crypto algorithms */ | 3112 | /* un-register crypto algorithms */ |
3086 | sa_unregister_algos(&pdev->dev); | 3113 | sa_unregister_algos(&pdev->dev); |
3114 | dma_pool_destroy(crypto->sc_pool); | ||
3087 | clk_disable_unprepare(crypto->clk); | 3115 | clk_disable_unprepare(crypto->clk); |
3088 | clk_put(crypto->clk); | 3116 | clk_put(crypto->clk); |
3089 | kfree(crypto); | 3117 | kfree(crypto); |
diff --git a/drivers/crypto/keystone-sa.h b/drivers/crypto/keystone-sa.h index 5e6420f7a18..a390892485c 100644 --- a/drivers/crypto/keystone-sa.h +++ b/drivers/crypto/keystone-sa.h | |||
@@ -214,6 +214,12 @@ typedef u8 SA_CTX_PE_PKT_TYPE_T; | |||
214 | ((php_e) << 6)) | 214 | ((php_e) << 6)) |
215 | 215 | ||
216 | /* | 216 | /* |
217 | * Byte offset of the owner word in SCCTL | ||
218 | * in the security context | ||
219 | */ | ||
220 | #define SA_CTX_SCCTL_OWNER_OFFSET 0 | ||
221 | |||
222 | /* | ||
217 | * Assumption: CTX size is mutiple of 32 | 223 | * Assumption: CTX size is mutiple of 32 |
218 | */ | 224 | */ |
219 | #define SA_CTX_SIZE_TO_DMA_SIZE(ctx_sz) \ | 225 | #define SA_CTX_SIZE_TO_DMA_SIZE(ctx_sz) \ |