|
@@ -370,13 +370,12 @@ static int drbg_fini_sym_kernel(struct drbg_state *drbg);
|
|
|
/* BCC function for CTR DRBG as defined in 10.4.3 */
|
|
|
static int drbg_ctr_bcc(struct drbg_state *drbg,
|
|
|
unsigned char *out, const unsigned char *key,
|
|
|
- struct drbg_string *in)
|
|
|
+ struct list_head *in)
|
|
|
{
|
|
|
- int ret = -EFAULT;
|
|
|
- struct drbg_string *curr = in;
|
|
|
- size_t inpos = curr->len;
|
|
|
- const unsigned char *pos = curr->buf;
|
|
|
+ int ret = 0;
|
|
|
+ struct drbg_string *curr = NULL;
|
|
|
struct drbg_string data;
|
|
|
+ short cnt = 0;
|
|
|
|
|
|
drbg_string_fill(&data, out, drbg_blocklen(drbg));
|
|
|
|
|
@@ -384,39 +383,29 @@ static int drbg_ctr_bcc(struct drbg_state *drbg,
|
|
|
memset(out, 0, drbg_blocklen(drbg));
|
|
|
|
|
|
/* 10.4.3 step 2 / 4 */
|
|
|
- while (inpos) {
|
|
|
- short cnt = 0;
|
|
|
+ list_for_each_entry(curr, in, list) {
|
|
|
+ const unsigned char *pos = curr->buf;
|
|
|
+ size_t len = curr->len;
|
|
|
/* 10.4.3 step 4.1 */
|
|
|
- for (cnt = 0; cnt < drbg_blocklen(drbg); cnt++) {
|
|
|
- out[cnt] ^= *pos;
|
|
|
- pos++; inpos--;
|
|
|
- /*
|
|
|
- * The following branch implements the linked list
|
|
|
- * iteration of drbg_string *in. If we are at the
|
|
|
- * end of the current list member, we have to start
|
|
|
- * using the next member if available. The inpos
|
|
|
- * value always points to the current byte and will
|
|
|
- * be zero if we have processed the last byte of
|
|
|
- * the last linked list member.
|
|
|
- */
|
|
|
- if (0 == inpos) {
|
|
|
- curr = curr->next;
|
|
|
- if (NULL != curr) {
|
|
|
- pos = curr->buf;
|
|
|
- inpos = curr->len;
|
|
|
- } else {
|
|
|
- inpos = 0;
|
|
|
- break;
|
|
|
- }
|
|
|
+ while (len) {
|
|
|
+ /* 10.4.3 step 4.2 */
|
|
|
+ if (drbg_blocklen(drbg) == cnt) {
|
|
|
+ cnt = 0;
|
|
|
+ ret = drbg_kcapi_sym(drbg, key, out, &data);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
}
|
|
|
+ out[cnt] ^= *pos;
|
|
|
+ pos++;
|
|
|
+ cnt++;
|
|
|
+ len--;
|
|
|
}
|
|
|
- /* 10.4.3 step 4.2 */
|
|
|
- ret = drbg_kcapi_sym(drbg, key, out, &data);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
- /* 10.4.3 step 2 */
|
|
|
}
|
|
|
- return 0;
|
|
|
+ /* 10.4.3 step 4.2 for last block */
|
|
|
+ if (cnt)
|
|
|
+ ret = drbg_kcapi_sym(drbg, key, out, &data);
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -461,13 +450,13 @@ static int drbg_ctr_bcc(struct drbg_state *drbg,
|
|
|
/* Derivation Function for CTR DRBG as defined in 10.4.2 */
|
|
|
static int drbg_ctr_df(struct drbg_state *drbg,
|
|
|
unsigned char *df_data, size_t bytes_to_return,
|
|
|
- struct drbg_string *addtl)
|
|
|
+ struct list_head *seedlist)
|
|
|
{
|
|
|
int ret = -EFAULT;
|
|
|
unsigned char L_N[8];
|
|
|
/* S3 is input */
|
|
|
struct drbg_string S1, S2, S4, cipherin;
|
|
|
- struct drbg_string *tempstr = addtl;
|
|
|
+ LIST_HEAD(bcc_list);
|
|
|
unsigned char *pad = df_data + drbg_statelen(drbg);
|
|
|
unsigned char *iv = pad + drbg_blocklen(drbg);
|
|
|
unsigned char *temp = iv + drbg_blocklen(drbg);
|
|
@@ -484,6 +473,7 @@ static int drbg_ctr_df(struct drbg_state *drbg,
|
|
|
unsigned char *X;
|
|
|
size_t generated_len = 0;
|
|
|
size_t inputlen = 0;
|
|
|
+ struct drbg_string *seed = NULL;
|
|
|
|
|
|
memset(pad, 0, drbg_blocklen(drbg));
|
|
|
memset(iv, 0, drbg_blocklen(drbg));
|
|
@@ -496,8 +486,8 @@ static int drbg_ctr_df(struct drbg_state *drbg,
|
|
|
return -EINVAL;
|
|
|
|
|
|
/* 10.4.2 step 2 -- calculate the entire length of all input data */
|
|
|
- for (; NULL != tempstr; tempstr = tempstr->next)
|
|
|
- inputlen += tempstr->len;
|
|
|
+ list_for_each_entry(seed, seedlist, list)
|
|
|
+ inputlen += seed->len;
|
|
|
drbg_int2byte(&L_N[0], inputlen, 4);
|
|
|
|
|
|
/* 10.4.2 step 3 */
|
|
@@ -518,20 +508,12 @@ static int drbg_ctr_df(struct drbg_state *drbg,
|
|
|
|
|
|
/* 10.4.2 step 4 -- first fill the linked list and then order it */
|
|
|
drbg_string_fill(&S1, iv, drbg_blocklen(drbg));
|
|
|
+ list_add_tail(&S1.list, &bcc_list);
|
|
|
drbg_string_fill(&S2, L_N, sizeof(L_N));
|
|
|
+ list_add_tail(&S2.list, &bcc_list);
|
|
|
+ list_splice_tail(seedlist, &bcc_list);
|
|
|
drbg_string_fill(&S4, pad, padlen);
|
|
|
- S1.next = &S2;
|
|
|
- S2.next = addtl;
|
|
|
-
|
|
|
- /*
|
|
|
- * Splice in addtl between S2 and S4 -- we place S4 at the end
|
|
|
- * of the input data chain. As this code is only triggered when
|
|
|
- * addtl is not NULL, no NULL checks are necessary.
|
|
|
- */
|
|
|
- tempstr = addtl;
|
|
|
- while (tempstr->next)
|
|
|
- tempstr = tempstr->next;
|
|
|
- tempstr->next = &S4;
|
|
|
+ list_add_tail(&S4.list, &bcc_list);
|
|
|
|
|
|
/* 10.4.2 step 9 */
|
|
|
while (templen < (drbg_keylen(drbg) + (drbg_blocklen(drbg)))) {
|
|
@@ -542,7 +524,7 @@ static int drbg_ctr_df(struct drbg_state *drbg,
|
|
|
*/
|
|
|
drbg_int2byte(iv, i, 4);
|
|
|
/* 10.4.2 step 9.2 -- BCC and concatenation with temp */
|
|
|
- ret = drbg_ctr_bcc(drbg, temp + templen, K, &S1);
|
|
|
+ ret = drbg_ctr_bcc(drbg, temp + templen, K, &bcc_list);
|
|
|
if (ret)
|
|
|
goto out;
|
|
|
/* 10.4.2 step 9.3 */
|
|
@@ -586,8 +568,8 @@ out:
|
|
|
}
|
|
|
|
|
|
/* update function of CTR DRBG as defined in 10.2.1.2 */
|
|
|
-static int drbg_ctr_update(struct drbg_state *drbg,
|
|
|
- struct drbg_string *addtl, int reseed)
|
|
|
+static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed,
|
|
|
+ int reseed)
|
|
|
{
|
|
|
int ret = -EFAULT;
|
|
|
/* 10.2.1.2 step 1 */
|
|
@@ -603,9 +585,8 @@ static int drbg_ctr_update(struct drbg_state *drbg,
|
|
|
memset(df_data, 0, drbg_statelen(drbg));
|
|
|
|
|
|
/* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
|
|
|
- if (addtl && 0 < addtl->len) {
|
|
|
- ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg),
|
|
|
- addtl);
|
|
|
+ if (seed) {
|
|
|
+ ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg), seed);
|
|
|
if (ret)
|
|
|
goto out;
|
|
|
}
|
|
@@ -665,8 +646,10 @@ static int drbg_ctr_generate(struct drbg_state *drbg,
|
|
|
|
|
|
/* 10.2.1.5.2 step 2 */
|
|
|
if (addtl && 0 < addtl->len) {
|
|
|
- addtl->next = NULL;
|
|
|
- ret = drbg_ctr_update(drbg, addtl, 1);
|
|
|
+ LIST_HEAD(addtllist);
|
|
|
+
|
|
|
+ list_add_tail(&addtl->list, &addtllist);
|
|
|
+ ret = drbg_ctr_update(drbg, &addtllist, 1);
|
|
|
if (ret)
|
|
|
return 0;
|
|
|
}
|
|
@@ -697,16 +680,21 @@ static int drbg_ctr_generate(struct drbg_state *drbg,
|
|
|
drbg_add_buf(drbg->V, drbg_blocklen(drbg), &prefix, 1);
|
|
|
}
|
|
|
|
|
|
- /* 10.2.1.5.2 step 6 */
|
|
|
- if (addtl)
|
|
|
- addtl->next = NULL;
|
|
|
/*
|
|
|
+ * 10.2.1.5.2 step 6
|
|
|
* The following call invokes the DF function again which could be
|
|
|
* optimized. In step 2, the "additional_input" after step 2 is the
|
|
|
* output of the DF function. If this result would be saved, the DF
|
|
|
* function would not need to be invoked again at this point.
|
|
|
*/
|
|
|
- ret = drbg_ctr_update(drbg, addtl, 1);
|
|
|
+ if (addtl && 0 < addtl->len) {
|
|
|
+ LIST_HEAD(addtllist);
|
|
|
+
|
|
|
+ list_add_tail(&addtl->list, &addtllist);
|
|
|
+ ret = drbg_ctr_update(drbg, &addtllist, 1);
|
|
|
+ } else {
|
|
|
+ ret = drbg_ctr_update(drbg, NULL, 1);
|
|
|
+ }
|
|
|
if (ret)
|
|
|
len = ret;
|
|
|
|
|
@@ -729,19 +717,21 @@ static struct drbg_state_ops drbg_ctr_ops = {
|
|
|
|
|
|
#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
|
|
|
static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
|
|
|
- unsigned char *outval, const struct drbg_string *in);
|
|
|
+ unsigned char *outval, const struct list_head *in);
|
|
|
static int drbg_init_hash_kernel(struct drbg_state *drbg);
|
|
|
static int drbg_fini_hash_kernel(struct drbg_state *drbg);
|
|
|
#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
|
|
|
|
|
|
#ifdef CONFIG_CRYPTO_DRBG_HMAC
|
|
|
/* update function of HMAC DRBG as defined in 10.1.2.2 */
|
|
|
-static int drbg_hmac_update(struct drbg_state *drbg,
|
|
|
- struct drbg_string *seed, int reseed)
|
|
|
+static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
|
|
|
+ int reseed)
|
|
|
{
|
|
|
int ret = -EFAULT;
|
|
|
int i = 0;
|
|
|
- struct drbg_string seed1, seed2, cipherin;
|
|
|
+ struct drbg_string seed1, seed2, vdata;
|
|
|
+ LIST_HEAD(seedlist);
|
|
|
+ LIST_HEAD(vdatalist);
|
|
|
|
|
|
if (!reseed) {
|
|
|
/* 10.1.2.3 step 2 */
|
|
@@ -750,13 +740,16 @@ static int drbg_hmac_update(struct drbg_state *drbg,
|
|
|
}
|
|
|
|
|
|
drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
|
|
|
+ list_add_tail(&seed1.list, &seedlist);
|
|
|
/* buffer of seed2 will be filled in for loop below with one byte */
|
|
|
drbg_string_fill(&seed2, NULL, 1);
|
|
|
- seed1.next = &seed2;
|
|
|
+ list_add_tail(&seed2.list, &seedlist);
|
|
|
/* input data of seed is allowed to be NULL at this point */
|
|
|
- seed2.next = seed;
|
|
|
+ if (seed)
|
|
|
+ list_splice_tail(seed, &seedlist);
|
|
|
|
|
|
- drbg_string_fill(&cipherin, drbg->V, drbg_statelen(drbg));
|
|
|
+ drbg_string_fill(&vdata, drbg->V, drbg_statelen(drbg));
|
|
|
+ list_add_tail(&vdata.list, &vdatalist);
|
|
|
for (i = 2; 0 < i; i--) {
|
|
|
/* first round uses 0x0, second 0x1 */
|
|
|
unsigned char prefix = DRBG_PREFIX0;
|
|
@@ -764,17 +757,17 @@ static int drbg_hmac_update(struct drbg_state *drbg,
|
|
|
prefix = DRBG_PREFIX1;
|
|
|
/* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
|
|
|
seed2.buf = &prefix;
|
|
|
- ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seed1);
|
|
|
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seedlist);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
/* 10.1.2.2 step 2 and 5 -- HMAC for V */
|
|
|
- ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &cipherin);
|
|
|
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &vdatalist);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
/* 10.1.2.2 step 3 */
|
|
|
- if (!seed || 0 == seed->len)
|
|
|
+ if (!seed)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -790,20 +783,24 @@ static int drbg_hmac_generate(struct drbg_state *drbg,
|
|
|
int len = 0;
|
|
|
int ret = 0;
|
|
|
struct drbg_string data;
|
|
|
+ LIST_HEAD(datalist);
|
|
|
|
|
|
/* 10.1.2.5 step 2 */
|
|
|
if (addtl && 0 < addtl->len) {
|
|
|
- addtl->next = NULL;
|
|
|
- ret = drbg_hmac_update(drbg, addtl, 1);
|
|
|
+ LIST_HEAD(addtllist);
|
|
|
+
|
|
|
+ list_add_tail(&addtl->list, &addtllist);
|
|
|
+ ret = drbg_hmac_update(drbg, &addtllist, 1);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
drbg_string_fill(&data, drbg->V, drbg_statelen(drbg));
|
|
|
+ list_add_tail(&data.list, &datalist);
|
|
|
while (len < buflen) {
|
|
|
unsigned int outlen = 0;
|
|
|
/* 10.1.2.5 step 4.1 */
|
|
|
- ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &data);
|
|
|
+ ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &datalist);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
|
|
@@ -817,9 +814,14 @@ static int drbg_hmac_generate(struct drbg_state *drbg,
|
|
|
}
|
|
|
|
|
|
/* 10.1.2.5 step 6 */
|
|
|
- if (addtl)
|
|
|
- addtl->next = NULL;
|
|
|
- ret = drbg_hmac_update(drbg, addtl, 1);
|
|
|
+ if (addtl && 0 < addtl->len) {
|
|
|
+ LIST_HEAD(addtllist);
|
|
|
+
|
|
|
+ list_add_tail(&addtl->list, &addtllist);
|
|
|
+ ret = drbg_hmac_update(drbg, &addtllist, 1);
|
|
|
+ } else {
|
|
|
+ ret = drbg_hmac_update(drbg, NULL, 1);
|
|
|
+ }
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
@@ -858,13 +860,13 @@ static struct drbg_state_ops drbg_hmac_ops = {
|
|
|
/* Derivation Function for Hash DRBG as defined in 10.4.1 */
|
|
|
static int drbg_hash_df(struct drbg_state *drbg,
|
|
|
unsigned char *outval, size_t outlen,
|
|
|
- struct drbg_string *entropy)
|
|
|
+ struct list_head *entropylist)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
size_t len = 0;
|
|
|
unsigned char input[5];
|
|
|
unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg);
|
|
|
- struct drbg_string data1;
|
|
|
+ struct drbg_string data;
|
|
|
|
|
|
memset(tmp, 0, drbg_blocklen(drbg));
|
|
|
|
|
@@ -873,14 +875,14 @@ static int drbg_hash_df(struct drbg_state *drbg,
|
|
|
drbg_int2byte(&input[1], (outlen * 8), 4);
|
|
|
|
|
|
/* 10.4.1 step 4.1 -- concatenation of data for input into hash */
|
|
|
- drbg_string_fill(&data1, input, 5);
|
|
|
- data1.next = entropy;
|
|
|
+ drbg_string_fill(&data, input, 5);
|
|
|
+ list_add(&data.list, entropylist);
|
|
|
|
|
|
/* 10.4.1 step 4 */
|
|
|
while (len < outlen) {
|
|
|
short blocklen = 0;
|
|
|
/* 10.4.1 step 4.1 */
|
|
|
- ret = drbg_kcapi_hash(drbg, NULL, tmp, &data1);
|
|
|
+ ret = drbg_kcapi_hash(drbg, NULL, tmp, entropylist);
|
|
|
if (ret)
|
|
|
goto out;
|
|
|
/* 10.4.1 step 4.2 */
|
|
@@ -897,11 +899,13 @@ out:
|
|
|
}
|
|
|
|
|
|
/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */
|
|
|
-static int drbg_hash_update(struct drbg_state *drbg, struct drbg_string *seed,
|
|
|
+static int drbg_hash_update(struct drbg_state *drbg, struct list_head *seed,
|
|
|
int reseed)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
struct drbg_string data1, data2;
|
|
|
+ LIST_HEAD(datalist);
|
|
|
+ LIST_HEAD(datalist2);
|
|
|
unsigned char *V = drbg->scratchpad;
|
|
|
unsigned char prefix = DRBG_PREFIX1;
|
|
|
|
|
@@ -913,26 +917,25 @@ static int drbg_hash_update(struct drbg_state *drbg, struct drbg_string *seed,
|
|
|
/* 10.1.1.3 step 1 */
|
|
|
memcpy(V, drbg->V, drbg_statelen(drbg));
|
|
|
drbg_string_fill(&data1, &prefix, 1);
|
|
|
+ list_add_tail(&data1.list, &datalist);
|
|
|
drbg_string_fill(&data2, V, drbg_statelen(drbg));
|
|
|
- data1.next = &data2;
|
|
|
- data2.next = seed;
|
|
|
- } else {
|
|
|
- drbg_string_fill(&data1, seed->buf, seed->len);
|
|
|
- data1.next = seed->next;
|
|
|
+ list_add_tail(&data2.list, &datalist);
|
|
|
}
|
|
|
+ list_splice_tail(seed, &datalist);
|
|
|
|
|
|
/* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
|
|
|
- ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &data1);
|
|
|
+ ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &datalist);
|
|
|
if (ret)
|
|
|
goto out;
|
|
|
|
|
|
/* 10.1.1.2 / 10.1.1.3 step 4 */
|
|
|
prefix = DRBG_PREFIX0;
|
|
|
drbg_string_fill(&data1, &prefix, 1);
|
|
|
+ list_add_tail(&data1.list, &datalist2);
|
|
|
drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
|
|
|
- data1.next = &data2;
|
|
|
+ list_add_tail(&data2.list, &datalist2);
|
|
|
/* 10.1.1.2 / 10.1.1.3 step 4 */
|
|
|
- ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &data1);
|
|
|
+ ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &datalist2);
|
|
|
|
|
|
out:
|
|
|
memset(drbg->scratchpad, 0, drbg_statelen(drbg));
|
|
@@ -945,7 +948,7 @@ static int drbg_hash_process_addtl(struct drbg_state *drbg,
|
|
|
{
|
|
|
int ret = 0;
|
|
|
struct drbg_string data1, data2;
|
|
|
- struct drbg_string *data3;
|
|
|
+ LIST_HEAD(datalist);
|
|
|
unsigned char prefix = DRBG_PREFIX2;
|
|
|
|
|
|
/* this is value w as per documentation */
|
|
@@ -958,11 +961,10 @@ static int drbg_hash_process_addtl(struct drbg_state *drbg,
|
|
|
/* 10.1.1.4 step 2a */
|
|
|
drbg_string_fill(&data1, &prefix, 1);
|
|
|
drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
|
|
|
- data3 = addtl;
|
|
|
- data1.next = &data2;
|
|
|
- data2.next = data3;
|
|
|
- data3->next = NULL;
|
|
|
- ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1);
|
|
|
+ list_add_tail(&data1.list, &datalist);
|
|
|
+ list_add_tail(&data2.list, &datalist);
|
|
|
+ list_add_tail(&addtl->list, &datalist);
|
|
|
+ ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
|
|
|
if (ret)
|
|
|
goto out;
|
|
|
|
|
@@ -985,6 +987,7 @@ static int drbg_hash_hashgen(struct drbg_state *drbg,
|
|
|
unsigned char *src = drbg->scratchpad;
|
|
|
unsigned char *dst = drbg->scratchpad + drbg_statelen(drbg);
|
|
|
struct drbg_string data;
|
|
|
+ LIST_HEAD(datalist);
|
|
|
unsigned char prefix = DRBG_PREFIX1;
|
|
|
|
|
|
memset(src, 0, drbg_statelen(drbg));
|
|
@@ -994,10 +997,11 @@ static int drbg_hash_hashgen(struct drbg_state *drbg,
|
|
|
memcpy(src, drbg->V, drbg_statelen(drbg));
|
|
|
|
|
|
drbg_string_fill(&data, src, drbg_statelen(drbg));
|
|
|
+ list_add_tail(&data.list, &datalist);
|
|
|
while (len < buflen) {
|
|
|
unsigned int outlen = 0;
|
|
|
/* 10.1.1.4 step hashgen 4.1 */
|
|
|
- ret = drbg_kcapi_hash(drbg, NULL, dst, &data);
|
|
|
+ ret = drbg_kcapi_hash(drbg, NULL, dst, &datalist);
|
|
|
if (ret) {
|
|
|
len = ret;
|
|
|
goto out;
|
|
@@ -1032,6 +1036,7 @@ static int drbg_hash_generate(struct drbg_state *drbg,
|
|
|
unsigned char req[8];
|
|
|
unsigned char prefix = DRBG_PREFIX3;
|
|
|
struct drbg_string data1, data2;
|
|
|
+ LIST_HEAD(datalist);
|
|
|
|
|
|
/* 10.1.1.4 step 2 */
|
|
|
ret = drbg_hash_process_addtl(drbg, addtl);
|
|
@@ -1044,9 +1049,10 @@ static int drbg_hash_generate(struct drbg_state *drbg,
|
|
|
memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
|
|
|
/* 10.1.1.4 step 4 */
|
|
|
drbg_string_fill(&data1, &prefix, 1);
|
|
|
+ list_add_tail(&data1.list, &datalist);
|
|
|
drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
|
|
|
- data1.next = &data2;
|
|
|
- ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &data1);
|
|
|
+ list_add_tail(&data2.list, &datalist);
|
|
|
+ ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
|
|
|
if (ret) {
|
|
|
len = ret;
|
|
|
goto out;
|
|
@@ -1099,6 +1105,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
|
|
|
unsigned char *entropy = NULL;
|
|
|
size_t entropylen = 0;
|
|
|
struct drbg_string data1;
|
|
|
+ LIST_HEAD(seedlist);
|
|
|
|
|
|
/* 9.1 / 9.2 / 9.3.1 step 3 */
|
|
|
if (pers && pers->len > (drbg_max_addtl(drbg))) {
|
|
@@ -1133,18 +1140,19 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
|
|
|
get_random_bytes(entropy, entropylen);
|
|
|
drbg_string_fill(&data1, entropy, entropylen);
|
|
|
}
|
|
|
+ list_add_tail(&data1.list, &seedlist);
|
|
|
|
|
|
/*
|
|
|
* concatenation of entropy with personalization str / addtl input)
|
|
|
* the variable pers is directly handed in by the caller, so check its
|
|
|
* contents whether it is appropriate
|
|
|
*/
|
|
|
- if (pers && pers->buf && 0 < pers->len && NULL == pers->next) {
|
|
|
- data1.next = pers;
|
|
|
+ if (pers && pers->buf && 0 < pers->len) {
|
|
|
+ list_add_tail(&pers->list, &seedlist);
|
|
|
pr_devel("DRBG: using personalization string\n");
|
|
|
}
|
|
|
|
|
|
- ret = drbg->d_ops->update(drbg, &data1, reseed);
|
|
|
+ ret = drbg->d_ops->update(drbg, &seedlist, reseed);
|
|
|
if (ret)
|
|
|
goto out;
|
|
|
|
|
@@ -1642,15 +1650,16 @@ static int drbg_fini_hash_kernel(struct drbg_state *drbg)
|
|
|
}
|
|
|
|
|
|
static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
|
|
|
- unsigned char *outval, const struct drbg_string *in)
|
|
|
+ unsigned char *outval, const struct list_head *in)
|
|
|
{
|
|
|
struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
|
|
|
+ struct drbg_string *input = NULL;
|
|
|
|
|
|
if (key)
|
|
|
crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
|
|
|
crypto_shash_init(&sdesc->shash);
|
|
|
- for (; NULL != in; in = in->next)
|
|
|
- crypto_shash_update(&sdesc->shash, in->buf, in->len);
|
|
|
+ list_for_each_entry(input, in, list)
|
|
|
+ crypto_shash_update(&sdesc->shash, input->buf, input->len);
|
|
|
return crypto_shash_final(&sdesc->shash, outval);
|
|
|
}
|
|
|
#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
|
|
@@ -1785,12 +1794,15 @@ static int drbg_kcapi_random(struct crypto_rng *tfm, u8 *rdata,
|
|
|
return drbg_generate_long(drbg, rdata, dlen, NULL);
|
|
|
} else {
|
|
|
struct drbg_gen *data = (struct drbg_gen *)rdata;
|
|
|
+ struct drbg_string addtl;
|
|
|
/* catch NULL pointer */
|
|
|
if (!data)
|
|
|
return 0;
|
|
|
drbg_set_testdata(drbg, data->test_data);
|
|
|
+ /* linked list variable is now local to allow modification */
|
|
|
+ drbg_string_fill(&addtl, data->addtl->buf, data->addtl->len);
|
|
|
return drbg_generate_long(drbg, data->outbuf, data->outlen,
|
|
|
- data->addtl);
|
|
|
+ &addtl);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1820,7 +1832,10 @@ static int drbg_kcapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
|
|
|
if (!data)
|
|
|
return drbg_instantiate(drbg, NULL, coreref, pr);
|
|
|
drbg_set_testdata(drbg, data->test_data);
|
|
|
- return drbg_instantiate(drbg, data->addtl, coreref, pr);
|
|
|
+ /* linked list variable is now local to allow modification */
|
|
|
+ drbg_string_fill(&seed_string, data->addtl->buf,
|
|
|
+ data->addtl->len);
|
|
|
+ return drbg_instantiate(drbg, &seed_string, coreref, pr);
|
|
|
}
|
|
|
}
|
|
|
|