Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

crypto: hisilicon/sec2 - fix for sec spec check

During encryption and decryption, user requests
must be checked first, if the specifications that
are not supported by the hardware are used, the
software computing is used for processing.

Fixes: 2f072d75d1ab ("crypto: hisilicon - Add aead support on SEC2")
Signed-off-by: Wenkai Lin <linwenkai6@hisilicon.com>
Signed-off-by: Chenghai Huang <huangchenghai2@huawei.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Wenkai Lin and committed by
Herbert Xu
f4f353cb a49cc71e

+39 -63
-1
drivers/crypto/hisilicon/sec2/sec.h
··· 37 37 u8 *a_ivin; 38 38 dma_addr_t a_ivin_dma; 39 39 struct aead_request *aead_req; 40 - bool fallback; 41 40 }; 42 41 43 42 /* SEC request of Crypto */
+39 -62
drivers/crypto/hisilicon/sec2/sec_crypto.c
··· 690 690 691 691 c_ctx->fallback = false; 692 692 693 - /* Currently, only XTS mode need fallback tfm when using 192bit key */ 694 - if (likely(strncmp(alg, "xts", SEC_XTS_NAME_SZ))) 695 - return 0; 696 - 697 693 c_ctx->fbtfm = crypto_alloc_sync_skcipher(alg, 0, 698 694 CRYPTO_ALG_NEED_FALLBACK); 699 695 if (IS_ERR(c_ctx->fbtfm)) { 700 - pr_err("failed to alloc xts mode fallback tfm!\n"); 696 + pr_err("failed to alloc fallback tfm for %s!\n", alg); 701 697 return PTR_ERR(c_ctx->fbtfm); 702 698 } 703 699 ··· 853 857 } 854 858 855 859 memcpy(c_ctx->c_key, key, keylen); 856 - if (c_ctx->fallback && c_ctx->fbtfm) { 860 + if (c_ctx->fbtfm) { 857 861 ret = crypto_sync_skcipher_setkey(c_ctx->fbtfm, key, keylen); 858 862 if (ret) { 859 863 dev_err(dev, "failed to set fallback skcipher key!\n"); ··· 1151 1155 } 1152 1156 1153 1157 ret = crypto_authenc_extractkeys(&keys, key, keylen); 1154 - if (ret) 1158 + if (ret) { 1159 + dev_err(dev, "sec extract aead keys err!\n"); 1155 1160 goto bad_key; 1161 + } 1156 1162 1157 1163 ret = sec_aead_aes_set_key(c_ctx, &keys); 1158 1164 if (ret) { ··· 1165 1167 ret = sec_aead_auth_set_key(&ctx->a_ctx, &keys); 1166 1168 if (ret) { 1167 1169 dev_err(dev, "set sec auth key err!\n"); 1168 - goto bad_key; 1169 - } 1170 - 1171 - if (ctx->a_ctx.a_key_len & WORD_MASK) { 1172 - ret = -EINVAL; 1173 - dev_err(dev, "AUTH key length error!\n"); 1174 1170 goto bad_key; 1175 1171 } 1176 1172 ··· 1987 1995 return sec_aead_ctx_init(tfm, "sha512"); 1988 1996 } 1989 1997 1990 - static int sec_skcipher_cryptlen_check(struct sec_ctx *ctx, 1991 - struct sec_req *sreq) 1998 + static int sec_skcipher_cryptlen_check(struct sec_ctx *ctx, struct sec_req *sreq) 1992 1999 { 1993 2000 u32 cryptlen = sreq->c_req.sk_req->cryptlen; 1994 2001 struct device *dev = ctx->dev; ··· 2009 2018 } 2010 2019 break; 2011 2020 case SEC_CMODE_CTR: 2012 - if (unlikely(ctx->sec->qm.ver < QM_HW_V3)) { 2013 - dev_err(dev, "skcipher HW version error!\n"); 2014 - ret = -EINVAL; 2015 - } 2016 2021 break; 2017 2022 default: 2018 2023 ret = -EINVAL; ··· 2017 2030 return ret; 2018 2031 } 2019 2032 2020 - static int sec_skcipher_param_check(struct sec_ctx *ctx, struct sec_req *sreq) 2033 + static int sec_skcipher_param_check(struct sec_ctx *ctx, 2034 + struct sec_req *sreq, bool *need_fallback) 2021 2035 { 2022 2036 struct skcipher_request *sk_req = sreq->c_req.sk_req; 2023 2037 struct device *dev = ctx->dev; 2024 2038 u8 c_alg = ctx->c_ctx.c_alg; 2025 2039 2026 - if (unlikely(!sk_req->src || !sk_req->dst || 2027 - sk_req->cryptlen > MAX_INPUT_DATA_LEN)) { 2040 + if (unlikely(!sk_req->src || !sk_req->dst)) { 2028 2041 dev_err(dev, "skcipher input param error!\n"); 2029 2042 return -EINVAL; 2030 2043 } 2044 + 2045 + if (sk_req->cryptlen > MAX_INPUT_DATA_LEN) 2046 + *need_fallback = true; 2047 + 2031 2048 sreq->c_req.c_len = sk_req->cryptlen; 2032 2049 2033 2050 if (ctx->pbuf_supported && sk_req->cryptlen <= SEC_PBUF_SZ) ··· 2089 2098 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(sk_req); 2090 2099 struct sec_req *req = skcipher_request_ctx(sk_req); 2091 2100 struct sec_ctx *ctx = crypto_skcipher_ctx(tfm); 2101 + bool need_fallback = false; 2092 2102 int ret; 2093 2103 2094 2104 if (!sk_req->cryptlen) { ··· 2103 2111 req->c_req.encrypt = encrypt; 2104 2112 req->ctx = ctx; 2105 2113 2106 - ret = sec_skcipher_param_check(ctx, req); 2114 + ret = sec_skcipher_param_check(ctx, req, &need_fallback); 2107 2115 if (unlikely(ret)) 2108 2116 return -EINVAL; 2109 2117 2110 - if (unlikely(ctx->c_ctx.fallback)) 2118 + if (unlikely(ctx->c_ctx.fallback || need_fallback)) 2111 2119 return sec_skcipher_soft_crypto(ctx, sk_req, encrypt); 2112 2120 2113 2121 return ctx->req_op->process(ctx, req); ··· 2215 2223 struct crypto_aead *tfm = crypto_aead_reqtfm(req); 2216 2224 size_t sz = crypto_aead_authsize(tfm); 2217 2225 u8 c_mode = ctx->c_ctx.c_mode; 2218 - struct device *dev = ctx->dev; 2219 2226 int ret; 2220 2227 2221 - /* Hardware does not handle cases where authsize is not 4 bytes aligned */ 2222 - if (c_mode == SEC_CMODE_CBC && (sz & WORD_MASK)) { 2223 - sreq->aead_req.fallback = true; 2228 + if (unlikely(ctx->sec->qm.ver == QM_HW_V2 && !sreq->c_req.c_len)) 2224 2229 return -EINVAL; 2225 - } 2226 2230 2227 2231 if (unlikely(req->cryptlen + req->assoclen > MAX_INPUT_DATA_LEN || 2228 - req->assoclen > SEC_MAX_AAD_LEN)) { 2229 - dev_err(dev, "aead input spec error!\n"); 2232 + req->assoclen > SEC_MAX_AAD_LEN)) 2230 2233 return -EINVAL; 2231 - } 2232 2234 2233 2235 if (c_mode == SEC_CMODE_CCM) { 2234 - if (unlikely(req->assoclen > SEC_MAX_CCM_AAD_LEN)) { 2235 - dev_err_ratelimited(dev, "CCM input aad parameter is too long!\n"); 2236 + if (unlikely(req->assoclen > SEC_MAX_CCM_AAD_LEN)) 2236 2237 return -EINVAL; 2237 - } 2238 - ret = aead_iv_demension_check(req); 2239 - if (ret) { 2240 - dev_err(dev, "aead input iv param error!\n"); 2241 - return ret; 2242 - } 2243 - } 2244 2238 2245 - if (sreq->c_req.encrypt) 2246 - sreq->c_req.c_len = req->cryptlen; 2247 - else 2248 - sreq->c_req.c_len = req->cryptlen - sz; 2249 - if (c_mode == SEC_CMODE_CBC) { 2250 - if (unlikely(sreq->c_req.c_len & (AES_BLOCK_SIZE - 1))) { 2251 - dev_err(dev, "aead crypto length error!\n"); 2239 + ret = aead_iv_demension_check(req); 2240 + if (unlikely(ret)) 2252 2241 return -EINVAL; 2253 - } 2242 + } else if (c_mode == SEC_CMODE_CBC) { 2243 + if (unlikely(sz & WORD_MASK)) 2244 + return -EINVAL; 2245 + if (unlikely(ctx->a_ctx.a_key_len & WORD_MASK)) 2246 + return -EINVAL; 2254 2247 } 2255 2248 2256 2249 return 0; 2257 2250 } 2258 2251 2259 - static int sec_aead_param_check(struct sec_ctx *ctx, struct sec_req *sreq) 2252 + static int sec_aead_param_check(struct sec_ctx *ctx, struct sec_req *sreq, bool *need_fallback) 2260 2253 { 2261 2254 struct aead_request *req = sreq->aead_req.aead_req; 2262 - struct crypto_aead *tfm = crypto_aead_reqtfm(req); 2263 - size_t authsize = crypto_aead_authsize(tfm); 2264 2255 struct device *dev = ctx->dev; 2265 2256 u8 c_alg = ctx->c_ctx.c_alg; 2266 2257 ··· 2252 2277 return -EINVAL; 2253 2278 } 2254 2279 2255 - if (ctx->sec->qm.ver == QM_HW_V2) { 2256 - if (unlikely(!req->cryptlen || (!sreq->c_req.encrypt && 2257 - req->cryptlen <= authsize))) { 2258 - sreq->aead_req.fallback = true; 2259 - return -EINVAL; 2260 - } 2280 + if (unlikely(ctx->c_ctx.c_mode == SEC_CMODE_CBC && 2281 + sreq->c_req.c_len & (AES_BLOCK_SIZE - 1))) { 2282 + dev_err(dev, "aead cbc mode input data length error!\n"); 2283 + return -EINVAL; 2261 2284 } 2262 2285 2263 2286 /* Support AES or SM4 */ ··· 2264 2291 return -EINVAL; 2265 2292 } 2266 2293 2267 - if (unlikely(sec_aead_spec_check(ctx, sreq))) 2294 + if (unlikely(sec_aead_spec_check(ctx, sreq))) { 2295 + *need_fallback = true; 2268 2296 return -EINVAL; 2297 + } 2269 2298 2270 2299 if (ctx->pbuf_supported && (req->cryptlen + req->assoclen) <= 2271 2300 SEC_PBUF_SZ) ··· 2311 2336 struct crypto_aead *tfm = crypto_aead_reqtfm(a_req); 2312 2337 struct sec_req *req = aead_request_ctx(a_req); 2313 2338 struct sec_ctx *ctx = crypto_aead_ctx(tfm); 2339 + size_t sz = crypto_aead_authsize(tfm); 2340 + bool need_fallback = false; 2314 2341 int ret; 2315 2342 2316 2343 req->flag = a_req->base.flags; 2317 2344 req->aead_req.aead_req = a_req; 2318 2345 req->c_req.encrypt = encrypt; 2319 2346 req->ctx = ctx; 2320 - req->aead_req.fallback = false; 2347 + req->c_req.c_len = a_req->cryptlen - (req->c_req.encrypt ? 0 : sz); 2321 2348 2322 - ret = sec_aead_param_check(ctx, req); 2349 + ret = sec_aead_param_check(ctx, req, &need_fallback); 2323 2350 if (unlikely(ret)) { 2324 - if (req->aead_req.fallback) 2351 + if (need_fallback) 2325 2352 return sec_aead_soft_crypto(ctx, a_req, encrypt); 2326 2353 return -EINVAL; 2327 2354 }