aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Mueller <smueller@chronox.de>2016-11-29 03:45:04 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2016-11-30 06:46:44 -0500
commit5102981212454998d549273ff9847f19e97a1794 (patch)
tree2f1b0259571af794c5e1004d452b0f81966c646f
parentc8467f7a3620698bf3c22f0e199b550fb611a8ae (diff)
crypto: drbg - prevent invalid SG mappings
When using SGs, only heap memory (memory that is valid as per virt_addr_valid) is allowed to be referenced. The CTR DRBG used to reference the caller-provided memory directly in an SG. In case the caller provided stack memory pointers, the SG mapping is not considered to be valid. In some cases, this would even cause a paging fault. The change adds a new scratch buffer that is used unconditionally to catch the cases where the caller-provided buffer is not suitable for use in an SG. The crypto operation of the CTR DRBG produces its output with that scratch buffer and finally copies the content of the scratch buffer to the caller's buffer. The scratch buffer is allocated during allocation time of the CTR DRBG as its access is protected with the DRBG mutex. Signed-off-by: Stephan Mueller <smueller@chronox.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--crypto/drbg.c29
-rw-r--r--include/crypto/drbg.h2
2 files changed, 26 insertions, 5 deletions
diff --git a/crypto/drbg.c b/crypto/drbg.c
index fb33f7d3b052..053035b5c8f8 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -262,6 +262,7 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
262 u8 *inbuf, u32 inbuflen, 262 u8 *inbuf, u32 inbuflen,
263 u8 *outbuf, u32 outlen); 263 u8 *outbuf, u32 outlen);
264#define DRBG_CTR_NULL_LEN 128 264#define DRBG_CTR_NULL_LEN 128
265#define DRBG_OUTSCRATCHLEN DRBG_CTR_NULL_LEN
265 266
266/* BCC function for CTR DRBG as defined in 10.4.3 */ 267/* BCC function for CTR DRBG as defined in 10.4.3 */
267static int drbg_ctr_bcc(struct drbg_state *drbg, 268static int drbg_ctr_bcc(struct drbg_state *drbg,
@@ -1644,6 +1645,9 @@ static int drbg_fini_sym_kernel(struct drbg_state *drbg)
1644 kfree(drbg->ctr_null_value_buf); 1645 kfree(drbg->ctr_null_value_buf);
1645 drbg->ctr_null_value = NULL; 1646 drbg->ctr_null_value = NULL;
1646 1647
1648 kfree(drbg->outscratchpadbuf);
1649 drbg->outscratchpadbuf = NULL;
1650
1647 return 0; 1651 return 0;
1648} 1652}
1649 1653
@@ -1708,6 +1712,15 @@ static int drbg_init_sym_kernel(struct drbg_state *drbg)
1708 drbg->ctr_null_value = (u8 *)PTR_ALIGN(drbg->ctr_null_value_buf, 1712 drbg->ctr_null_value = (u8 *)PTR_ALIGN(drbg->ctr_null_value_buf,
1709 alignmask + 1); 1713 alignmask + 1);
1710 1714
1715 drbg->outscratchpadbuf = kmalloc(DRBG_OUTSCRATCHLEN + alignmask,
1716 GFP_KERNEL);
1717 if (!drbg->outscratchpadbuf) {
1718 drbg_fini_sym_kernel(drbg);
1719 return -ENOMEM;
1720 }
1721 drbg->outscratchpad = (u8 *)PTR_ALIGN(drbg->outscratchpadbuf,
1722 alignmask + 1);
1723
1711 return alignmask; 1724 return alignmask;
1712} 1725}
1713 1726
@@ -1737,15 +1750,16 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
1737 u8 *outbuf, u32 outlen) 1750 u8 *outbuf, u32 outlen)
1738{ 1751{
1739 struct scatterlist sg_in; 1752 struct scatterlist sg_in;
1753 int ret;
1740 1754
1741 sg_init_one(&sg_in, inbuf, inlen); 1755 sg_init_one(&sg_in, inbuf, inlen);
1742 1756
1743 while (outlen) { 1757 while (outlen) {
1744 u32 cryptlen = min_t(u32, inlen, outlen); 1758 u32 cryptlen = min3(inlen, outlen, (u32)DRBG_OUTSCRATCHLEN);
1745 struct scatterlist sg_out; 1759 struct scatterlist sg_out;
1746 int ret;
1747 1760
1748 sg_init_one(&sg_out, outbuf, cryptlen); 1761 /* Output buffer may not be valid for SGL, use scratchpad */
1762 sg_init_one(&sg_out, drbg->outscratchpad, cryptlen);
1749 skcipher_request_set_crypt(drbg->ctr_req, &sg_in, &sg_out, 1763 skcipher_request_set_crypt(drbg->ctr_req, &sg_in, &sg_out,
1750 cryptlen, drbg->V); 1764 cryptlen, drbg->V);
1751 ret = crypto_skcipher_encrypt(drbg->ctr_req); 1765 ret = crypto_skcipher_encrypt(drbg->ctr_req);
@@ -1761,14 +1775,19 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
1761 break; 1775 break;
1762 } 1776 }
1763 default: 1777 default:
1764 return ret; 1778 goto out;
1765 } 1779 }
1766 init_completion(&drbg->ctr_completion); 1780 init_completion(&drbg->ctr_completion);
1767 1781
1782 memcpy(outbuf, drbg->outscratchpad, cryptlen);
1783
1768 outlen -= cryptlen; 1784 outlen -= cryptlen;
1769 } 1785 }
1786 ret = 0;
1770 1787
1771 return 0; 1788out:
1789 memzero_explicit(drbg->outscratchpad, DRBG_OUTSCRATCHLEN);
1790 return ret;
1772} 1791}
1773#endif /* CONFIG_CRYPTO_DRBG_CTR */ 1792#endif /* CONFIG_CRYPTO_DRBG_CTR */
1774 1793
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
index 61580b19f9f6..22f884c97387 100644
--- a/include/crypto/drbg.h
+++ b/include/crypto/drbg.h
@@ -124,6 +124,8 @@ struct drbg_state {
124 struct skcipher_request *ctr_req; /* CTR mode request handle */ 124 struct skcipher_request *ctr_req; /* CTR mode request handle */
125 __u8 *ctr_null_value_buf; /* CTR mode unaligned buffer */ 125 __u8 *ctr_null_value_buf; /* CTR mode unaligned buffer */
126 __u8 *ctr_null_value; /* CTR mode aligned zero buf */ 126 __u8 *ctr_null_value; /* CTR mode aligned zero buf */
127 __u8 *outscratchpadbuf; /* CTR mode output scratchpad */
128 __u8 *outscratchpad; /* CTR mode aligned outbuf */
127 struct completion ctr_completion; /* CTR mode async handler */ 129 struct completion ctr_completion; /* CTR mode async handler */
128 int ctr_async_err; /* CTR mode async error */ 130 int ctr_async_err; /* CTR mode async error */
129 131