Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a07203fb authored by Stephan Mueller's avatar Stephan Mueller Committed by Herbert Xu
Browse files

crypto: drbg - use full CTR AES for update



The CTR DRBG update function performs a full CTR AES operation including
the XOR with "plaintext" data. Hence, remove the XOR from the code and
use the CTR mode to do the XOR.

Signed-off-by: default avatarStephan Mueller <smueller@chronox.de>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 3cfc3b97
Loading
Loading
Loading
Loading
+13 −17
Original line number Original line Diff line number Diff line
@@ -258,7 +258,10 @@ static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *outval,
			  const struct drbg_string *in);
			  const struct drbg_string *in);
static int drbg_init_sym_kernel(struct drbg_state *drbg);
static int drbg_init_sym_kernel(struct drbg_state *drbg);
static int drbg_fini_sym_kernel(struct drbg_state *drbg);
static int drbg_fini_sym_kernel(struct drbg_state *drbg);
static int drbg_kcapi_sym_ctr(struct drbg_state *drbg, u8 *outbuf, u32 outlen);
static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
			      u8 *inbuf, u32 inbuflen,
			      u8 *outbuf, u32 outlen);
#define DRBG_CTR_NULL_LEN 128


/* BCC function for CTR DRBG as defined in 10.4.3 */
/* BCC function for CTR DRBG as defined in 10.4.3 */
static int drbg_ctr_bcc(struct drbg_state *drbg,
static int drbg_ctr_bcc(struct drbg_state *drbg,
@@ -481,8 +484,6 @@ static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed,
	unsigned char *temp = drbg->scratchpad;
	unsigned char *temp = drbg->scratchpad;
	unsigned char *df_data = drbg->scratchpad + drbg_statelen(drbg) +
	unsigned char *df_data = drbg->scratchpad + drbg_statelen(drbg) +
				 drbg_blocklen(drbg);
				 drbg_blocklen(drbg);
	unsigned char *temp_p, *df_data_p; /* pointer to iterate over buffers */
	unsigned int len = 0;


	if (3 > reseed)
	if (3 > reseed)
		memset(df_data, 0, drbg_statelen(drbg));
		memset(df_data, 0, drbg_statelen(drbg));
@@ -510,18 +511,11 @@ static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed,
			goto out;
			goto out;
	}
	}


	ret = drbg_kcapi_sym_ctr(drbg, temp, drbg_statelen(drbg));
	ret = drbg_kcapi_sym_ctr(drbg, df_data, drbg_statelen(drbg),
				 temp, drbg_statelen(drbg));
	if (ret)
	if (ret)
		return ret;
		return ret;


	/* 10.2.1.2 step 4 */
	temp_p = temp;
	df_data_p = df_data;
	for (len = 0; len < drbg_statelen(drbg); len++) {
		*temp_p ^= *df_data_p;
		df_data_p++; temp_p++;
	}

	/* 10.2.1.2 step 5 */
	/* 10.2.1.2 step 5 */
	memcpy(drbg->C, temp, drbg_keylen(drbg));
	memcpy(drbg->C, temp, drbg_keylen(drbg));
	ret = crypto_skcipher_setkey(drbg->ctr_handle, drbg->C,
	ret = crypto_skcipher_setkey(drbg->ctr_handle, drbg->C,
@@ -561,7 +555,8 @@ static int drbg_ctr_generate(struct drbg_state *drbg,
	}
	}


	/* 10.2.1.5.2 step 4.1 */
	/* 10.2.1.5.2 step 4.1 */
	ret = drbg_kcapi_sym_ctr(drbg, buf, len);
	ret = drbg_kcapi_sym_ctr(drbg, drbg->ctr_null_value, DRBG_CTR_NULL_LEN,
				 buf, len);
	if (ret)
	if (ret)
		return ret;
		return ret;


@@ -1657,7 +1652,6 @@ static void drbg_skcipher_cb(struct crypto_async_request *req, int error)
	complete(&drbg->ctr_completion);
	complete(&drbg->ctr_completion);
}
}


#define DRBG_CTR_NULL_LEN 128
static int drbg_init_sym_kernel(struct drbg_state *drbg)
static int drbg_init_sym_kernel(struct drbg_state *drbg)
{
{
	struct crypto_cipher *tfm;
	struct crypto_cipher *tfm;
@@ -1733,14 +1727,16 @@ static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *outval,
	return 0;
	return 0;
}
}


static int drbg_kcapi_sym_ctr(struct drbg_state *drbg, u8 *outbuf, u32 outlen)
static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
			      u8 *inbuf, u32 inlen,
			      u8 *outbuf, u32 outlen)
{
{
	struct scatterlist sg_in;
	struct scatterlist sg_in;


	sg_init_one(&sg_in, drbg->ctr_null_value, DRBG_CTR_NULL_LEN);
	sg_init_one(&sg_in, inbuf, inlen);


	while (outlen) {
	while (outlen) {
		u32 cryptlen = min_t(u32, outlen, DRBG_CTR_NULL_LEN);
		u32 cryptlen = min_t(u32, inlen, outlen);
		struct scatterlist sg_out;
		struct scatterlist sg_out;
		int ret;
		int ret;