Export drbg_ctr_df() derivative function to new module df_sp80090.
Signed-off-by: Harsh Jain <h.jain@amd.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
config CRYPTO_DRBG_CTR
bool "CTR_DRBG"
- select CRYPTO_AES
- select CRYPTO_CTR
+ select CRYPTO_DF80090A
help
CTR_DRBG variant as defined in NIST SP800-90A.
select CRYPTO_HMAC
select CRYPTO_SHA256
+config CRYPTO_DF80090A
+ tristate
+ select CRYPTO_AES
+ select CRYPTO_CTR
+
endmenu
menu "Userspace interface"
#
obj-$(CONFIG_CRYPTO_KDF800108_CTR) += kdf_sp800108.o
+obj-$(CONFIG_CRYPTO_DF80090A) += df_sp80090a.o
+
obj-$(CONFIG_CRYPTO_KRB5) += krb5/
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * NIST SP800-90A DRBG derivation function
+ *
+ * Copyright (C) 2014, Stephan Mueller <smueller@chronox.de>
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <crypto/df_sp80090a.h>
+#include <crypto/internal/drbg.h>
+
+static void drbg_kcapi_symsetkey(struct crypto_cipher *tfm,
+ const unsigned char *key,
+ u8 keylen);
+static int drbg_kcapi_sym(struct crypto_cipher *tfm, unsigned char *outval,
+ const struct drbg_string *in, u8 blocklen_bytes);
+
+static void drbg_kcapi_symsetkey(struct crypto_cipher *tfm,
+ const unsigned char *key, u8 keylen)
+{
+ crypto_cipher_setkey(tfm, key, keylen);
+}
+
+static int drbg_kcapi_sym(struct crypto_cipher *tfm, unsigned char *outval,
+ const struct drbg_string *in, u8 blocklen_bytes)
+{
+ /* there is only component in *in */
+ BUG_ON(in->len < blocklen_bytes);
+ crypto_cipher_encrypt_one(tfm, outval, in->buf);
+ return 0;
+}
+
+/* BCC function for CTR DRBG as defined in 10.4.3 */
+
+static int drbg_ctr_bcc(struct crypto_cipher *tfm,
+ unsigned char *out, const unsigned char *key,
+ struct list_head *in,
+ u8 blocklen_bytes,
+ u8 keylen)
+{
+ int ret = 0;
+ struct drbg_string *curr = NULL;
+ struct drbg_string data;
+ short cnt = 0;
+
+ drbg_string_fill(&data, out, blocklen_bytes);
+
+ /* 10.4.3 step 2 / 4 */
+ drbg_kcapi_symsetkey(tfm, key, keylen);
+ list_for_each_entry(curr, in, list) {
+ const unsigned char *pos = curr->buf;
+ size_t len = curr->len;
+ /* 10.4.3 step 4.1 */
+ while (len) {
+ /* 10.4.3 step 4.2 */
+ if (blocklen_bytes == cnt) {
+ cnt = 0;
+ ret = drbg_kcapi_sym(tfm, out, &data, blocklen_bytes);
+ if (ret)
+ return ret;
+ }
+ out[cnt] ^= *pos;
+ pos++;
+ cnt++;
+ len--;
+ }
+ }
+ /* 10.4.3 step 4.2 for last block */
+ if (cnt)
+ ret = drbg_kcapi_sym(tfm, out, &data, blocklen_bytes);
+
+ return ret;
+}
+
+/*
+ * scratchpad usage: drbg_ctr_update is interlinked with crypto_drbg_ctr_df
+ * (and drbg_ctr_bcc, but this function does not need any temporary buffers),
+ * the scratchpad is used as follows:
+ * drbg_ctr_update:
+ * temp
+ * start: drbg->scratchpad
+ * length: drbg_statelen(drbg) + drbg_blocklen(drbg)
+ * note: the cipher writing into this variable works
+ * blocklen-wise. Now, when the statelen is not a multiple
+ * of blocklen, the generateion loop below "spills over"
+ * by at most blocklen. Thus, we need to give sufficient
+ * memory.
+ * df_data
+ * start: drbg->scratchpad +
+ * drbg_statelen(drbg) + drbg_blocklen(drbg)
+ * length: drbg_statelen(drbg)
+ *
+ * crypto_drbg_ctr_df:
+ * pad
+ * start: df_data + drbg_statelen(drbg)
+ * length: drbg_blocklen(drbg)
+ * iv
+ * start: pad + drbg_blocklen(drbg)
+ * length: drbg_blocklen(drbg)
+ * temp
+ * start: iv + drbg_blocklen(drbg)
+ * length: drbg_satelen(drbg) + drbg_blocklen(drbg)
+ * note: temp is the buffer that the BCC function operates
+ * on. BCC operates blockwise. drbg_statelen(drbg)
+ * is sufficient when the DRBG state length is a multiple
+ * of the block size. For AES192 (and maybe other ciphers)
+ * this is not correct and the length for temp is
+ * insufficient (yes, that also means for such ciphers,
+ * the final output of all BCC rounds are truncated).
+ * Therefore, add drbg_blocklen(drbg) to cover all
+ * possibilities.
+ * refer to crypto_drbg_ctr_df_datalen() to get required length
+ */
+
+/* Derivation Function for CTR DRBG as defined in 10.4.2 */
+int crypto_drbg_ctr_df(struct crypto_cipher *tfm,
+ unsigned char *df_data, size_t bytes_to_return,
+ struct list_head *seedlist,
+ u8 blocklen_bytes,
+ u8 statelen)
+{
+ int ret = -EFAULT;
+ unsigned char L_N[8];
+ /* S3 is input */
+ struct drbg_string S1, S2, S4, cipherin;
+ LIST_HEAD(bcc_list);
+ unsigned char *pad = df_data + statelen;
+ unsigned char *iv = pad + blocklen_bytes;
+ unsigned char *temp = iv + blocklen_bytes;
+ size_t padlen = 0;
+ unsigned int templen = 0;
+ /* 10.4.2 step 7 */
+ unsigned int i = 0;
+ /* 10.4.2 step 8 */
+ const unsigned char *K = (unsigned char *)
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17"
+ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
+ unsigned char *X;
+ size_t generated_len = 0;
+ size_t inputlen = 0;
+ struct drbg_string *seed = NULL;
+ u8 keylen;
+
+ memset(pad, 0, blocklen_bytes);
+ memset(iv, 0, blocklen_bytes);
+ keylen = statelen - blocklen_bytes;
+ /* 10.4.2 step 1 is implicit as we work byte-wise */
+
+ /* 10.4.2 step 2 */
+ if ((512 / 8) < bytes_to_return)
+ return -EINVAL;
+
+ /* 10.4.2 step 2 -- calculate the entire length of all input data */
+ list_for_each_entry(seed, seedlist, list)
+ inputlen += seed->len;
+ drbg_cpu_to_be32(inputlen, &L_N[0]);
+
+ /* 10.4.2 step 3 */
+ drbg_cpu_to_be32(bytes_to_return, &L_N[4]);
+
+ /* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
+ padlen = (inputlen + sizeof(L_N) + 1) % (blocklen_bytes);
+ /* wrap the padlen appropriately */
+ if (padlen)
+ padlen = blocklen_bytes - padlen;
+ /*
+ * pad / padlen contains the 0x80 byte and the following zero bytes.
+ * As the calculated padlen value only covers the number of zero
+ * bytes, this value has to be incremented by one for the 0x80 byte.
+ */
+ padlen++;
+ pad[0] = 0x80;
+
+ /* 10.4.2 step 4 -- first fill the linked list and then order it */
+ drbg_string_fill(&S1, iv, blocklen_bytes);
+ 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);
+ list_add_tail(&S4.list, &bcc_list);
+
+ /* 10.4.2 step 9 */
+ while (templen < (keylen + (blocklen_bytes))) {
+ /*
+ * 10.4.2 step 9.1 - the padding is implicit as the buffer
+ * holds zeros after allocation -- even the increment of i
+ * is irrelevant as the increment remains within length of i
+ */
+ drbg_cpu_to_be32(i, iv);
+ /* 10.4.2 step 9.2 -- BCC and concatenation with temp */
+ ret = drbg_ctr_bcc(tfm, temp + templen, K, &bcc_list,
+ blocklen_bytes, keylen);
+ if (ret)
+ goto out;
+ /* 10.4.2 step 9.3 */
+ i++;
+ templen += blocklen_bytes;
+ }
+
+ /* 10.4.2 step 11 */
+ X = temp + (keylen);
+ drbg_string_fill(&cipherin, X, blocklen_bytes);
+
+ /* 10.4.2 step 12: overwriting of outval is implemented in next step */
+
+ /* 10.4.2 step 13 */
+ drbg_kcapi_symsetkey(tfm, temp, keylen);
+ while (generated_len < bytes_to_return) {
+ short blocklen = 0;
+ /*
+ * 10.4.2 step 13.1: the truncation of the key length is
+ * implicit as the key is only drbg_blocklen in size based on
+ * the implementation of the cipher function callback
+ */
+ ret = drbg_kcapi_sym(tfm, X, &cipherin, blocklen_bytes);
+ if (ret)
+ goto out;
+ blocklen = (blocklen_bytes <
+ (bytes_to_return - generated_len)) ?
+ blocklen_bytes :
+ (bytes_to_return - generated_len);
+ /* 10.4.2 step 13.2 and 14 */
+ memcpy(df_data + generated_len, X, blocklen);
+ generated_len += blocklen;
+ }
+
+ ret = 0;
+
+out:
+ memset(iv, 0, blocklen_bytes);
+ memset(temp, 0, statelen + blocklen_bytes);
+ memset(pad, 0, blocklen_bytes);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(crypto_drbg_ctr_df);
+
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Derivation Function conformant to SP800-90A");
*/
#include <crypto/drbg.h>
+#include <crypto/df_sp80090a.h>
#include <crypto/internal/cipher.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
return 0;
}
-/*
- * Convert an integer into a byte representation of this integer.
- * The byte representation is big-endian
- *
- * @val value to be converted
- * @buf buffer holding the converted integer -- caller must ensure that
- * buffer size is at least 32 bit
- */
-#if (defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR))
-static inline void drbg_cpu_to_be32(__u32 val, unsigned char *buf)
-{
- struct s {
- __be32 conv;
- };
- struct s *conversion = (struct s *) buf;
-
- conversion->conv = cpu_to_be32(val);
-}
-#endif /* defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_CTR) */
-
/******************************************************************
* CTR DRBG callback functions
******************************************************************/
MODULE_ALIAS_CRYPTO("drbg_pr_ctr_aes128");
MODULE_ALIAS_CRYPTO("drbg_nopr_ctr_aes128");
-static void drbg_kcapi_symsetkey(struct drbg_state *drbg,
- const unsigned char *key);
-static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *outval,
- const struct drbg_string *in);
static int drbg_init_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);
#define DRBG_OUTSCRATCHLEN 256
-/* 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 list_head *in)
-{
- int ret = 0;
- struct drbg_string *curr = NULL;
- struct drbg_string data;
- short cnt = 0;
-
- drbg_string_fill(&data, out, drbg_blocklen(drbg));
-
- /* 10.4.3 step 2 / 4 */
- drbg_kcapi_symsetkey(drbg, key);
- list_for_each_entry(curr, in, list) {
- const unsigned char *pos = curr->buf;
- size_t len = curr->len;
- /* 10.4.3 step 4.1 */
- while (len) {
- /* 10.4.3 step 4.2 */
- if (drbg_blocklen(drbg) == cnt) {
- cnt = 0;
- ret = drbg_kcapi_sym(drbg, out, &data);
- if (ret)
- return ret;
- }
- out[cnt] ^= *pos;
- pos++;
- cnt++;
- len--;
- }
- }
- /* 10.4.3 step 4.2 for last block */
- if (cnt)
- ret = drbg_kcapi_sym(drbg, out, &data);
-
- return ret;
-}
-
-/*
- * scratchpad usage: drbg_ctr_update is interlinked with drbg_ctr_df
- * (and drbg_ctr_bcc, but this function does not need any temporary buffers),
- * the scratchpad is used as follows:
- * drbg_ctr_update:
- * temp
- * start: drbg->scratchpad
- * length: drbg_statelen(drbg) + drbg_blocklen(drbg)
- * note: the cipher writing into this variable works
- * blocklen-wise. Now, when the statelen is not a multiple
- * of blocklen, the generateion loop below "spills over"
- * by at most blocklen. Thus, we need to give sufficient
- * memory.
- * df_data
- * start: drbg->scratchpad +
- * drbg_statelen(drbg) + drbg_blocklen(drbg)
- * length: drbg_statelen(drbg)
- *
- * drbg_ctr_df:
- * pad
- * start: df_data + drbg_statelen(drbg)
- * length: drbg_blocklen(drbg)
- * iv
- * start: pad + drbg_blocklen(drbg)
- * length: drbg_blocklen(drbg)
- * temp
- * start: iv + drbg_blocklen(drbg)
- * length: drbg_satelen(drbg) + drbg_blocklen(drbg)
- * note: temp is the buffer that the BCC function operates
- * on. BCC operates blockwise. drbg_statelen(drbg)
- * is sufficient when the DRBG state length is a multiple
- * of the block size. For AES192 (and maybe other ciphers)
- * this is not correct and the length for temp is
- * insufficient (yes, that also means for such ciphers,
- * the final output of all BCC rounds are truncated).
- * Therefore, add drbg_blocklen(drbg) to cover all
- * possibilities.
- */
-
-/* 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 list_head *seedlist)
{
- int ret = -EFAULT;
- unsigned char L_N[8];
- /* S3 is input */
- struct drbg_string S1, S2, S4, cipherin;
- 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);
- size_t padlen = 0;
- unsigned int templen = 0;
- /* 10.4.2 step 7 */
- unsigned int i = 0;
- /* 10.4.2 step 8 */
- const unsigned char *K = (unsigned char *)
- "\x00\x01\x02\x03\x04\x05\x06\x07"
- "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
- "\x10\x11\x12\x13\x14\x15\x16\x17"
- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
- 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));
-
- /* 10.4.2 step 1 is implicit as we work byte-wise */
-
- /* 10.4.2 step 2 */
- if ((512/8) < bytes_to_return)
- return -EINVAL;
-
- /* 10.4.2 step 2 -- calculate the entire length of all input data */
- list_for_each_entry(seed, seedlist, list)
- inputlen += seed->len;
- drbg_cpu_to_be32(inputlen, &L_N[0]);
-
- /* 10.4.2 step 3 */
- drbg_cpu_to_be32(bytes_to_return, &L_N[4]);
-
- /* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
- padlen = (inputlen + sizeof(L_N) + 1) % (drbg_blocklen(drbg));
- /* wrap the padlen appropriately */
- if (padlen)
- padlen = drbg_blocklen(drbg) - padlen;
- /*
- * pad / padlen contains the 0x80 byte and the following zero bytes.
- * As the calculated padlen value only covers the number of zero
- * bytes, this value has to be incremented by one for the 0x80 byte.
- */
- padlen++;
- pad[0] = 0x80;
-
- /* 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);
- list_add_tail(&S4.list, &bcc_list);
-
- /* 10.4.2 step 9 */
- while (templen < (drbg_keylen(drbg) + (drbg_blocklen(drbg)))) {
- /*
- * 10.4.2 step 9.1 - the padding is implicit as the buffer
- * holds zeros after allocation -- even the increment of i
- * is irrelevant as the increment remains within length of i
- */
- drbg_cpu_to_be32(i, iv);
- /* 10.4.2 step 9.2 -- BCC and concatenation with temp */
- ret = drbg_ctr_bcc(drbg, temp + templen, K, &bcc_list);
- if (ret)
- goto out;
- /* 10.4.2 step 9.3 */
- i++;
- templen += drbg_blocklen(drbg);
- }
-
- /* 10.4.2 step 11 */
- X = temp + (drbg_keylen(drbg));
- drbg_string_fill(&cipherin, X, drbg_blocklen(drbg));
-
- /* 10.4.2 step 12: overwriting of outval is implemented in next step */
-
- /* 10.4.2 step 13 */
- drbg_kcapi_symsetkey(drbg, temp);
- while (generated_len < bytes_to_return) {
- short blocklen = 0;
- /*
- * 10.4.2 step 13.1: the truncation of the key length is
- * implicit as the key is only drbg_blocklen in size based on
- * the implementation of the cipher function callback
- */
- ret = drbg_kcapi_sym(drbg, X, &cipherin);
- if (ret)
- goto out;
- blocklen = (drbg_blocklen(drbg) <
- (bytes_to_return - generated_len)) ?
- drbg_blocklen(drbg) :
- (bytes_to_return - generated_len);
- /* 10.4.2 step 13.2 and 14 */
- memcpy(df_data + generated_len, X, blocklen);
- generated_len += blocklen;
- }
-
- ret = 0;
-
-out:
- memset(iv, 0, drbg_blocklen(drbg));
- memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
- memset(pad, 0, drbg_blocklen(drbg));
- return ret;
+ return crypto_drbg_ctr_df(drbg->priv_data, df_data, drbg_statelen(drbg),
+ seedlist, drbg_blocklen(drbg), drbg_statelen(drbg));
}
/*
sb_size = 0;
else if (drbg->core->flags & DRBG_CTR)
sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg) + /* temp */
- drbg_statelen(drbg) + /* df_data */
- drbg_blocklen(drbg) + /* pad */
- drbg_blocklen(drbg) + /* iv */
- drbg_statelen(drbg) + drbg_blocklen(drbg); /* temp */
+ crypto_drbg_ctr_df_datalen(drbg_statelen(drbg),
+ drbg_blocklen(drbg));
else
sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg);
return alignmask;
}
-static void drbg_kcapi_symsetkey(struct drbg_state *drbg,
- const unsigned char *key)
-{
- struct crypto_cipher *tfm = drbg->priv_data;
-
- crypto_cipher_setkey(tfm, key, (drbg_keylen(drbg)));
-}
-
-static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *outval,
- const struct drbg_string *in)
-{
- struct crypto_cipher *tfm = drbg->priv_data;
-
- /* there is only component in *in */
- BUG_ON(in->len < drbg_blocklen(drbg));
- crypto_cipher_encrypt_one(tfm, outval, in->buf);
- return 0;
-}
-
static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
u8 *inbuf, u32 inlen,
u8 *outbuf, u32 outlen)
config CRYPTO_DEV_XILINX_TRNG
tristate "Support for Xilinx True Random Generator"
depends on ZYNQMP_FIRMWARE || COMPILE_TEST
+ select CRYPTO_DF80090A
select CRYPTO_RNG
select HW_RANDOM
help
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * Copyright Stephan Mueller <smueller@chronox.de>, 2014
+ */
+
+#ifndef _CRYPTO_DF80090A_H
+#define _CRYPTO_DF80090A_H
+
+#include <crypto/internal/cipher.h>
+
+static inline int crypto_drbg_ctr_df_datalen(u8 statelen, u8 blocklen)
+{
+ return statelen + /* df_data */
+ blocklen + /* pad */
+ blocklen + /* iv */
+ statelen + blocklen; /* temp */
+}
+
+int crypto_drbg_ctr_df(struct crypto_cipher *tfm,
+ unsigned char *df_data,
+ size_t bytes_to_return,
+ struct list_head *seedlist,
+ u8 blocklen_bytes,
+ u8 statelen);
+
+#endif /* _CRYPTO_DF80090A_H */
#include <linux/module.h>
#include <linux/crypto.h>
#include <linux/slab.h>
+#include <crypto/internal/drbg.h>
#include <crypto/internal/rng.h>
#include <crypto/rng.h>
#include <linux/fips.h>
#include <linux/list.h>
#include <linux/workqueue.h>
-/*
- * Concatenation Helper and string operation helper
- *
- * SP800-90A requires the concatenation of different data. To avoid copying
- * buffers around or allocate additional memory, the following data structure
- * is used to point to the original memory with its size. In addition, it
- * is used to build a linked list. The linked list defines the concatenation
- * of individual buffers. The order of memory block referenced in that
- * linked list determines the order of concatenation.
- */
-struct drbg_string {
- const unsigned char *buf;
- size_t len;
- struct list_head list;
-};
-
-static inline void drbg_string_fill(struct drbg_string *string,
- const unsigned char *buf, size_t len)
-{
- string->buf = buf;
- string->len = len;
- INIT_LIST_HEAD(&string->list);
-}
-
struct drbg_state;
typedef uint32_t drbg_flag_t;
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * NIST SP800-90A DRBG derivation function
+ *
+ * Copyright (C) 2014, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _INTERNAL_DRBG_H
+#define _INTERNAL_DRBG_H
+
+/*
+ * Convert an integer into a byte representation of this integer.
+ * The byte representation is big-endian
+ *
+ * @val value to be converted
+ * @buf buffer holding the converted integer -- caller must ensure that
+ * buffer size is at least 32 bit
+ */
+static inline void drbg_cpu_to_be32(__u32 val, unsigned char *buf)
+{
+ struct s {
+ __be32 conv;
+ };
+ struct s *conversion = (struct s *)buf;
+
+ conversion->conv = cpu_to_be32(val);
+}
+
+/*
+ * Concatenation Helper and string operation helper
+ *
+ * SP800-90A requires the concatenation of different data. To avoid copying
+ * buffers around or allocate additional memory, the following data structure
+ * is used to point to the original memory with its size. In addition, it
+ * is used to build a linked list. The linked list defines the concatenation
+ * of individual buffers. The order of memory block referenced in that
+ * linked list determines the order of concatenation.
+ */
+struct drbg_string {
+ const unsigned char *buf;
+ size_t len;
+ struct list_head list;
+};
+
+static inline void drbg_string_fill(struct drbg_string *string,
+ const unsigned char *buf, size_t len)
+{
+ string->buf = buf;
+ string->len = len;
+ INIT_LIST_HEAD(&string->list);
+}
+
+#endif //_INTERNAL_DRBG_H