aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Mueller <smueller@chronox.de>2016-06-14 01:34:13 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2016-06-15 05:07:53 -0400
commit355912852115cd8aa4ad02c25182ae615ce925fb (patch)
treef25c7201d6538cebae6a4d5ded1998a2164717de
parente123be16120df6cdda4e1811a49326125f0aa4dd (diff)
crypto: drbg - use CTR AES instead of ECB AES
The CTR DRBG derives its random data from the CTR that is encrypted with AES. This patch now changes the CTR DRBG implementation such that the CTR AES mode is employed. This allows the use of steamlined CTR AES implementation such as ctr-aes-aesni. Unfortunately there are the following subtile changes we need to apply when using the CTR AES mode: - the CTR mode increments the counter after the cipher operation, but the CTR DRBG requires the increment before the cipher op. Hence, the crypto_inc is applied to the counter (drbg->V) once it is recalculated. - the CTR mode wants to encrypt data, but the CTR DRBG is interested in the encrypted counter only. The full CTR mode is the XOR of the encrypted counter with the plaintext data. To access the encrypted counter, the patch uses a NULL data vector as plaintext to be "encrypted". Signed-off-by: Stephan Mueller <smueller@chronox.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--crypto/Kconfig1
-rw-r--r--crypto/drbg.c193
-rw-r--r--include/crypto/drbg.h9
3 files changed, 149 insertions, 54 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 1d33beb6a1ae..c903f1832f2c 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1567,6 +1567,7 @@ config CRYPTO_DRBG_HASH
1567config CRYPTO_DRBG_CTR 1567config CRYPTO_DRBG_CTR
1568 bool "Enable CTR DRBG" 1568 bool "Enable CTR DRBG"
1569 select CRYPTO_AES 1569 select CRYPTO_AES
1570 depends on CRYPTO_CTR
1570 help 1571 help
1571 Enable the CTR DRBG variant as defined in NIST SP800-90A. 1572 Enable the CTR DRBG variant as defined in NIST SP800-90A.
1572 1573
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 0aca2b908c76..4ee1a9c79420 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -258,6 +258,7 @@ static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *outval,
258 const struct drbg_string *in); 258 const struct drbg_string *in);
259static int drbg_init_sym_kernel(struct drbg_state *drbg); 259static int drbg_init_sym_kernel(struct drbg_state *drbg);
260static int drbg_fini_sym_kernel(struct drbg_state *drbg); 260static int drbg_fini_sym_kernel(struct drbg_state *drbg);
261static int drbg_kcapi_sym_ctr(struct drbg_state *drbg, u8 *outbuf, u32 outlen);
261 262
262/* BCC function for CTR DRBG as defined in 10.4.3 */ 263/* BCC function for CTR DRBG as defined in 10.4.3 */
263static int drbg_ctr_bcc(struct drbg_state *drbg, 264static int drbg_ctr_bcc(struct drbg_state *drbg,
@@ -482,36 +483,37 @@ static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed,
482 drbg_blocklen(drbg); 483 drbg_blocklen(drbg);
483 unsigned char *temp_p, *df_data_p; /* pointer to iterate over buffers */ 484 unsigned char *temp_p, *df_data_p; /* pointer to iterate over buffers */
484 unsigned int len = 0; 485 unsigned int len = 0;
485 struct drbg_string cipherin;
486 486
487 if (3 > reseed) 487 if (3 > reseed)
488 memset(df_data, 0, drbg_statelen(drbg)); 488 memset(df_data, 0, drbg_statelen(drbg));
489 489
490 /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */ 490 if (!reseed) {
491 if (seed) { 491 /*
492 ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg), seed); 492 * The DRBG uses the CTR mode of the underlying AES cipher. The
493 * CTR mode increments the counter value after the AES operation
494 * but SP800-90A requires that the counter is incremented before
495 * the AES operation. Hence, we increment it at the time we set
496 * it by one.
497 */
498 crypto_inc(drbg->V, drbg_blocklen(drbg));
499
500 ret = crypto_skcipher_setkey(drbg->ctr_handle, drbg->C,
501 drbg_keylen(drbg));
493 if (ret) 502 if (ret)
494 goto out; 503 goto out;
495 drbg_kcapi_symsetkey(drbg, drbg->C);
496 } 504 }
497 505
498 drbg_string_fill(&cipherin, drbg->V, drbg_blocklen(drbg)); 506 /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
499 /* 507 if (seed) {
500 * 10.2.1.3.2 steps 2 and 3 are already covered as the allocation 508 ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg), seed);
501 * zeroizes all memory during initialization
502 */
503 while (len < (drbg_statelen(drbg))) {
504 /* 10.2.1.2 step 2.1 */
505 crypto_inc(drbg->V, drbg_blocklen(drbg));
506 /*
507 * 10.2.1.2 step 2.2 */
508 ret = drbg_kcapi_sym(drbg, temp + len, &cipherin);
509 if (ret) 509 if (ret)
510 goto out; 510 goto out;
511 /* 10.2.1.2 step 2.3 and 3 */
512 len += drbg_blocklen(drbg);
513 } 511 }
514 512
513 ret = drbg_kcapi_sym_ctr(drbg, temp, drbg_statelen(drbg));
514 if (ret)
515 return ret;
516
515 /* 10.2.1.2 step 4 */ 517 /* 10.2.1.2 step 4 */
516 temp_p = temp; 518 temp_p = temp;
517 df_data_p = df_data; 519 df_data_p = df_data;
@@ -522,9 +524,14 @@ static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed,
522 524
523 /* 10.2.1.2 step 5 */ 525 /* 10.2.1.2 step 5 */
524 memcpy(drbg->C, temp, drbg_keylen(drbg)); 526 memcpy(drbg->C, temp, drbg_keylen(drbg));
525 drbg_kcapi_symsetkey(drbg, drbg->C); 527 ret = crypto_skcipher_setkey(drbg->ctr_handle, drbg->C,
528 drbg_keylen(drbg));
529 if (ret)
530 goto out;
526 /* 10.2.1.2 step 6 */ 531 /* 10.2.1.2 step 6 */
527 memcpy(drbg->V, temp + drbg_keylen(drbg), drbg_blocklen(drbg)); 532 memcpy(drbg->V, temp + drbg_keylen(drbg), drbg_blocklen(drbg));
533 /* See above: increment counter by one to compensate timing of CTR op */
534 crypto_inc(drbg->V, drbg_blocklen(drbg));
528 ret = 0; 535 ret = 0;
529 536
530out: 537out:
@@ -543,46 +550,26 @@ static int drbg_ctr_generate(struct drbg_state *drbg,
543 unsigned char *buf, unsigned int buflen, 550 unsigned char *buf, unsigned int buflen,
544 struct list_head *addtl) 551 struct list_head *addtl)
545{ 552{
546 int len = 0; 553 int ret;
547 int ret = 0; 554 int len = min_t(int, buflen, INT_MAX);
548 struct drbg_string data;
549 555
550 /* 10.2.1.5.2 step 2 */ 556 /* 10.2.1.5.2 step 2 */
551 if (addtl && !list_empty(addtl)) { 557 if (addtl && !list_empty(addtl)) {
552 ret = drbg_ctr_update(drbg, addtl, 2); 558 ret = drbg_ctr_update(drbg, addtl, 2);
553 if (ret) 559 if (ret)
554 return 0; 560 return 0;
555 drbg_kcapi_symsetkey(drbg, drbg->C);
556 } 561 }
557 562
558 /* 10.2.1.5.2 step 4.1 */ 563 /* 10.2.1.5.2 step 4.1 */
559 crypto_inc(drbg->V, drbg_blocklen(drbg)); 564 ret = drbg_kcapi_sym_ctr(drbg, buf, len);
560 drbg_string_fill(&data, drbg->V, drbg_blocklen(drbg)); 565 if (ret)
561 while (len < buflen) { 566 return ret;
562 int outlen = 0;
563 /* 10.2.1.5.2 step 4.2 */
564 ret = drbg_kcapi_sym(drbg, drbg->scratchpad, &data);
565 if (ret) {
566 len = ret;
567 goto out;
568 }
569 outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
570 drbg_blocklen(drbg) : (buflen - len);
571 /* 10.2.1.5.2 step 4.3 */
572 memcpy(buf + len, drbg->scratchpad, outlen);
573 len += outlen;
574 /* 10.2.1.5.2 step 6 */
575 if (len < buflen)
576 crypto_inc(drbg->V, drbg_blocklen(drbg));
577 }
578 567
579 /* 10.2.1.5.2 step 6 */ 568 /* 10.2.1.5.2 step 6 */
580 ret = drbg_ctr_update(drbg, NULL, 3); 569 ret = drbg_ctr_update(drbg, NULL, 3);
581 if (ret) 570 if (ret)
582 len = ret; 571 len = ret;
583 572
584out:
585 memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
586 return len; 573 return len;
587} 574}
588 575
@@ -1634,10 +1621,46 @@ static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
1634#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */ 1621#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
1635 1622
1636#ifdef CONFIG_CRYPTO_DRBG_CTR 1623#ifdef CONFIG_CRYPTO_DRBG_CTR
1624static int drbg_fini_sym_kernel(struct drbg_state *drbg)
1625{
1626 struct crypto_cipher *tfm =
1627 (struct crypto_cipher *)drbg->priv_data;
1628 if (tfm)
1629 crypto_free_cipher(tfm);
1630 drbg->priv_data = NULL;
1631
1632 if (drbg->ctr_handle)
1633 crypto_free_skcipher(drbg->ctr_handle);
1634 drbg->ctr_handle = NULL;
1635
1636 if (drbg->ctr_req)
1637 skcipher_request_free(drbg->ctr_req);;
1638 drbg->ctr_req = NULL;
1639
1640 kfree(drbg->ctr_null_value_buf);
1641 drbg->ctr_null_value = NULL;
1642
1643 return 0;
1644}
1645
1646static void drbg_skcipher_cb(struct crypto_async_request *req, int error)
1647{
1648 struct drbg_state *drbg = req->data;
1649
1650 if (error == -EINPROGRESS)
1651 return;
1652 drbg->ctr_async_err = error;
1653 complete(&drbg->ctr_completion);
1654}
1655
1656#define DRBG_CTR_NULL_LEN 128
1637static int drbg_init_sym_kernel(struct drbg_state *drbg) 1657static int drbg_init_sym_kernel(struct drbg_state *drbg)
1638{ 1658{
1639 int ret = 0;
1640 struct crypto_cipher *tfm; 1659 struct crypto_cipher *tfm;
1660 struct crypto_skcipher *sk_tfm;
1661 struct skcipher_request *req;
1662 unsigned int alignmask;
1663 char ctr_name[CRYPTO_MAX_ALG_NAME];
1641 1664
1642 tfm = crypto_alloc_cipher(drbg->core->backend_cra_name, 0, 0); 1665 tfm = crypto_alloc_cipher(drbg->core->backend_cra_name, 0, 0);
1643 if (IS_ERR(tfm)) { 1666 if (IS_ERR(tfm)) {
@@ -1647,16 +1670,41 @@ static int drbg_init_sym_kernel(struct drbg_state *drbg)
1647 } 1670 }
1648 BUG_ON(drbg_blocklen(drbg) != crypto_cipher_blocksize(tfm)); 1671 BUG_ON(drbg_blocklen(drbg) != crypto_cipher_blocksize(tfm));
1649 drbg->priv_data = tfm; 1672 drbg->priv_data = tfm;
1650 return ret;
1651}
1652 1673
1653static int drbg_fini_sym_kernel(struct drbg_state *drbg) 1674 if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)",
1654{ 1675 drbg->core->backend_cra_name) >= CRYPTO_MAX_ALG_NAME) {
1655 struct crypto_cipher *tfm = 1676 drbg_fini_sym_kernel(drbg);
1656 (struct crypto_cipher *)drbg->priv_data; 1677 return -EINVAL;
1657 if (tfm) 1678 }
1658 crypto_free_cipher(tfm); 1679 sk_tfm = crypto_alloc_skcipher(ctr_name, 0, 0);
1659 drbg->priv_data = NULL; 1680 if (IS_ERR(sk_tfm)) {
1681 pr_info("DRBG: could not allocate CTR cipher TFM handle: %s\n",
1682 ctr_name);
1683 drbg_fini_sym_kernel(drbg);
1684 return PTR_ERR(sk_tfm);
1685 }
1686 drbg->ctr_handle = sk_tfm;
1687
1688 req = skcipher_request_alloc(sk_tfm, GFP_KERNEL);
1689 if (!req) {
1690 pr_info("DRBG: could not allocate request queue\n");
1691 drbg_fini_sym_kernel(drbg);
1692 return PTR_ERR(req);
1693 }
1694 drbg->ctr_req = req;
1695 skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
1696 drbg_skcipher_cb, drbg);
1697
1698 alignmask = crypto_skcipher_alignmask(sk_tfm);
1699 drbg->ctr_null_value_buf = kzalloc(DRBG_CTR_NULL_LEN + alignmask,
1700 GFP_KERNEL);
1701 if (!drbg->ctr_null_value_buf) {
1702 drbg_fini_sym_kernel(drbg);
1703 return -ENOMEM;
1704 }
1705 drbg->ctr_null_value = (u8 *)PTR_ALIGN(drbg->ctr_null_value_buf,
1706 alignmask + 1);
1707
1660 return 0; 1708 return 0;
1661} 1709}
1662 1710
@@ -1680,6 +1728,43 @@ static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *outval,
1680 crypto_cipher_encrypt_one(tfm, outval, in->buf); 1728 crypto_cipher_encrypt_one(tfm, outval, in->buf);
1681 return 0; 1729 return 0;
1682} 1730}
1731
1732static int drbg_kcapi_sym_ctr(struct drbg_state *drbg, u8 *outbuf, u32 outlen)
1733{
1734 struct scatterlist sg_in;
1735
1736 sg_init_one(&sg_in, drbg->ctr_null_value, DRBG_CTR_NULL_LEN);
1737
1738 while (outlen) {
1739 u32 cryptlen = min_t(u32, outlen, DRBG_CTR_NULL_LEN);
1740 struct scatterlist sg_out;
1741 int ret;
1742
1743 sg_init_one(&sg_out, outbuf, cryptlen);
1744 skcipher_request_set_crypt(drbg->ctr_req, &sg_in, &sg_out,
1745 cryptlen, drbg->V);
1746 ret = crypto_skcipher_encrypt(drbg->ctr_req);
1747 switch (ret) {
1748 case 0:
1749 break;
1750 case -EINPROGRESS:
1751 case -EBUSY:
1752 ret = wait_for_completion_interruptible(
1753 &drbg->ctr_completion);
1754 if (!ret && !drbg->ctr_async_err) {
1755 reinit_completion(&drbg->ctr_completion);
1756 break;
1757 }
1758 default:
1759 return ret;
1760 }
1761 init_completion(&drbg->ctr_completion);
1762
1763 outlen -= cryptlen;
1764 }
1765
1766 return 0;
1767}
1683#endif /* CONFIG_CRYPTO_DRBG_CTR */ 1768#endif /* CONFIG_CRYPTO_DRBG_CTR */
1684 1769
1685/*************************************************************** 1770/***************************************************************
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
index d961b2b16f55..b2fe15d1ceba 100644
--- a/include/crypto/drbg.h
+++ b/include/crypto/drbg.h
@@ -43,6 +43,7 @@
43#include <linux/random.h> 43#include <linux/random.h>
44#include <linux/scatterlist.h> 44#include <linux/scatterlist.h>
45#include <crypto/hash.h> 45#include <crypto/hash.h>
46#include <crypto/skcipher.h>
46#include <linux/module.h> 47#include <linux/module.h>
47#include <linux/crypto.h> 48#include <linux/crypto.h>
48#include <linux/slab.h> 49#include <linux/slab.h>
@@ -115,6 +116,14 @@ struct drbg_state {
115 /* some memory the DRBG can use for its operation */ 116 /* some memory the DRBG can use for its operation */
116 unsigned char *scratchpad; 117 unsigned char *scratchpad;
117 void *priv_data; /* Cipher handle */ 118 void *priv_data; /* Cipher handle */
119
120 struct crypto_skcipher *ctr_handle; /* CTR mode cipher handle */
121 struct skcipher_request *ctr_req; /* CTR mode request handle */
122 __u8 *ctr_null_value_buf; /* CTR mode unaligned buffer */
123 __u8 *ctr_null_value; /* CTR mode aligned zero buf */
124 struct completion ctr_completion; /* CTR mode async handler */
125 int ctr_async_err; /* CTR mode async error */
126
118 bool seeded; /* DRBG fully seeded? */ 127 bool seeded; /* DRBG fully seeded? */
119 bool pr; /* Prediction resistance enabled? */ 128 bool pr; /* Prediction resistance enabled? */
120 struct work_struct seed_work; /* asynchronous seeding support */ 129 struct work_struct seed_work; /* asynchronous seeding support */