diff options
author | Lee Nipper <lee.nipper@gmail.com> | 2011-11-21 03:13:25 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2011-11-21 03:21:48 -0500 |
commit | 79b3a418e090248d00ceba40b81da9dfac753367 (patch) | |
tree | 99ac80d75596b08206e3397a632ff7df6b5ad015 | |
parent | d35643385628d44a5933a0755b01478eb4df5c65 (diff) |
crypto: talitos - add hmac algorithms
Add these hmac algorithms to talitos:
hmac(md5),
hmac(sha1),
hmac(sha224),
hmac(sha256),
hmac(sha384),
hmac(sha512).
These are all type ahash.
Signed-off-by: Lee Nipper <lee.nipper@gmail.com>
Fixed up to not register HMAC algorithms on sec2.0 devices.
Rationale (from Lee):
on an 8349E Rev1.1, there's a problem with hmac for any talitos
hmac sequence requiring an intermediate hash context (Pointer
DWORD 1); the result is an incorrect hmac. An intermediate hash
context is required for something longer than (65536-blocksize),
and for other cases when update/finup/final are used inefficiently.
Interestingly, a normal hash (without hmac) works perfectly
when using an intermediate context.
Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | drivers/crypto/talitos.c | 237 |
1 files changed, 235 insertions, 2 deletions
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index dbe76b5df9cf..8ce87317310b 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c | |||
@@ -157,6 +157,7 @@ struct talitos_private { | |||
157 | #define TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT 0x00000001 | 157 | #define TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT 0x00000001 |
158 | #define TALITOS_FTR_HW_AUTH_CHECK 0x00000002 | 158 | #define TALITOS_FTR_HW_AUTH_CHECK 0x00000002 |
159 | #define TALITOS_FTR_SHA224_HWINIT 0x00000004 | 159 | #define TALITOS_FTR_SHA224_HWINIT 0x00000004 |
160 | #define TALITOS_FTR_HMAC_OK 0x00000008 | ||
160 | 161 | ||
161 | static void to_talitos_ptr(struct talitos_ptr *talitos_ptr, dma_addr_t dma_addr) | 162 | static void to_talitos_ptr(struct talitos_ptr *talitos_ptr, dma_addr_t dma_addr) |
162 | { | 163 | { |
@@ -1874,6 +1875,97 @@ static int ahash_digest(struct ahash_request *areq) | |||
1874 | return ahash_process_req(areq, areq->nbytes); | 1875 | return ahash_process_req(areq, areq->nbytes); |
1875 | } | 1876 | } |
1876 | 1877 | ||
1878 | struct keyhash_result { | ||
1879 | struct completion completion; | ||
1880 | int err; | ||
1881 | }; | ||
1882 | |||
1883 | static void keyhash_complete(struct crypto_async_request *req, int err) | ||
1884 | { | ||
1885 | struct keyhash_result *res = req->data; | ||
1886 | |||
1887 | if (err == -EINPROGRESS) | ||
1888 | return; | ||
1889 | |||
1890 | res->err = err; | ||
1891 | complete(&res->completion); | ||
1892 | } | ||
1893 | |||
1894 | static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen, | ||
1895 | u8 *hash) | ||
1896 | { | ||
1897 | struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); | ||
1898 | |||
1899 | struct scatterlist sg[1]; | ||
1900 | struct ahash_request *req; | ||
1901 | struct keyhash_result hresult; | ||
1902 | int ret; | ||
1903 | |||
1904 | init_completion(&hresult.completion); | ||
1905 | |||
1906 | req = ahash_request_alloc(tfm, GFP_KERNEL); | ||
1907 | if (!req) | ||
1908 | return -ENOMEM; | ||
1909 | |||
1910 | /* Keep tfm keylen == 0 during hash of the long key */ | ||
1911 | ctx->keylen = 0; | ||
1912 | ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, | ||
1913 | keyhash_complete, &hresult); | ||
1914 | |||
1915 | sg_init_one(&sg[0], key, keylen); | ||
1916 | |||
1917 | ahash_request_set_crypt(req, sg, hash, keylen); | ||
1918 | ret = crypto_ahash_digest(req); | ||
1919 | switch (ret) { | ||
1920 | case 0: | ||
1921 | break; | ||
1922 | case -EINPROGRESS: | ||
1923 | case -EBUSY: | ||
1924 | ret = wait_for_completion_interruptible( | ||
1925 | &hresult.completion); | ||
1926 | if (!ret) | ||
1927 | ret = hresult.err; | ||
1928 | break; | ||
1929 | default: | ||
1930 | break; | ||
1931 | } | ||
1932 | ahash_request_free(req); | ||
1933 | |||
1934 | return ret; | ||
1935 | } | ||
1936 | |||
1937 | static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key, | ||
1938 | unsigned int keylen) | ||
1939 | { | ||
1940 | struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); | ||
1941 | unsigned int blocksize = | ||
1942 | crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); | ||
1943 | unsigned int digestsize = crypto_ahash_digestsize(tfm); | ||
1944 | unsigned int keysize = keylen; | ||
1945 | u8 hash[SHA512_DIGEST_SIZE]; | ||
1946 | int ret; | ||
1947 | |||
1948 | if (keylen <= blocksize) | ||
1949 | memcpy(ctx->key, key, keysize); | ||
1950 | else { | ||
1951 | /* Must get the hash of the long key */ | ||
1952 | ret = keyhash(tfm, key, keylen, hash); | ||
1953 | |||
1954 | if (ret) { | ||
1955 | crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); | ||
1956 | return -EINVAL; | ||
1957 | } | ||
1958 | |||
1959 | keysize = digestsize; | ||
1960 | memcpy(ctx->key, hash, digestsize); | ||
1961 | } | ||
1962 | |||
1963 | ctx->keylen = keysize; | ||
1964 | |||
1965 | return 0; | ||
1966 | } | ||
1967 | |||
1968 | |||
1877 | struct talitos_alg_template { | 1969 | struct talitos_alg_template { |
1878 | u32 type; | 1970 | u32 type; |
1879 | union { | 1971 | union { |
@@ -2217,6 +2309,138 @@ static struct talitos_alg_template driver_algs[] = { | |||
2217 | DESC_HDR_SEL0_MDEUB | | 2309 | DESC_HDR_SEL0_MDEUB | |
2218 | DESC_HDR_MODE0_MDEUB_SHA512, | 2310 | DESC_HDR_MODE0_MDEUB_SHA512, |
2219 | }, | 2311 | }, |
2312 | { .type = CRYPTO_ALG_TYPE_AHASH, | ||
2313 | .alg.hash = { | ||
2314 | .init = ahash_init, | ||
2315 | .update = ahash_update, | ||
2316 | .final = ahash_final, | ||
2317 | .finup = ahash_finup, | ||
2318 | .digest = ahash_digest, | ||
2319 | .setkey = ahash_setkey, | ||
2320 | .halg.digestsize = MD5_DIGEST_SIZE, | ||
2321 | .halg.base = { | ||
2322 | .cra_name = "hmac(md5)", | ||
2323 | .cra_driver_name = "hmac-md5-talitos", | ||
2324 | .cra_blocksize = MD5_BLOCK_SIZE, | ||
2325 | .cra_flags = CRYPTO_ALG_TYPE_AHASH | | ||
2326 | CRYPTO_ALG_ASYNC, | ||
2327 | .cra_type = &crypto_ahash_type | ||
2328 | } | ||
2329 | }, | ||
2330 | .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | | ||
2331 | DESC_HDR_SEL0_MDEUA | | ||
2332 | DESC_HDR_MODE0_MDEU_MD5, | ||
2333 | }, | ||
2334 | { .type = CRYPTO_ALG_TYPE_AHASH, | ||
2335 | .alg.hash = { | ||
2336 | .init = ahash_init, | ||
2337 | .update = ahash_update, | ||
2338 | .final = ahash_final, | ||
2339 | .finup = ahash_finup, | ||
2340 | .digest = ahash_digest, | ||
2341 | .setkey = ahash_setkey, | ||
2342 | .halg.digestsize = SHA1_DIGEST_SIZE, | ||
2343 | .halg.base = { | ||
2344 | .cra_name = "hmac(sha1)", | ||
2345 | .cra_driver_name = "hmac-sha1-talitos", | ||
2346 | .cra_blocksize = SHA1_BLOCK_SIZE, | ||
2347 | .cra_flags = CRYPTO_ALG_TYPE_AHASH | | ||
2348 | CRYPTO_ALG_ASYNC, | ||
2349 | .cra_type = &crypto_ahash_type | ||
2350 | } | ||
2351 | }, | ||
2352 | .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | | ||
2353 | DESC_HDR_SEL0_MDEUA | | ||
2354 | DESC_HDR_MODE0_MDEU_SHA1, | ||
2355 | }, | ||
2356 | { .type = CRYPTO_ALG_TYPE_AHASH, | ||
2357 | .alg.hash = { | ||
2358 | .init = ahash_init, | ||
2359 | .update = ahash_update, | ||
2360 | .final = ahash_final, | ||
2361 | .finup = ahash_finup, | ||
2362 | .digest = ahash_digest, | ||
2363 | .setkey = ahash_setkey, | ||
2364 | .halg.digestsize = SHA224_DIGEST_SIZE, | ||
2365 | .halg.base = { | ||
2366 | .cra_name = "hmac(sha224)", | ||
2367 | .cra_driver_name = "hmac-sha224-talitos", | ||
2368 | .cra_blocksize = SHA224_BLOCK_SIZE, | ||
2369 | .cra_flags = CRYPTO_ALG_TYPE_AHASH | | ||
2370 | CRYPTO_ALG_ASYNC, | ||
2371 | .cra_type = &crypto_ahash_type | ||
2372 | } | ||
2373 | }, | ||
2374 | .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | | ||
2375 | DESC_HDR_SEL0_MDEUA | | ||
2376 | DESC_HDR_MODE0_MDEU_SHA224, | ||
2377 | }, | ||
2378 | { .type = CRYPTO_ALG_TYPE_AHASH, | ||
2379 | .alg.hash = { | ||
2380 | .init = ahash_init, | ||
2381 | .update = ahash_update, | ||
2382 | .final = ahash_final, | ||
2383 | .finup = ahash_finup, | ||
2384 | .digest = ahash_digest, | ||
2385 | .setkey = ahash_setkey, | ||
2386 | .halg.digestsize = SHA256_DIGEST_SIZE, | ||
2387 | .halg.base = { | ||
2388 | .cra_name = "hmac(sha256)", | ||
2389 | .cra_driver_name = "hmac-sha256-talitos", | ||
2390 | .cra_blocksize = SHA256_BLOCK_SIZE, | ||
2391 | .cra_flags = CRYPTO_ALG_TYPE_AHASH | | ||
2392 | CRYPTO_ALG_ASYNC, | ||
2393 | .cra_type = &crypto_ahash_type | ||
2394 | } | ||
2395 | }, | ||
2396 | .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | | ||
2397 | DESC_HDR_SEL0_MDEUA | | ||
2398 | DESC_HDR_MODE0_MDEU_SHA256, | ||
2399 | }, | ||
2400 | { .type = CRYPTO_ALG_TYPE_AHASH, | ||
2401 | .alg.hash = { | ||
2402 | .init = ahash_init, | ||
2403 | .update = ahash_update, | ||
2404 | .final = ahash_final, | ||
2405 | .finup = ahash_finup, | ||
2406 | .digest = ahash_digest, | ||
2407 | .setkey = ahash_setkey, | ||
2408 | .halg.digestsize = SHA384_DIGEST_SIZE, | ||
2409 | .halg.base = { | ||
2410 | .cra_name = "hmac(sha384)", | ||
2411 | .cra_driver_name = "hmac-sha384-talitos", | ||
2412 | .cra_blocksize = SHA384_BLOCK_SIZE, | ||
2413 | .cra_flags = CRYPTO_ALG_TYPE_AHASH | | ||
2414 | CRYPTO_ALG_ASYNC, | ||
2415 | .cra_type = &crypto_ahash_type | ||
2416 | } | ||
2417 | }, | ||
2418 | .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | | ||
2419 | DESC_HDR_SEL0_MDEUB | | ||
2420 | DESC_HDR_MODE0_MDEUB_SHA384, | ||
2421 | }, | ||
2422 | { .type = CRYPTO_ALG_TYPE_AHASH, | ||
2423 | .alg.hash = { | ||
2424 | .init = ahash_init, | ||
2425 | .update = ahash_update, | ||
2426 | .final = ahash_final, | ||
2427 | .finup = ahash_finup, | ||
2428 | .digest = ahash_digest, | ||
2429 | .setkey = ahash_setkey, | ||
2430 | .halg.digestsize = SHA512_DIGEST_SIZE, | ||
2431 | .halg.base = { | ||
2432 | .cra_name = "hmac(sha512)", | ||
2433 | .cra_driver_name = "hmac-sha512-talitos", | ||
2434 | .cra_blocksize = SHA512_BLOCK_SIZE, | ||
2435 | .cra_flags = CRYPTO_ALG_TYPE_AHASH | | ||
2436 | CRYPTO_ALG_ASYNC, | ||
2437 | .cra_type = &crypto_ahash_type | ||
2438 | } | ||
2439 | }, | ||
2440 | .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | | ||
2441 | DESC_HDR_SEL0_MDEUB | | ||
2442 | DESC_HDR_MODE0_MDEUB_SHA512, | ||
2443 | } | ||
2220 | }; | 2444 | }; |
2221 | 2445 | ||
2222 | struct talitos_crypto_alg { | 2446 | struct talitos_crypto_alg { |
@@ -2373,8 +2597,12 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, | |||
2373 | case CRYPTO_ALG_TYPE_AHASH: | 2597 | case CRYPTO_ALG_TYPE_AHASH: |
2374 | alg = &t_alg->algt.alg.hash.halg.base; | 2598 | alg = &t_alg->algt.alg.hash.halg.base; |
2375 | alg->cra_init = talitos_cra_init_ahash; | 2599 | alg->cra_init = talitos_cra_init_ahash; |
2600 | if (!(priv->features & TALITOS_FTR_HMAC_OK) && | ||
2601 | !strncmp(alg->cra_name, "hmac", 4)) | ||
2602 | return ERR_PTR(-ENOTSUPP); | ||
2376 | if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) && | 2603 | if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) && |
2377 | !strcmp(alg->cra_name, "sha224")) { | 2604 | (!strcmp(alg->cra_name, "sha224") || |
2605 | !strcmp(alg->cra_name, "hmac(sha224)"))) { | ||
2378 | t_alg->algt.alg.hash.init = ahash_init_sha224_swinit; | 2606 | t_alg->algt.alg.hash.init = ahash_init_sha224_swinit; |
2379 | t_alg->algt.desc_hdr_template = | 2607 | t_alg->algt.desc_hdr_template = |
2380 | DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | | 2608 | DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU | |
@@ -2471,7 +2699,8 @@ static int talitos_probe(struct platform_device *ofdev) | |||
2471 | 2699 | ||
2472 | if (of_device_is_compatible(np, "fsl,sec2.1")) | 2700 | if (of_device_is_compatible(np, "fsl,sec2.1")) |
2473 | priv->features |= TALITOS_FTR_HW_AUTH_CHECK | | 2701 | priv->features |= TALITOS_FTR_HW_AUTH_CHECK | |
2474 | TALITOS_FTR_SHA224_HWINIT; | 2702 | TALITOS_FTR_SHA224_HWINIT | |
2703 | TALITOS_FTR_HMAC_OK; | ||
2475 | 2704 | ||
2476 | priv->chan = kzalloc(sizeof(struct talitos_channel) * | 2705 | priv->chan = kzalloc(sizeof(struct talitos_channel) * |
2477 | priv->num_channels, GFP_KERNEL); | 2706 | priv->num_channels, GFP_KERNEL); |
@@ -2530,6 +2759,10 @@ static int talitos_probe(struct platform_device *ofdev) | |||
2530 | t_alg = talitos_alg_alloc(dev, &driver_algs[i]); | 2759 | t_alg = talitos_alg_alloc(dev, &driver_algs[i]); |
2531 | if (IS_ERR(t_alg)) { | 2760 | if (IS_ERR(t_alg)) { |
2532 | err = PTR_ERR(t_alg); | 2761 | err = PTR_ERR(t_alg); |
2762 | if (err == -ENOTSUPP) { | ||
2763 | kfree(t_alg); | ||
2764 | continue; | ||
2765 | } | ||
2533 | goto err_out; | 2766 | goto err_out; |
2534 | } | 2767 | } |
2535 | 2768 | ||